先看一下運作效果:

實作功能:背景定位+步行導航(可通過長按螢幕自定義終點,起點為定位點)
背景定位即當程式在背景時依舊執行定位功能,步行導航支援30米-50千米範圍内的導航
一 導入SDK并配置相關資訊
SDK下載下傳和AK建立詳見 Android Studio調用百度地圖(一):注冊成為百度地圖開發者并下載下傳SDK
SDK的導入具體可見百度地圖官網
這裡我要說的是實作定位和導航時需要注意的地方。
在proguard-rules.pro中添加
-dontoptimize
-ignorewarnings
-keeppackagenames com.baidu.**
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
-dontwarn com.baidu.**
-dontwarn com.baidu.navisdk.**
-dontwarn com.baidu.navi.**
-keep class com.baidu.** { *; }
-keep interface com.baidu.** { *; }
-keep class vi.com.gdi.** { *; }
-dontwarn com.google.protobuf.**
-keep class com.google.protobuf.** { *;}
-keep interface com.google.protobuf.** { *;}
在AndroidManifest.xml中添加
二 調用百度地圖API實作背景定位和步行導航
1 實作背景定位核心代碼
// 定位初始化
private void initLocationSDK() {
mClient = new LocationClient(this);
LocationClientOption mOption = new LocationClientOption();
mOption.setScanSpan(5000);
mOption.setCoorType("bd09ll");//設定坐标類型
mOption.setIsNeedAddress(true);//設定是否需要位址資訊,預設為無位址。
mOption.setOpenGps(true);
mClient.setLocOption(mOption);
mClient.registerLocationListener(myLocationListener);
}
//開始背景定位
private void settingLocInForeground() {
//android8.0及以上使用NotificationUtils
if (Build.VERSION.SDK_INT >= 26) {
mNotificationUtils = new NotificationUtils(this);
Notification.Builder builder2 = mNotificationUtils.getAndroidChannelNotification
("适配android 8限制背景定位功能", "正在背景定位");
notification = builder2.build();
} else {
//擷取一個Notification構造器
Notification.Builder builder = new Notification.Builder(DeleveryInfo.this);
Intent nfIntent = new Intent(DeleveryInfo.this, DeleveryInfo.class);
builder.setContentIntent(PendingIntent.
getActivity(DeleveryInfo.this, 0, nfIntent, 0)) // 設定PendingIntent
.setContentTitle("适配android 8限制背景定位功能") // 設定下拉清單裡的标題
// .setSmallIcon(R.drawable.ic_launcher) // 設定狀态欄内的小圖示
.setContentText("正在背景定位") // 設定上下文内容
.setWhen(System.currentTimeMillis()); // 設定該通知發生的時間
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.build(); // 擷取建構好的Notification
}
}
notification.defaults = Notification.DEFAULT_SOUND; //設定為預設的聲音
//開發者應用如果有背景定位需求,在退到背景的時候,為了保證定位可以在背景一直運作, 可以調用該函數,
//會将定位SDK的SERVICE設定成為前台服務,适配ANDROID 8背景無法定位問題,其他版本下也會提高定位程序存活率
//id - 為通知欄notifation設定唯一id,必須大于0
//notification - 開發者自定義通知
mClient.enableLocInForeground(1001, notification);// 調起前台定位
mClient.disableLocInForeground(true);// 關閉前台定位,同時移除通知欄
}
建立MyLocationListener監聽定位
class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
if (bdLocation == null || mMapView == null) {
return;
}
MyLocationData locData = new MyLocationData.Builder().accuracy(bdLocation.getRadius())
// 此處設定開發者擷取到的方向資訊,順時針0-360
.direction(bdLocation.getDirection()).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
// 設定定位資料
mBaiduMap.setMyLocationData(locData);
//地圖SDK處理
if (isFirstLoc) {
isFirstLoc = false;
LatLng ll = new LatLng(bdLocation.getLatitude(),
bdLocation.getLongitude());
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
LatLng point = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
OverlayOptions dotOption = new DotOptions().center(point).color(0xAAA9A9A9);
mBaiduMap.addOverlay(dotOption);
StringBuffer sb = new StringBuffer(256);
sb.append("Latitude:");
sb.append(bdLocation.getLatitude());
sb.append("Longitude");
Dest_BD09LL_Start = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
sb.append(bdLocation.getLongitude() + "\n");
if (null != mTextView) {
mTextView.append(sb.toString());
}
}
}
- 步行導航可信代碼
開啟步行導航很簡單 首先點選開始導航button初始化引擎,發起算路(如果引擎初始化成功),跳轉誘導界面開始步行導航(如果算路成功)
/**
* @Description: 引擎初始化
* @Author: LY
*/
private void startBikeNavi() {
Log.d(TAG, "startBikeNavi");
try {
WalkNavigateHelper.getInstance().initNaviEngine(this, new IWEngineInitListener() {
@Override
public void engineInitSuccess() {
Log.d(TAG, "BikeNavi engineInitSuccess");
routePlanWithWalkParam();
}
@Override
public void engineInitFail() {
Log.d(TAG, "BikeNavi engineInitFail");
BikeNavigateHelper.getInstance().unInitNaviEngine();
}
});
} catch (Exception e) {
Log.d(TAG, "startBikeNavi Exception");
e.printStackTrace();
}
}
/**
* @Description: 步行導航算路
* @Author: LY
*/
private void routePlanWithWalkParam() {
walkStartNode = new LatLng(Dest_BD09LL_Start.latitude, Dest_BD09LL_Start.longitude);
walkEndNode = new LatLng(Dest_BD09LL_End.latitude, Dest_BD09LL_End.longitude);
walkParam = new WalkNaviLaunchParam().stPt(walkStartNode).endPt(walkEndNode);
WalkNavigateHelper.getInstance().routePlanWithParams(walkParam, new IWRoutePlanListener() {
@Override
public void onRoutePlanStart() {
Log.d("Walk", "WalkNavi onRoutePlanStart");
}
@Override
public void onRoutePlanSuccess() {
Log.d("Walk", "onRoutePlanSuccess");
Intent intent = new Intent();
intent.setClass(DeleveryInfo.this, WNaviGuideActivity.class);
startActivity(intent);
}
@Override
public void onRoutePlanFail(WalkRoutePlanError error) {
Log.d("Walk", "WalkNavi onRoutePlanFail");
Toast.makeText(mNotificationUtils, "" + error, Toast.LENGTH_SHORT).show();
}
});
}
誘導界面 WNaviGuideActivity.java
public class WNaviGuideActivity extends Activity {
private final static String TAG = WNaviGuideActivity.class.getSimpleName();
private WalkNavigateHelper mNaviHelper;
private boolean isPreSPEAKtotal = true;
private String orient = "";
@Override
protected void onDestroy() {
super.onDestroy();
mNaviHelper.quit();
}
@Override
protected void onResume() {
super.onResume();
mNaviHelper.resume();
}
@Override
protected void onPause() {
super.onPause();
mNaviHelper.pause();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0x001) {
ChangeState();
handler.sendEmptyMessageDelayed(0x001, 45000);
}
if (msg.what == 0x002) {
handler.sendEmptyMessageDelayed(0x002, 30000);
}
if (msg.what == 0x003) {
startActivity(new Intent(WNaviGuideActivity.this, DeleveryInfo.class));
}
}
};
private void ChangeState() {
isPreSPEAKtotal = true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNaviHelper = WalkNavigateHelper.getInstance();
try {
View view = mNaviHelper.onCreate(WNaviGuideActivity.this);
if (view != null) {
setContentView(view);
}
} catch (Exception e) {
e.printStackTrace();
}
//設定步行導航狀态監聽
mNaviHelper.setWalkNaviStatusListener(new IWNaviStatusListener() {
@Override
public void onWalkNaviModeChange(int mode, WalkNaviModeSwitchListener listener) {
Log.d(TAG, "onWalkNaviModeChange : " + mode);
mNaviHelper.switchWalkNaviMode(WNaviGuideActivity.this, mode, listener);
}
/* @Description: 這個是在退出導航時自動調用的方法,在這裡要把對象進行釋放,避免空對象的産生
* @Author: LiY ue
*/
@Override
public void onNaviExit() {
Log.d(TAG, "onNaviExit");
handler.removeMessages(0x001);
handler.removeMessages(0x002);
handler.removeMessages(0x003);
}
});
/**
* 誘導文本回調
* @param s 誘導文本
* @param b 是否搶先播報
* @return
*/
mNaviHelper.setTTsPlayer(new IWTTSPlayer() {
@Override
public int playTTSText(final String s, boolean b) {
Log.d(TAG, "tts: " + s);
return 0;
}
});
boolean startResult = mNaviHelper.startWalkNavi(WNaviGuideActivity.this);
Log.e(TAG, "startWalkNavi result : " + startResult);
//設定路線指引監聽
mNaviHelper.setRouteGuidanceListener(this, new
IWRouteGuidanceListener() {
/**
* @Description: 誘導圖示更改方法回調
* @Author: LY
*/
@Override
public void onRouteGuideIconUpdate(Drawable icon) {
}
@Override
public void onRouteGuideKind(RouteGuideKind routeGuideKind) {
Log.d(TAG, "onRouteGuideKind: " + routeGuideKind);
if (routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_PassRoad_Left || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_PassRoad_Right || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_Right_PassRoad_Front || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_Right_PassRoad_UTurn)
if (routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Front || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Left || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Left_Front || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Right || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Right_Back || routeGuideKind == RouteGuideKind.NE_Maneuver_Kind_RightDiagonal_PassRoad_Right_Front)
}
/**
* @Description: 誘導資訊
*/
@Override
public void onRoadGuideTextUpdate(CharSequence charSequence, CharSequence
charSequence1) {
Log.d(TAG, "onRoadGuideTextUpdate charSequence=: " + charSequence + " charSequence1 = : " +
charSequence1);
orient = charSequence.toString() + charSequence1.toString();
}
/**
*
* @Description: 總剩餘距離回調
*/
@Override
public void onRemainDistanceUpdate(CharSequence charSequence) {
Log.d(TAG, "onRemainDistanceUpdate: charSequence = :" + charSequence);
if (isPreSPEAKtotal) {
}
}
/**
*
* @Description: 總剩餘時間回調
* @Author: LY
*/
@Override
public void onRemainTimeUpdate(CharSequence charSequence) {
Log.d(TAG, "onRemainTimeUpdate: charSequence = :" + charSequence);
if (isPreSPEAKtotal) {
isPreSPEAKtotal = false;
}
}
@Override
public void onGpsStatusChange(CharSequence charSequence, Drawable drawable) {
Log.d(TAG, "onGpsStatusChange: charSequence = :" + charSequence);
}
@Override
public void onRouteFarAway(CharSequence charSequence, Drawable drawable) {
Log.d(TAG, "onRouteFarAway: charSequence = :" + charSequence);
}
/**
* @Description: 偏航規劃中
*/
@Override
public void onRoutePlanYawing(CharSequence charSequence, Drawable drawable) {
Log.d(TAG, "onRoutePlanYawing: charSequence = :" + charSequence);
}
/**
*
* @Description: 重新算路成功
*/
@Override
public void onReRouteComplete() {
}
/**
*
* @Description: 到達目的地回調
*/
@Override
public void onArriveDest() {
handler.sendEmptyMessageDelayed(0x003, 6000);
}
@Override
public void onIndoorEnd(Message msg) {
}
@Override
public void onFinalEnd(Message msg) {
}
@Override
public void onVibrate() {
}
});
handler.sendEmptyMessage(0x001);
handler.sendEmptyMessage(0x002);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == ArCameraView.WALK_AR_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
Toast.makeText(WNaviGuideActivity.this, "沒有相機權限,請打開後重試", Toast.LENGTH_SHORT).show();
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mNaviHelper.startCameraAndSetMapView(WNaviGuideActivity.this);
}
}
}
}
Android Studio調用百度地圖(三):定位資料實時上傳到雲端資料庫
完整代碼下載下傳
BaiDuDemoTest