先看一下运行效果:
实现功能:后台定位+步行导航(可通过长按屏幕自定义终点,起点为定位点)
后台定位即当程序在后台时依旧执行定位功能,步行导航支持30米-50千米范围内的导航
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.** { *;}
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