超详细的Android百度地图开发:在APP上定位并显示出来

超详细的Android百度地图开发:在APP上定位并显示出来

一 写在前面

由于项目所需,我需要在手机APP中嵌入百度地图。参考的文档是《第一行代码》。其中的功能包括GPS/网络定位、地图的显示、搜索地点并进行导航(这个第一行代码没有,需要自己实现)。今天要实现的功能是,通过GPS/网络来进行定位,并以文本的形式1、将经纬度显示在APP上,2、具体的国省市区街道信息

效果如图所示:
在这里插入图片描述

二 注册百度开发者账户、申请API KEY

1、注册百度开发者账户:http://lbsyun.baidu.com/
在右上角按下登录,若有账号直接登录,反之注册。
在这里插入图片描述
2、进入百度地图Android定位SDK网页:http://lbsyun.baidu.com/index.php?title=android-locsdk

点击获取密钥
在这里插入图片描述
点击创建应用
在这里插入图片描述
如图操作:
在这里插入图片描述
其中上图第三步,如下图操作所示,将SHA1复制进入上图的两个SHA1空位。
在这里插入图片描述

提交之后,你就发现自己已经有一个应用啦。
在这里插入图片描述
3、下载百度地图SDK:http://lbsyun.baidu.com/index.php?title=android-locsdk/geosdk-android-download

点击去下载,网页会提示你需要下载哪些组件,由于我需要定位、地图、检索和导航功能,所以我选择了以下四项,点击开发包下载。
在这里插入图片描述
4.新建Android项目
在Android Studio中新建一个名为LBSTest的项目,包名应该会自动被命名为com.example.lbstest。注意本章中的代码最好在手机上运行,因为手机可以得到真实的位置数据,感受会更深刻。

5、将SDK文件放入相关的路径中
下载成功并解压之后,会发现如下文件,点击进入libs。
在这里插入图片描述
libs中含有以下文件:
在这里插入图片描述
将BaiduLBS_Android.jar文件放在LBSTest文件夹-》app-》libs文件夹下。
将其余文件夹(arm64-v8a、armeabi、armeabi-v7a、x86、x86_64)放在LBSTest-》src-》main-》jniLibs文件夹下
注意:jniLibs文件夹是原本没有的,需要自己创建。

6、重新构建项目
打开LBSTest项目,点击AS右上角的Sync Project with Gradle Files
在这里插入图片描述

现在,百度地图所需的基本配置已经完成啦,接下来让我们修改代码部分。

三、代码实现

1、AndroidManifest.xml文件
在这个文件,主要有两个功能:
(1)、声明些所需要用到的权限,比如手机GPS、网络的权限等。(位置:uses-permission)
(2)、将百度地图的API-KEY写进去,下面代码我没有将API-KEY写进去,需要读者自行将自己申请的APIKEY复制输入进去。(位置:meta-data)
(3)、定义百度地图的服务,用于定位。(位置:service)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.lbstest">



    <!-- 读写sd卡 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 写sd卡 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_GPS" />
    <!-- 获取精确gps位置 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- 获取粗略位置 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 允许程序访问额外的定位提供者指令获取模拟定位信息 -->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <!-- 网络链接 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 获取网络状态 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 更改wifi连状态 -->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <!-- 获取wifi状态 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--允许程序读写手机状态和身份-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
<!--
        <meta-data
            android:name="BaiduMobAd_STAT_ID"
            android:value="48ae76de3f" />
-->
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="填写刚申请的API_KEY" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--定义百度地图的服务,用于定位-->
        <service android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote">
        </service>
    </application>

</manifest>

2、activity_main.xml文件,即UI配置文件
一开始,我们就简单地用文本显示定位的经纬度,所以在UI文件中,我们只配置了一个TextView的控件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:id="@+id/position_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

3、MainActivity文件,即主活动文件
这个文件主要写了创建位置客户端,打开相应的权限,以及获取经纬度、字符串拼接并打印在TextView上。
一个需要注意的问题,如果是自己按照书本上敲的代码,出现红色的错误请不要慌。因为要么后面会有函数声明,要么没有import相应的库。后者的解决方法就是同时按下Alt+Enter,系统会自动帮你import相应的库,或者可以直接复制我下面的代码。

package com.example.lbstest;


import android.Manifest;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
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 java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {

    public LocationClient mLocationClient;
    //private MapView mapview;
    private TextView positionText;
    private StringBuilder currentPosition;

    public MainActivity() {
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLocationClient = new LocationClient((getApplicationContext()));
        mLocationClient.registerNotifyLocationListener(new MyLocationListener());
        setContentView(R.layout.activity_main);
        positionText = (TextView)findViewById(R.id.position_text_view);
        List<String> permissionList = new ArrayList<>();
        //如果没有启动下面权限,就询问用户让用户打开
        if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
        {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED)
        {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissionList.isEmpty()) {
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);
        }
        else {
            requestLocation();
        }
    }
    
/*初始化函数,并启动位置客户端LocationClient*/ 
    private void requestLocation() {
        initLocation();
        mLocationClient.start();
    }

/*初始化函数*/
    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        mLocationClient.setLocOption(option);
    }
    
/*只有同意打开相关权限才可以开启本程序*/
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(this, "必须同意所有权限才能使用本程序", Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                } else {
                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }

/*监听线程,获得当前的经纬度,并显示*/
    public class MyLocationListener implements BDLocationListener {
     @Override
     public void onReceiveLocation(final BDLocation location) {
        runOnUiThread(new Runnable() {
         @Override
         public void run() {
            currentPosition = new StringBuilder();
             currentPosition.append("纬度:").append(location.getLatitude()).append("\n");
            currentPosition.append("经度:").append(location.getLongitude()).append("\n");
            currentPosition.append("定位方式:");
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                currentPosition.append("GPS");
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                currentPosition.append("网络");
            }
            positionText.setText(currentPosition);
         }
     });
    }
  }


    public void onConnectHotSpotMessage(String s, int i) {

    }
	@Override
    protected void onDestroy(){
        super.onDestroy();
        mLocationClient.stop();
    }

}

4、选择定位方式:
聪明的读者已经注意到了,开头的截图显示的是网络定位,众所周知,网络定位精度在室外不如GPS定位,那我们怎么切换成GPS定位呢?
很简单,只要修改initLoation()函数。如下所示:

   private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
        mLocationClient.setLocOption(option);
    }

重新编译安装,然后走到室外,你会发现已经是GPS定位了。

5、具体位置显示
由于只看经纬度我们无法一下子知道自己的具体位置,所以引入具体位置显示。只需要修改MainActivity.java即可。
修改部分:
(1)、先是调用了setIsNeedAddress传入true,表示我们需要获取当前具体的位置。

 private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
       // option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
    }

(2)、调用getProvince、getCity等函数获得具体的位置信息。

    public class MyLocationListener implements BDLocationListener {
     @Override
     public void onReceiveLocation(final BDLocation location) {
        runOnUiThread(new Runnable() {
         @Override
         public void run() {
            currentPosition = new StringBuilder();
            currentPosition.append("纬度:").append(location.getLatitude()).append("\n");
            currentPosition.append("经度:").append(location.getLongitude()).append("\n");
            currentPosition.append("国家:").append(location.getCountry()).append("\n");
            currentPosition.append("省:").append(location.getProvince()).append("\n");
            currentPosition.append("市:").append(location.getCity()).append("\n");
            currentPosition.append("区:").append(location.getDistrict()).append("\n");
            currentPosition.append("街道:").append(location.getStreet()).append("\n");
            currentPosition.append("定位方式:");
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                currentPosition.append("GPS");
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                currentPosition.append("网络");
            }
            positionText.setText(currentPosition);
         }
     });
    }
  }

四、问题

1.错误:从内部类中访问本地变量location;需要被声明为最终类型。
解决方法:加上final
在这里插入图片描述2.Invalid process name remote in package com.example.lbstest: must have at least one
百度了一下INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,发现错误是出现在AndroidManifest.xml里,经检查发现:
在这里插入图片描述
红线处少了一个’:'

修改之后:
在这里插入图片描述
3.显示地图,但定位总是在北京。

当做完显示地图这个步骤之后,将地图移动到我的位置这一步似乎没有发挥其作用,即总是定位在北京。

检查之后,我觉得是这部分代码可能出现了一些问题。

位置:onReceiveLocation函数

书上这个函数的代码是没有开启线程的,这样的话就不会移动到我的当前位置,所以一直都是北京区域。

所以的话,在此函数增加一条线程代码即可,亲测有效的。^- ^

 public class MyLocationListener implements BDLocationListener {
            @Override
            public void onReceiveLocation(final BDLocation location) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (location.getLocType() == BDLocation.TypeGpsLocation || location.getLocType() == BDLocation.TypeNetWorkLocation) {
                            navigateTo(location);
                        }
                    }
                });
            }
    }

五、总结

那么这一小节就完成了,效果如开头的手机截图一样。

如果我的文章对你有帮助,欢迎关注,点赞,收藏,有问题可以评论。

  • 46
    点赞
  • 276
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
要实现百度地图定位和导航功能,需要进行以下几个步骤: 1. 在AndroidManifest.xml文件中添加相应的权限和申请百度地图SDK的Key。 2. 在布局文件中添加MapView控件,用于显示地图。 3. 在Java代码中初始化MapView控件和百度地图SDK,并进行定位和导航设置。 4. 通过百度地图SDK提供的定位功能,获取当前位置信息。 5. 通过百度地图SDK提供的导航功能,实现从当前位置到目的地的导航。 下面是一个简单的实现示例: 1. 在AndroidManifest.xml文件中添加以下权限和申请百度地图SDK的Key: ```xml <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="申请的百度地图SDK Key"/> ``` 2. 在布局文件中添加MapView控件: ```xml <com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="match_parent" android:layout_height="match_parent"/> ``` 3. 在Java代码中初始化MapView控件和百度地图SDK,并进行定位和导航设置: ```java public class MainActivity extends AppCompatActivity { private MapView mMapView; private BaiduMap mBaiduMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化MapView控件 mMapView = (MapView) findViewById(R.id.bmapView); mBaiduMap = mMapView.getMap(); // 初始化定位功能 LocationClient mLocationClient = new LocationClient(getApplicationContext()); MyLocationListener mMyLocationListener = new MyLocationListener(); mLocationClient.registerLocationListener(mMyLocationListener); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); option.setCoorType("bd09ll"); option.setScanSpan(1000); mLocationClient.setLocOption(option); mLocationClient.start(); // 初始化导航功能 BNOuterLogUtil.setLogSwitcher(true); BaiduNaviManager.getInstance().init(this, getExternalFilesDir(null).getAbsolutePath(), "app_name", new NaviInitListener() { @Override public void onAuthResult(int status, String msg) { if (status == 0) { Log.e("BaiduNaviManager", "百度导航鉴权成功"); } else { Log.e("BaiduNaviManager", "百度导航鉴权失败"); } } @Override public void initSuccess() { Log.e("BaiduNaviManager", "百度导航初始化成功"); } @Override public void initStart() { Log.e("BaiduNaviManager", "百度导航初始化开始"); } @Override public void initFailed() { Log.e("BaiduNaviManager", "百度导航初始化失败"); } }, null); } // 定位回调 private class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { if (location == null) { return; } MyLocationData locData = new MyLocationData.Builder() .accuracy(location.getRadius()) .direction(location.getDirection()) .latitude(location.getLatitude()) .longitude(location.getLongitude()) .build(); mBaiduMap.setMyLocationData(locData); } } } ``` 4. 通过百度地图SDK提供的定位功能,获取当前位置信息: ```java LocationClient mLocationClient = new LocationClient(getApplicationContext()); MyLocationListener mMyLocationListener = new MyLocationListener(); mLocationClient.registerLocationListener(mMyLocationListener); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); option.setCoorType("bd09ll"); option.setScanSpan(1000); mLocationClient.setLocOption(option); mLocationClient.start(); ``` 5. 通过百度地图SDK提供的导航功能,实现从当前位置到目的地的导航: ```java // 初始化导航功能 BNOuterLogUtil.setLogSwitcher(true); BaiduNaviManager.getInstance().init(this, getExternalFilesDir(null).getAbsolutePath(), "app_name", new NaviInitListener() { @Override public void onAuthResult(int status, String msg) { if (status == 0) { Log.e("BaiduNaviManager", "百度导航鉴权成功"); } else { Log.e("BaiduNaviManager", "百度导航鉴权失败"); } } @Override public void initSuccess() { Log.e("BaiduNaviManager", "百度导航初始化成功"); } @Override public void initStart() { Log.e("BaiduNaviManager", "百度导航初始化开始"); } @Override public void initFailed() { Log.e("BaiduNaviManager", "百度导航初始化失败"); } }, null); // 开始导航 String startNodeStr = "当前位置"; String endNodeStr = "目的地"; double startLatitude = 0.0; double startLongitude = 0.0; double endLatitude = 0.0; double endLongitude = 0.0; BNRoutePlanNode startNode = new BNRoutePlanNode(startLongitude, startLatitude, startNodeStr, null, BNRoutePlanNode.CoordinateType.BD09LL); BNRoutePlanNode endNode = new BNRoutePlanNode(endLongitude, endLatitude, endNodeStr, null, BNRoutePlanNode.CoordinateType.BD09LL); List<BNRoutePlanNode> list = new ArrayList<>(); list.add(startNode); list.add(endNode); BaiduNaviManager.getInstance().launchNavigator(this, list, 1, true, new DemoRoutePlanListener(startNode), null); ``` 注意:以上代码仅供参考,需要根据实际情况进行修改。同时,百度地图SDK也提供了详细开发文档和示例代码,可以帮助开发者更好地了解和使用其功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值