问题
最近项目需要实现一个这样的功能:点击位置信息,调用手机上安装的地图软件,进行导航(效果图见上图)
然后就是一顿百度.....
还好找到了解决办法,其实很简单,因为常用的地图软件开放的都有相关api,
我们再开发的过程中直接调用就可以了
下面的是代码,可以直接复制粘贴使用
注:底部弹框使用的是xPopup开源库,很好用,推荐给大家
工具类
作用:为了遍历手机上安装的所有软件,看看是否安装的有相关地图软件
public class isAvilibleUitls {
// 检索地图软件
public static boolean isAvilible(Context context, String packageName) {
//获取packagemanager
final PackageManager packageManager = context.getPackageManager();
//获取所有已安装程序的包信息
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
//用于存储所有已安装程序的包名
List<String> packageNames = new ArrayList<String>();
//从pinfo中将包名字逐一取出,压入pName list中
if (packageInfos != null) {
for (int i = 0; i < packageInfos.size(); i++) {
String packName = packageInfos.get(i).packageName;
packageNames.add(packName);
}
}
//判断packageNames中是否有目标程序的包名,有TRUE,没有FALSE
return packageNames.contains(packageName);
}
/**
* 指定地图
* 百度地图包名:com.baidu.BaiduMap
* <p>
* 高德地图包名:com.autonavi.minimap
* <p>
* 腾讯地图包名:com.tencent.map
* <p>
* 谷歌地图 com.google.android.apps.maps
*/
public List<String> mapsList() {
List<String> maps = new ArrayList<>();
maps.add("com.baidu.BaiduMap");
maps.add("com.autonavi.minimap");
maps.add("com.tencent.map");
return maps;
}
// 检索筛选后返回
public List<String> hasMap(Context context) {
List<String> mapsList = mapsList();
List<String> backList = new ArrayList<>();
for (int i = 0; i < mapsList.size(); i++) {
boolean avilible = isAvilible(context, mapsList.get(i));
if (avilible) {
backList.add(mapsList.get(i));
}
}
return backList;
}
}
弹框
public class BottomMapPopup extends BottomPopupView {
private Context context;
//注意:自定义弹窗本质是一个自定义View,但是只需重写一个参数的构造,其他的不要重写,所有的自定义弹窗都是这样。
public BottomMapPopup(@NonNull Context context) {
super(context);
this.context = context;
}
// 返回自定义弹窗的布局
@Override
protected int getImplLayoutId() {
return R.layout.open_map_bottom_popup;
}
// 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑
@Override
protected void onCreate() {
super.onCreate();
}
// 设置最大宽度,看需要而定
@Override
protected int getMaxWidth() {
return super.getMaxWidth();
}
// 设置最大高度,看需要而定
@Override
protected int getMaxHeight() {
return super.getMaxWidth();
}
// 设置自定义动画器,看需要而定
@Override
protected PopupAnimator getPopupAnimator() {
return super.getPopupAnimator();
}
/**
* 弹窗的宽度,用来动态设定当前弹窗的宽度,受getMaxWidth()限制
*
* @return
*/
protected int getPopupWidth() {
return 0;
}
/**
* 弹窗的高度,用来动态设定当前弹窗的高度,受getMaxHeight()限制
*
* @return
*/
protected int getPopupHeight() {
return 0;
}
}
弹框布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="horizontal"
android:padding="10dp">
<LinearLayout
android:id="@+id/lin_gaode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/gaodemap" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="高德地图" />
</LinearLayout>
<LinearLayout
android:id="@+id/lin_tencent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/tecentmap" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="腾讯地图" />
</LinearLayout>
<LinearLayout
android:id="@+id/lin_baidu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/baidumap" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="百度地图" />
</LinearLayout>
</LinearLayout>
重点来啦,点击事件的调用地图软件
public class HisLocationVo implements Serializable {
private String lat;
private String lon;
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
}
mBinding.tvTitle.setOnClickListener(view -> {
isBaidu = isAvilibleUitls.isAvilible(CircleDiscountStoreInfoActivity.this, "com.baidu.BaiduMap");
isGaode = isAvilibleUitls.isAvilible(CircleDiscountStoreInfoActivity.this, "com.autonavi.minimap");
isTencent = isAvilibleUitls.isAvilible(CircleDiscountStoreInfoActivity.this, "com.tencent.map");
if (!isBaidu && !isGaode && !isTencent) {
Toast.makeText(CircleDiscountStoreInfoActivity.this, "请安装地图软件", Toast.LENGTH_SHORT).show();
return;
}
if (merchantDetailVo == null) {
return;
}
if (TextUtils.isEmpty(merchantDetailVo.latitude) || TextUtils.isEmpty(merchantDetailVo.longitude)) {
ToastUtils.showShort("暂无详细地址");
return;
}
hisLocationBean = new HisLocationVo();
hisLocationBean.setLat(merchantDetailVo.latitude);
hisLocationBean.setLon(merchantDetailVo.longitude);
initMapBottom();
});
initMapBottom()方法
public void initMapBottom() {
BottomMapPopup customBottomPopup = new BottomMapPopup(CircleDiscountStoreInfoActivity.this);
BasePopupView xPopup = new XPopup.Builder(CircleDiscountStoreInfoActivity.this).setPopupCallback(new XPopupCallback() {
@Override
public void onCreated() {
LinearLayout lin_baidu = customBottomPopup.findViewById(R.id.lin_baidu);
LinearLayout lin_gaode = customBottomPopup.findViewById(R.id.lin_gaode);
LinearLayout lin_tencent = customBottomPopup.findViewById(R.id.lin_tencent);
if (isBaidu) {
lin_baidu.setVisibility(View.VISIBLE);
}
if (isGaode) {
lin_gaode.setVisibility(View.VISIBLE);
}
if (isTencent) {
lin_tencent.setVisibility(View.VISIBLE);
}
lin_baidu.setOnClickListener(view1 -> {
toBaidu(CircleDiscountStoreInfoActivity.this, hisLocationBean);
xPopup.dismiss();
});
lin_gaode.setOnClickListener(view12 -> {
toGaodeNavi(CircleDiscountStoreInfoActivity.this, hisLocationBean);
xPopup.dismiss();
});
lin_tencent.setOnClickListener(view13 -> {
toTencent(CircleDiscountStoreInfoActivity.this, hisLocationBean);
xPopup.dismiss();
});
}
@Override
public void beforeShow() {
}
@Override
public void onShow() {
}
@Override
public void onDismiss() {
}
@Override
public boolean onBackPressed() {
return false;
}
}).asCustom(customBottomPopup)
.show();
}
地图的跳转方法
// 百度地图
public void toBaidu(Context context, HisLocationVo bean) {
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("baidumap://map/geocoder?location=" + bean.getLat() + "," + bean.getLon()));
context.startActivity(intent);
}
// 高德地图
public void toGaodeNavi(Context context, HisLocationVo bean) {
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("androidamap://route?sourceApplication=appName&slat=&slon=&sname=我的位置&dlat=" + bean.getLat() + "&dlon=" + bean.getLon() + "&dname=目的地&dev=0&t=2"));
context.startActivity(intent);
}
// 腾讯地图
public void toTencent(Context context, HisLocationVo bean) {
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("qqmap://map/routeplan?type=drive&from=&fromcoord=&to=目的地&tocoord=" + bean.getLat() + "," + bean.getLon() + "&policy=0&referer=appName"));
context.startActivity(intent);
}