持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
Android跳转到第三方导航工具封装
现在基于位置的服务已经越来越完善,涉及到导航的功能也越来越多,常用的平台为谷歌地图,百度地图,高德地图。
开发中常用的导航分为两种类型,一种是内置地图SDK,调用SDK的导航方法,直接应用内导航,无需跳转到第三方的应用。缺点是如果该地图位置不齐全或者导航不精准,用户无法控制自己想要的哪一个厂商的导航功能。我们不可能集成所有的导航SDK。
另一种类型是判断用户手机中安装的地图软件,如果存在就弹窗让用户选择哪一个导航。目前微信的位置分享点击导航也是基于这个实现。如用户安装了百度地图,会弹出让用户选择腾讯地图还是百度地图,如果选择百度地图则会跳转到百度地图App的导航页面。
比较实用的方式是我们判断是否安装了导航。如果没有安装地图App,那么就跳转到百度的路径规划页面,如果安装了地图App,就跳转到指定的地图导航
比如百度地图的SDK导航
@Override
protected void init() {
initView();
//初始化百度地图的初始位置和状态
initBaiduMap();
initListener();
}
private void initListener() {
mIvBack.setOnClickListener(this);
mIvNavigationIcon.setOnClickListener(this);
}
//开启导航
private void navigate2Location() {
// 获取导航控制类
BikeNavigateHelper.getInstance().initNaviEngine(this, new IBEngineInitListener() {
@Override
public void engineInitSuccess() {
//骑行导航初始化成功之后的回调
LogUtil.w("骑行导航初始化成功");
//起终点位置
LatLng endPt = new LatLng(30.61548699999999, 114.254961);
//构造BikeNaviLaunchParam
//.vehicle(0)默认的普通骑行导航
BikeNaviLaunchParam param = new BikeNaviLaunchParam().stPt(mMyLatLng).endPt(endPt).vehicle(0);
//发起算路
BikeNavigateHelper.getInstance().routePlanWithParams(param, new IBRoutePlanListener() {
@Override
public void onRoutePlanStart() {
//执行算路开始的逻辑
}
@Override
public void onRoutePlanSuccess() {
//算路成功
//跳转至导航页面
Intent intent = new Intent(mActivity, BNaviGuideActivity.class);
startActivity(intent);
}
@Override
public void onRoutePlanFail(BikeRoutePlanError bikeRoutePlanError) {
//执行算路失败的逻辑
ToastUtils.makeText(mActivity, "规划导航路径失败:" + bikeRoutePlanError.toString());
}
});
}
@Override
public void engineInitFail() {
//骑行导航初始化失败之后的回调
LogUtil.w("骑行导航初始化失败");
}
});
}
//路线规划
private void initTTS() {
mRouteSearch = RoutePlanSearch.newInstance();
mRouteSearch.setOnGetRoutePlanResultListener(listener);
PlanNode stNode = PlanNode.withLocation(mMyLatLng);
PlanNode enNode = PlanNode.withLocation(new LatLng(30.61548699999999, 114.254961));
mRouteSearch.bikingSearch((new BikingRoutePlanOption())
.from(stNode)
.to(enNode));
}
private void initBaiduMap() {
//获取地图控制器
mBaiduMap = mMapView.getMap();
//隐藏比例按钮:隐藏缩放按钮
mMapView.showScaleControl(false);
mMapView.showZoomControls(false);
//改变缩放值到17
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(17));
//获取UI控制器,隐藏指南针:
UiSettings uiSettings = mBaiduMap.getUiSettings();
//不显示指南针
uiSettings.setCompassEnabled(false);
//设置自己的定位点的 模式-方向-icon
MyLocationConfiguration configuration = new MyLocationConfiguration(
MyLocationConfiguration.LocationMode.NORMAL, true, null
);
mBaiduMap.setMyLocationConfiguration(configuration);
mBaiduMap.setMyLocationEnabled(true);
//自己位置的定位初始化
mLocationClient = new LocationClient(this);
//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
//设置locationClientOption
mLocationClient.setLocOption(option);
//注册LocationListener监听器
MyLocationListener myLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
//开启地图定位图层
mLocationClient.start();
}
@Override
public void onNetworkConnectionChanged(boolean isConnected, NetWorkUtil.NetworkType networkType) {
}
@Override
protected void dataObserver() {
}
private void initView() {
mMapView = findViewById(R.id.bmapView);
mTvTitle = findViewById(R.id.tv_title);
mTvAddress = findViewById(R.id.tv_address);
mIvNavigationIcon = findViewById(R.id.iv_navigation_icon);
mIvBack = findViewById(R.id.iv_back);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.iv_back:
mActivity.finish();
break;
case R.id.iv_navigation_icon:
if (mMyLatLng != null) {
navigate2Location();
}
break;
}
}
/**
* 百度地图位置更新
*/
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
// LogUtil.e("获取到自己的位置信息:" + location.toString());
//mapView 销毁后不在处理新接收的位置
if (location == null || mMapView == null) {
return;
}
mMyLatLng = new LatLng(location.getLatitude(), location.getLongitude());
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(location.getDirection())
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
mBaiduMap.setMyLocationData(locData);
if (!isMovedMyLocation) {
//移动相机到指定的经纬度,只是第一次移动
isMovedMyLocation = true;
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(new LatLng(location.getLatitude(), location.getLongitude())).zoom(17.0f);
mBaiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
//初始化路线规划
initTTS();
}
//添加指定的覆盖物
// BitmapDescriptor searchBdA = BitmapDescriptorFactory.fromResource(R.drawable.ico_search);
// MarkerOptions option = new MarkerOptions().icon(searchBdA).position(latLng);
// mBaiduMap.addOverlay(option);
}
}
/**
* 路径规划的回调
*/
OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener() {
@Override
public void onGetWalkingRouteResult(WalkingRouteResult walkingRouteResult) {
}
@Override
public void onGetTransitRouteResult(TransitRouteResult transitRouteResult) {
}
@Override
public void onGetMassTransitRouteResult(MassTransitRouteResult massTransitRouteResult) {
}
@Override
public void onGetDrivingRouteResult(DrivingRouteResult drivingRouteResult) {
//创建DrivingRouteOverlay实例
DrivingRouteOverlay overlay = new DrivingRouteOverlay(mBaiduMap);
if (drivingRouteResult != null && drivingRouteResult.getRouteLines().size() > 0) {
//获取路径规划数据,(以返回的第一条路线为例)
//为DrivingRouteOverlay实例设置数据
overlay.setData(drivingRouteResult.getRouteLines().get(0));
//在地图上绘制DrivingRouteOverlay
overlay.addToMap();
}
}
@Override
public void onGetIndoorRouteResult(IndoorRouteResult indoorRouteResult) {
}
@Override
public void onGetBikingRouteResult(BikingRouteResult bikingRouteResult) {
if (bikingRouteResult != null && !CheckUtil.isEmpty(bikingRouteResult.getRouteLines())) {
BikingRouteOverlay overlay = new BikingRouteOverlay(mBaiduMap);
//获取路径规划数据,(以返回的第一条路线为例)
//为DrivingRouteOverlay实例设置数据
overlay.setData(bikingRouteResult.getRouteLines().get(0));
//在地图上绘制DrivingRouteOverlay
overlay.addToMap();
}
}
};
@Override
protected void onResume() {
mMapView.onResume();
super.onResume();
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mLocationClient.stop();
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
if (mRouteSearch != null)
mRouteSearch.destroy();
}
如果想直接进入导航:
//开启导航
private void navigate2Location() {
// 获取导航控制类
BikeNavigateHelper.getInstance().initNaviEngine(this, new IBEngineInitListener() {
@Override
public void engineInitSuccess() {
//骑行导航初始化成功之后的回调
LogUtil.w("骑行导航初始化成功");
//起终点位置
LatLng endPt = new LatLng(30.61548699999999, 114.254961);
//构造BikeNaviLaunchParam
//.vehicle(0)默认的普通骑行导航
BikeNaviLaunchParam param = new BikeNaviLaunchParam().stPt(mMyLatLng).endPt(endPt).vehicle(0);
//发起算路
BikeNavigateHelper.getInstance().routePlanWithParams(param, new IBRoutePlanListener() {
@Override
public void onRoutePlanStart() {
//执行算路开始的逻辑
}
@Override
public void onRoutePlanSuccess() {
//算路成功
//跳转至导航页面
Intent intent = new Intent(mActivity, BNaviGuideActivity.class);
startActivity(intent);
}
@Override
public void onRoutePlanFail(BikeRoutePlanError bikeRoutePlanError) {
//执行算路失败的逻辑
ToastUtils.makeText(mActivity, "规划导航路径失败:" + bikeRoutePlanError.toString());
}
});
}
@Override
public void engineInitFail() {
//骑行导航初始化失败之后的回调
LogUtil.w("骑行导航初始化失败");
}
});
}
另一种方式,跳转到地图App导航 地图APP判断和导航的工具类。
public class MapNavigationUtil {
public final static String BAIDU_PKG = "com.baidu.BaiduMap"; //百度地图的包名
public final static String GAODE_PKG = "com.autonavi.minimap";//高德地图的包名
public final static String GOOGLE_PKG = "com.google.android.apps.maps";//谷歌地图的包名
public static void openAMap(Context context, String endLat, String endLnt, String endAddress) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setPackage(GAODE_PKG);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("androidamap://route?sourceApplication=" + CommUtils.getString(R.string.app_name) +
// "&dname=" + endAddress +
"&dlat=" + endLat +
"&dlon=" + endLnt +
"&dev=0&t=4"
));
context.startActivity(intent);
}
public static void openBaidu(Context context, String endLat, String endLnt, String endAddress) {
Intent intent = new Intent();
intent.setData(Uri.parse("baidumap://map/direction?region=0" +
"&destination=" + endLat + "," + endLnt +
// "&destination=name:" + endAddress + "|latlng:" + endLat + "," + endLnt +
"&mode=walking"));
context.startActivity(intent);
}
public static void openGoogle(Context context, String endLat, String endLnt, String endAddress) {
Uri gmmIntentUri = Uri.parse("google.navigation:q="
+ endLat + "," + endLnt);
Intent intent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
intent.setPackage(GOOGLE_PKG);
context.startActivity(intent);
}
/**
* 检测地图应用是否安装
*/
public static boolean checkMapAppsIsExist(Context context, String packagename) {
PackageInfo packageInfo;
try {
packageInfo = context.getPackageManager().getPackageInfo(packagename, 0);
} catch (Exception e) {
packageInfo = null;
e.printStackTrace();
}
if (packageInfo == null) {
return false;
} else {
return true;
}
}
}
这里是集成了谷歌地图 百度地图 高德地图,在国内的话可以加上腾讯地图。类似的逻辑是一样的。设置对应的intent数据 跳转到指定App的指定页面
使用的方法如下:
private void showNavigationPopup() {
boolean googleMapEnable = MapNavigationUtil.checkMapAppsIsExist(mActivity, MapNavigationUtil.GOOGLE_PKG);
boolean baiduMapEnable = MapNavigationUtil.checkMapAppsIsExist(mActivity, MapNavigationUtil.BAIDU_PKG);
boolean aMapEnable = MapNavigationUtil.checkMapAppsIsExist(mActivity, MapNavigationUtil.GAODE_PKG);
//只要有一个地图安装了就可以使用弹窗指示导航
if (!googleMapEnable && !baiduMapEnable && !aMapEnable) {
ToastUtils.get().makeText(mActivity, "You don't have any map apps installed");
} else {
mPopupView = new PopupView(mActivity)
.moveUpToKeyboard(false)
.hasShadowBg(true)
.dismissOnTouchOutside(true)
.autoDismiss(true)
.popupType(PopupType.Bottom)
.asCustom(new BottomMerchantNavigationPopup(mActivity,
mMerchantDetail.latStr, mMerchantDetail.longStr, mMerchantDetail.merchant_address,
googleMapEnable, baiduMapEnable, aMapEnable));
if (mPopupView != null && !mPopupView.isShow()) {
mPopupView.show();
}
}
}
效果:
弹窗选择:
百度地图:
高德地图:
谷歌地图需要谷歌服务和科学上网才可以使用,测试也是可以用的,这里就不放图了。
关于谷歌地图的使用,谷歌位置服务,谷歌定位坐标系如何在百度地图上展示,后面有时间会专门出一期。
这一块都是SDK和一些API的调用,不涉及到定位,坐标系之类的转换。不算复杂,希望对大家有帮助!