第三方SDK:百度地圖(二)定位 + 鷹眼軌跡
阿新 • • 發佈:2019-01-19
#1 基礎地圖 + 基礎定位#
可以看到地圖的介面。
如圖:
Menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.cqc.baidumapdemo02.MainActivity" >
<item
android:id ="@+id/menu_normal"
android:showAsAction="never"
android:title="普通圖"/>
<item
android:id="@+id/menu_satellite"
android:showAsAction="never"
android:title="衛星圖"/>
<item
android:id="@+id/menu_none"
android:showAsAction="never"
android:title="空白圖" />
<item
android:id="@+id/menu_traffic"
android:showAsAction="never"
android:title="交通圖"/>
<item
android:id="@+id/menu_mylocation"
android:showAsAction="never"
android:title="定位我的位置"/>
<item
android:id="@+id/menu_location_normal"
android:showAsAction="never"
android:title="普通模式"/>
<item
android:id="@+id/menu_location_follow"
android:showAsAction="never"
android:title="跟隨模式"/>
<item
android:id="@+id/menu_location_compass"
android:showAsAction="never"
android:title="羅盤模式"/>
</menu>
MainActivity.java
package com.imooc.baidumap;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.imooc.baidumap.MyOrientationListener.OnOrientationListener;
public class MainActivity extends Activity
{
private MapView mMapView;
private BaiduMap mBaiduMap;
private Context context;
// 定位相關
private LocationClient mLocationClient;
private MyLocationListener mLocationListener;
private boolean isFirstIn = true;
private double mLatitude;
private double mLongtitude;
// 自定義定點陣圖標
private BitmapDescriptor mIconLocation;
private MyOrientationListener myOrientationListener;
private float mCurrentX;
private LocationMode mLocationMode;
// 覆蓋物相關
private BitmapDescriptor mMarker;
private RelativeLayout mMarkerLy;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
// 在使用SDK各元件之前初始化context資訊,傳入ApplicationContext
// 注意該方法要再setContentView方法之前實現
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY,
// WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
this.context = this;
initView();
// 初始化定位
initLocation();
initMarker();
mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener()
{
@Override
public boolean onMarkerClick(Marker marker)
{
Bundle extraInfo = marker.getExtraInfo();
Info info = (Info) extraInfo.getSerializable("info");
ImageView iv = (ImageView) mMarkerLy
.findViewById(R.id.id_info_img);
TextView distance = (TextView) mMarkerLy
.findViewById(R.id.id_info_distance);
TextView name = (TextView) mMarkerLy
.findViewById(R.id.id_info_name);
TextView zan = (TextView) mMarkerLy
.findViewById(R.id.id_info_zan);
iv.setImageResource(info.getImgId());
distance.setText(info.getDistance());
name.setText(info.getName());
zan.setText(info.getZan() + "");
InfoWindow infoWindow;
TextView tv = new TextView(context);
tv.setBackgroundResource(R.drawable.location_tips);
tv.setPadding(30, 20, 30, 50);
tv.setText(info.getName());
tv.setTextColor(Color.parseColor("#ffffff"));
final LatLng latLng = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(latLng);
p.y -= 47;
LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);
infoWindow = new InfoWindow(tv, ll,
new OnInfoWindowClickListener()
{
@Override
public void onInfoWindowClick()
{
mBaiduMap.hideInfoWindow();
}
});
mBaiduMap.showInfoWindow(infoWindow);
mMarkerLy.setVisibility(View.VISIBLE);
return true;
}
});
mBaiduMap.setOnMapClickListener(new OnMapClickListener()
{
@Override
public boolean onMapPoiClick(MapPoi arg0)
{
return false;
}
@Override
public void onMapClick(LatLng arg0)
{
mMarkerLy.setVisibility(View.GONE);
mBaiduMap.hideInfoWindow();
}
});
}
private void initMarker()
{
mMarker = BitmapDescriptorFactory.fromResource(R.drawable.maker);
mMarkerLy = (RelativeLayout) findViewById(R.id.id_maker_ly);
}
private void initLocation()
{
mLocationMode = LocationMode.NORMAL;
mLocationClient = new LocationClient(this);
mLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(mLocationListener);
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");
option.setIsNeedAddress(true);
option.setOpenGps(true);
option.setScanSpan(1000);
mLocationClient.setLocOption(option);
// 初始化圖示
mIconLocation = BitmapDescriptorFactory
.fromResource(R.drawable.navi_map_gps_locked);
myOrientationListener = new MyOrientationListener(context);
myOrientationListener
.setOnOrientationListener(new OnOrientationListener()
{
@Override
public void onOrientationChanged(float x)
{
mCurrentX = x;
}
});
}
private void initView()
{
mMapView = (MapView) findViewById(R.id.id_bmapView);
mBaiduMap = mMapView.getMap();
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);
}
@Override
protected void onResume()
{
super.onResume();
// 在activity執行onResume時執行mMapView. onResume (),實現地圖生命週期管理
mMapView.onResume();
}
@Override
protected void onStart()
{
super.onStart();
// 開啟定位
mBaiduMap.setMyLocationEnabled(true);
if (!mLocationClient.isStarted())
mLocationClient.start();
// 開啟方向感測器
myOrientationListener.start();
}
@Override
protected void onPause()
{
super.onPause();
// 在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命週期管理
mMapView.onPause();
}
@Override
protected void onStop()
{
super.onStop();
// 停止定位
mBaiduMap.setMyLocationEnabled(false);
mLocationClient.stop();
// 停止方向感測器
myOrientationListener.stop();
}
@Override
protected void onDestroy()
{
super.onDestroy();
// 在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命週期管理
mMapView.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.id_map_common:
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
break;
case R.id.id_map_site:
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
break;
case R.id.id_map_traffic:
if (mBaiduMap.isTrafficEnabled())
{
mBaiduMap.setTrafficEnabled(false);
item.setTitle("實時交通(off)");
} else
{
mBaiduMap.setTrafficEnabled(true);
item.setTitle("實時交通(on)");
}
break;
case R.id.id_map_location:
centerToMyLocation();
break;
case R.id.id_map_mode_common:
mLocationMode = LocationMode.NORMAL;
break;
case R.id.id_map_mode_following:
mLocationMode = LocationMode.FOLLOWING;
break;
case R.id.id_map_mode_compass:
mLocationMode = LocationMode.COMPASS;
break;
case R.id.id_add_overlay:
addOverlays(Info.infos);
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
/**
* 新增覆蓋物
*
* @param infos
*/
private void addOverlays(List<Info> infos)
{
mBaiduMap.clear();
LatLng latLng = null;
Marker marker = null;
OverlayOptions options;
for (Info info : infos)
{
// 經緯度
latLng = new LatLng(info.getLatitude(), info.getLongitude());
// 圖示
options = new MarkerOptions().position(latLng).icon(mMarker)
.zIndex(5);
marker = (Marker) mBaiduMap.addOverlay(options);
Bundle arg0 = new Bundle();
arg0.putSerializable("info", info);
marker.setExtraInfo(arg0);
}
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.setMapStatus(msu);
}
/**
* 定位到我的位置
*/
private void centerToMyLocation()
{
LatLng latLng = new LatLng(mLatitude, mLongtitude);
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.animateMapStatus(msu);
}
private class MyLocationListener implements BDLocationListener
{
@Override
public void onReceiveLocation(BDLocation location)
{
MyLocationData data = new MyLocationData.Builder()//
.direction(mCurrentX)//
.accuracy(location.getRadius())//
.latitude(location.getLatitude())//
.longitude(location.getLongitude())//
.build();
mBaiduMap.setMyLocationData(data);
// 設定自定義圖示
MyLocationConfiguration config = new MyLocationConfiguration(
mLocationMode, true, mIconLocation);
mBaiduMap.setMyLocationConfigeration(config);
// 更新經緯度
mLatitude = location.getLatitude();
mLongtitude = location.getLongitude();
if (isFirstIn)
{
LatLng latLng = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.animateMapStatus(msu);
isFirstIn = false;
Toast.makeText(context, location.getAddrStr(),
Toast.LENGTH_SHORT).show();
}
}
}
}
2 只使用基礎定位
步驟:
1 獲取金鑰:key
2 環境配置
3 獲取位置
1 建立LocationClient 和 BDLocationListener物件
2 給LocationClient 物件設定引數,和註冊監聽
3 開啟定位
1 獲取金鑰:key
2 環境配置
步驟:
1 先下載基礎定位SDK
2 配置jar+so檔案
3 配置AndoridManifest.xml(網路許可權 + 定位service + 定位key)
先下載基礎定位:
只需要下載這一個即可,不需要其他的,不需要基礎地圖(這次只定位,不看圖)
配置jar+so檔案
將jar檔案放入libs資料夾中,在project結構中,src/main下建立jniLibs資料夾,將各架構下的so檔案放入其中。見下圖:
配置AndoridManifest.xml(網路許可權 + 定位service + 定位key)
網路許可權:
<!-- 這個許可權用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 這個許可權用於訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用於訪問wifi網路資訊,wifi資訊會用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 這個許可權用於獲取wifi的獲取許可權,wifi資訊會用來進行網路定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用於讀取手機當前的狀態-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 寫入擴充套件儲存,向擴充套件卡寫入資料,用於寫入離線定位資料-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 訪問網路,網路定位需要上網-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- SD卡讀取許可權,使用者寫入離線定位資料-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
宣告定位service:
<!--宣告定位service-->
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
</service>
有的版本指定service,所以要看清下載的sdk+demo,最好複製demo的
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
<intent-filter>
<action android:name="com.baidu.location.service_v2.2">
</action>
</intent-filter>
</service>
定位key:
<!--百度地圖:定位功能key: tpiB1a5OmkkFz4ZYSRyByp9bqHYjML4D-->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="tpiB1a5OmkkFz4ZYSRyByp9bqHYjML4D"/>
3 獲取位置
步驟:
1 建立LocationClient物件
2 設定引數
3 設定監聽(可以在監聽中獲取地址)
建立LocationClient物件
mLocationClient = new LocationClient(getApplicationContext()); //宣告LocationClient類
設定引數
private void initLocation() {
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//可選,預設高精度,設定定位模式,高精度,低功耗,僅裝置
option.setCoorType("bd09ll");//可選,預設gcj02,設定返回的定位結果座標系
int span = 0;
option.setScanSpan(span);//可選,預設0,即僅定位一次,設定發起定位請求的間隔需要大於等於1000ms才是有效的
option.setIsNeedAddress(true);//可選,設定是否需要地址資訊,預設不需要
option.setOpenGps(true);//可選,預設false,設定是否使用gps
option.setLocationNotify(true);//可選,預設false,設定是否當gps有效時按照1S1次頻率輸出GPS結果
option.setIsNeedLocationDescribe(true);//可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似於“在北京天安門附近”
option.setIsNeedLocationPoiList(true);//可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
option.setIgnoreKillProcess(false);//可選,預設true,定位SDK內部是一個SERVICE,並放到了獨立程序,設定是否在stop的時候殺死這個程序,預設不殺死
option.SetIgnoreCacheException(false);//可選,預設false,設定是否收集CRASH資訊,預設收集
option.setEnableSimulateGps(false);//可選,預設false,設定是否需要過濾gps模擬結果,預設需要
mLocationClient.setLocOption(option);
}
設定監聽(可以在監聽中獲取地址)
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//Receive Location
StringBuffer sb = new StringBuffer(256);
sb.append("time : ");
sb.append(location.getTime());
sb.append("\nerror code : ");
sb.append(location.getLocType());
sb.append("\nlatitude : ");
sb.append(location.getLatitude());
sb.append("\nlontitude : ");
sb.append(location.getLongitude());
sb.append("\nradius : ");
sb.append(location.getRadius());
if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位結果
sb.append("\nspeed : ");
sb.append(location.getSpeed());// 單位:公里每小時
sb.append("\nsatellite : ");
sb.append(location.getSatelliteNumber());
sb.append("\nheight : ");
sb.append(location.getAltitude());// 單位:米
sb.append("\ndirection : ");
sb.append(location.getDirection());// 單位度
sb.append("\naddr : ");
sb.append(location.getAddrStr());
sb.append("\ndescribe : ");
sb.append("gps定位成功");
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 網路定位結果
sb.append("\naddr : ");
sb.append(location.getAddrStr());
//運營商資訊
sb.append("\noperationers : ");
sb.append(location.getOperators());
sb.append("\ndescribe : ");
sb.append("網路定位成功");
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 離線定位結果
sb.append("\ndescribe : ");
sb.append("離線定位成功,離線定位結果也是有效的");
} else if (location.getLocType() == BDLocation.TypeServerError) {
sb.append("\ndescribe : ");
sb.append("服務端網路定位失敗,可以反饋IMEI號和大體定位時間到[email protected],會有人追查原因");
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
sb.append("\ndescribe : ");
sb.append("網路不同導致定位失敗,請檢查網路是否通暢");
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
sb.append("\ndescribe : ");
sb.append("無法獲取有效定位依據導致定位失敗,一般是由於手機的原因,處於飛航模式下一般會造成這種結果,可以試著重啟手機");
}
sb.append("\nlocationdescribe : ");
sb.append(location.getLocationDescribe());// 位置語義化資訊
List<Poi> list = location.getPoiList();// POI資料
if (list != null) {
sb.append("\npoilist size = : ");
sb.append(list.size());
for (Poi p : list) {
sb.append("\npoi= : ");
sb.append(p.getId() + " " + p.getName() + " " + p.getRank());
}
}
//獲取定位資訊
Log.i("BaiduLocationApiDem", sb.toString());
//獲取位置資訊
Log.i("BaiduLocationApiDem", location.getAddrStr());
}
}
開啟定位
mLocationClient = new LocationClient(getApplicationContext()); //宣告LocationClient類
mLocationClient.registerLocationListener(myListener); //註冊監聽函式
initLocation();//設定引數
mLocationClient.start();
沒有呼叫initLocation()方法時,列印的log為:
呼叫initLocation()方法時,列印的log為:
注意:按照百度基本定位SDK文件說明,定位用的一個API_key是不可以對應多個包名的,但我在實際測試中發現定位的一個key,可以對應多個包名(各位可以嘗試修改本demo的applicationId,會發現log仍然有地址)。但是僅限定位,基本地圖就不可以。
原始碼:
每隔10秒定位一次,並獲取定位資訊
只是多了一個條件:“每隔10秒定位一次”,這次放在了service中,其他都一樣.下圖是每隔10秒的定位資料,10秒有點短,但基本獲取到了資料,也基本是間隔10秒。
public class LocationService extends Service {
private int seconds = 10;
public LocationClient mLocationClient = null;
public BDLocationListener myListener = new MyLocationListener();
private Timer timer;
private TimerTask mTask;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mLocationClient = new LocationClient(LocationService.this); //宣告LocationClient類
mLocationClient.registerLocationListener(myListener); //註冊監聽函式
initLocation();//設定引數
mLocationClient.start();
//以上程式碼是copy官網文件
//設定1秒後,每個seconds秒定位一次,定位資訊log中有列印
timer = new Timer();
timer.schedule(task, 1000,seconds * 1000);//1秒後,每個seconds秒定位一次。
}
TimerTask task = new TimerTask() {
@Override
public void run() {
mLocationClient.start();
mLocationClient.requestLocation();
}
};
@Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
mLocationClient.unRegisterLocationListener(myListener);
}
//這個方法是copy官網文件
private void initLocation() {
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//可選,預設高精度,設定定位模式,高精度,低功耗,僅裝置
option.setCoorType("bd09ll");//可選,預設gcj02,設定返回的定位結果座標系
int span = 0;
option.setScanSpan(span);//可選,預設0,即僅定位一次,設定發起定位請求的間隔需要大於等於1000ms才是有效的
option.setIsNeedAddress(true);//可選,設定是否需要地址資訊,預設不需要
option.setOpenGps(true);//可選,預設false,設定是否使用gps
option.setLocationNotify(true);//可選,預設false,設定是否當GPS有效時按照1S/1次頻率輸出GPS結果
option.setIsNeedLocationDescribe(true);//可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似於“在北京天安門附近”
option.setIsNeedLocationPoiList(true);//可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
option.setIgnoreKillProcess(false);//可選,預設true,定位SDK內部是一個SERVICE,並放到了獨立程序,設定是否在stop的時候殺死這個程序,預設不殺死
option.SetIgnoreCacheException(false);//可選,預設false,設定是否收集CRASH資訊,預設收集
option.setEnableSimulateGps(false);//可選,預設false,設定是否需要過濾GPS模擬結果,預設需要
mLocationClient.setLocOption(option);
}
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//Receive Location
StringBuffer sb = new StringBuffer(256);
sb.append("time : ");
sb.append(location.getTime());
sb.append("\nerror code : ");
sb.append(location.getLocType());
sb.append("\nlatitude : ");
sb.append(location.getLatitude());
sb.append("\nlontitude : ");
sb.append(location.getLongitude());
sb.append("\nradius : ");
sb.append(location.getRadius());
if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位結果
sb.append("\nspeed : ");
sb.append(location.getSpeed());// 單位:公里每小時
sb.append("\nsatellite : ");
sb.append(location.getSatelliteNumber());
sb.append("\nheight : ");
sb.append(location.getAltitude());// 單位:米
sb.append("\ndirection : ");
sb.append(location.getDirection());// 單位度
sb.append("\naddr : ");
sb.append(location.getAddrStr());
sb.append("\ndescribe : ");
sb.append("gps定位成功");
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 網路定位結果
sb.append("\naddr : ");
sb.append(location.getAddrStr());
//運營商資訊
sb.append("\noperationers : ");
sb.append(location.getOperators());
sb.append("\ndescribe : ");
sb.append("網路定位成功");
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 離線定位結果
sb.append("\ndescribe : ");
sb.append("離線定位成