11特色开发-百度地图

申请API Key

  1. 打开这个连接 http://lbsyun.baidu.com/apiconsole/key,申请百度地图开发者平台服务,点击我同意,创建应用
    11特色开发-百度地图_第1张图片
    创建应用界面.png
  2. 这个发布版SHA1和开发板SHA1是什么意思呢?这个是打包程序时所用签名文件的SHA1指纹,通过ANdroid Studio可以查看到,打开任何一个项目点击右边工具栏的Gradle-->项目名-->:app-->Tasks-->android


    11特色开发-百度地图_第2张图片
    内置的Tasks.png
  3. 双击这个signingReport文件


    11特色开发-百度地图_第3张图片
    signingReport.png
    • 其中的F2:F8:68:53:5F:1C:D9:1E:68:6A:14:4B:24:91:DD:37:95:58:A1:9B就是需要的SHA1指纹了,要注意的是现在使用的是debug.keystore文件生成的指纹,这是Android自动生成用于测试的签名文件,当应用程序发布时还要创建一个正式的签名文件,
    • 在定义的项目中(com.example.lbstest)
      11特色开发-百度地图_第4张图片
      创建数字签名.png

      11特色开发-百度地图_第5张图片
      新创建一个.png

      11特色开发-百度地图_第6张图片
      创建.png

      记住这个密码,这就创建成功了
      要得到它的指纹,就在cmd中输入以下命令
      keytool -list -v -keystore <签名文件路径>
      11特色开发-百度地图_第7张图片
      获取到签名.png
  4. 现在得到的SHA1指纹实际上是一个开发版的SHA1指纹,不过现在没有发布版的SHA1,这两个值填写一样就可以了,最后还有一个包名,就是上一步中的包名


    完整信息.png
  5. 提交后,应用就创建成功了


    11特色开发-百度地图_第8张图片
    查看已创建的应用.png
    • 其中的AK就是申请到的API Key,有了它就可以进行后续的LBS开发工作了

使用百度定位

项目就是lsbtest,包名是com.example.lbstest,就是上面定义的那个

  1. 准备LBS SDKhttp://lbsyun.baidu.com/index.php?title=sdk/download&action#selected=location_all
    • 将百度LBS开发平台上的SDK下载下来,点击开发包


      11特色开发-百度地图_第9张图片
      下载SDK界面.png
  2. 下载后解压,其中有一个libs目录,这里面的内容就是我们需要的


    11特色开发-百度地图_第10张图片
    压缩包libs目录下的文件.png
    • BaiduLBS_Android.jar这个文件是java层要使用的,其他子目录下的so文件是Native层要用的,
    • so文件是C/C++语言写的,因为百度都封装好了,直接使用就可以了
  3. 首先看一下当前项目目录,
    • 其中app模块下的libs目录就是用来存放Jar包的,把BaiduLBS_Android.jar复制到这里


      11特色开发-百度地图_第11张图片
      把jar包复制到这里.png
    • 接下来右击src/main目录,进行目录jniLibs目录,把压缩包里的所有目录直接复制到这里


      11特色开发-百度地图_第12张图片
      把so文件放置到jniLibs目录中.png
  4. 这个时候在配置文件中build.gradle中,会默认有这一行代码
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    ...
}
  • 这将表示将所有以jar结尾的文件添加到当前的项目中,但是这个时候还没有引用成功,重启这个Android Studio
  • 这个时候libs目录下的jar包就会多出一个向右的箭头,这就表示引用成功了


    11特色开发-百度地图_第13张图片
    jar包引用成功.png

确定自己的位置的经纬度

  1. 修改activity_main.xml中的代码



    

  • 这里只有一个TextView控件,用于显示当前位置的经纬度
  1. 修改AndroidManifest.xml文件中的代码



    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
    
    
        
            
                
                
            
        


        
        

        
        
        

    



  • 首先添加了好多权限,这在百度的开发文档中可以看到
  • meta-data标签中value就是前面申请的API Key值
  • 还有一个service标签,这个是百度带的
  1. 修改MainActivity中的代码
package com.example.lbstest;

public class MainActivity extends AppCompatActivity {

    // 声明这个对象,该对象初始化需传入Context类型参数。推荐使用getApplicationConext()方法获取全进程有效的Context。
    public LocationClient mLocationClient;
    private MyLocationListener myListener = new MyLocationListener();
    private TextView positionText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 进行初始化
        mLocationClient = new LocationClient(getApplicationContext());
        // 注册监听函数
        mLocationClient.registerLocationListener(myListener);
        setContentView(R.layout.activity_main);
        // 获取到控件
        positionText = (TextView)findViewById(R.id.position_text_view);
        // 关于权限的操作
        List 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的start()方法,便可发起定位请求
    public void requestLocation(){
        mLocationClient.start();
    }

    // 动态添加权限
    @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{
        //此处的BDLocation为定位结果信息类,通过它的各种get方法可获取定位相关的全部结果
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            StringBuilder currentPosition = new StringBuilder();
            currentPosition.append("纬度:").append(bdLocation.getLatitude()).append("\n");
            currentPosition.append("经度:").append(bdLocation.getLongitude()).append("\n");
            currentPosition.append("定位方式:");
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation){
                currentPosition.append("GPS");
            }else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                currentPosition.append("网络");
            }
            // 获取完信息添加到控件中
            positionText.setText(currentPosition);
        }
    }

}

  • 在onCreate()方法中,首先创建了一个LocationClient的实例,在构建函数中接收一个Context参数,这里调用了getApplicationContext()方法获取全局的Context参数传入,然后调用LocationClient的registerLocationListener()方法来注册一个监听器,当获取位置的时候,就会回调这个定位监听器
  • 关于运行时权限,这里使用了集合,只有当所有权限都被用户同意了,才会调用 requestLocation()方法开始地理位置定位
  • 在 requestLocation()方法中,就只是的调用了LocationClient的start()方法就能开始定位了
  • 在这个监听器中,获取到了详细的位置信息,然后设置到textView控件中
  1. 运行程序,运行权限就可以看到


    11特色开发-百度地图_第14张图片
    地理位置定位.png
  2. 不过,在默认的情况下,LocationClient的start()方法只会定位一次,但是如果我们此时移·动的话,怎么样才能更新位置呢?这个时候就得修改MainActivity中的代码了
...


  //调用LocationClient的start()方法,便可发起定位请求
    public void requestLocation(){
        initLocation();
        mLocationClient.start();
    }

    // 创建一个LocationClientOption对象,调用方法来设置跟新的间隔
    private void initLocation(){
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        mLocationClient.setLocOption(option);
    }

    // 活动被销毁的时候要调用stop()方法来停止定位
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
    }

    ...

  • 别的代码保持不变,增加了一个initLocation()方法,在这个方法中创建一个LocationClientOption对象,用这个对象的setScanSpan()方法来设置更新的间隔,这里这是5000,表示每个5秒就会更新当前的位置
  • 注意:在这个活动销毁的时候,调用LocationClient的stop()方法来停止定位,不然程序会在后台不停的进行定位,从而消耗手机的电量

选择定位模式

上面是使用网络定位的方式,这次使用精准度高的GPS定位

  1. 首先GPS定位功能要由用户主动的启动才行,进入设置-->位置信息


    11特色开发-百度地图_第15张图片
    选择定位模式.png
  2. 开启GPS定位功能后,可以在initLocation()方法中对百度LBS SDK的定位模式指定,Hinght_Accuracy、Battery_Saving和Device_Sensors,其中Hinght_Accuracy模式标识高精确度,在GPS信号正常的情况下优先使用,在无法使用GPS信号的时候就使用网络定位,Battery_Saving表示节点模式,只会使用网络进行定位,Device_Sensors表示传感模式,只会使用GPS定位,其中的Hinght_Accuracy是默认的定位,不需要修改任何代码,把手机拿到室外就可以了,这个时候手机就会自动切换到GPS定位模式了
  3. 当然了也可以强制指定为GPS定位,修改MainActivity中的代码
    private void initLocation(){
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        // 强制使用GPS定位的模式
        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
        mLocationClient.setLocOption(option);
    }

  • 这里调用了setLocationMode()方法将定位模式指定为传感器模式,就只能使用GPS来进行定位了,重新运行程序,到室外去,运行程序
  • 11特色开发-百度地图_第16张图片
    GPS定位的结果.png

看得懂的位置信息

当然了,获取经度和纬度对于小白来说也是看不懂的,这个时候就得获取直观的位置信息,

  1. 当然了,这些百度LBS SDK都支持,只需要进行一些简单的接口调用就可以了,修改MainActiviyt中的代码
package com.example.lbstest;


public class MainActivity extends AppCompatActivity {

    ...
    
    private void initLocation(){
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        // 开启详细信息
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
    }

    // 监听函数
    public class MyLocationListener implements BDLocationListener{
        //此处的BDLocation为定位结果信息类,通过它的各种get方法可获取定位相关的全部结果
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            StringBuilder currentPosition = new StringBuilder();
            currentPosition.append("纬度:").append(bdLocation.getLatitude()).append("\n");
            currentPosition.append("经度:").append(bdLocation.getLongitude()).append("\n");
            currentPosition.append("国家:").append(bdLocation.getCountry()).append("\n");
            currentPosition.append("省:").append(bdLocation.getProvince()).append("\n");
            currentPosition.append("市:").append(bdLocation.getCity()).append("\n");
            currentPosition.append("区:").append(bdLocation.getDistrict()).append("\n");
            currentPosition.append("街道:").append(bdLocation.getStreet()).append("\n");
            currentPosition.append("定位方式:");
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation){
                currentPosition.append("GPS");
            }else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                currentPosition.append("网络");
            }
            // 获取完信息添加到控件中
            positionText.setText(currentPosition);
        }
    }

}

  • 首先在initLocation()方法中调用了LocationClientOption的setIsNeedAddress(),设置了true,这就表示要获取当前位置的详细信息
  • 在onReceiveLocation()方法中,通过get方法获取详细的位置,要注意的是:获取地址信息一定要需要用网络,即使设置了Device_Sensors这个模式,也会自动开启网络定位功能


    11特色开发-百度地图_第17张图片
    当前位置的详细地址.png
  • 这样就获取了当前位置的详细信息了

让地图显示出来

  1. 直接在上一个的基础上进行修改,在activity_main.xml中



    

    
    

  • 首先在TextView控件中设置visibility="gone",就是让它在界面上隐藏
  • 放置了一个新的MapView控件,这个是百度自定义的,直接使用就可以了,设置为充满屏幕
  1. 接下来修改MainActivity中的代码
package com.example.lbstest;


public class MainActivity extends AppCompatActivity {

    // 声明这个对象,该对象初始化需传入Context类型参数。推荐使用getApplicationConext()方法获取全进程有效的Context。
    public LocationClient mLocationClient;
    private MyLocationListener myListener = new MyLocationListener();
    private TextView positionText;

    // 
    private MapView mapView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 进行初始化
        mLocationClient = new LocationClient(getApplicationContext());
        // 注册监听函数
        mLocationClient.registerLocationListener(myListener);
        
        // 调用这个方法来进行初始化
        SDKInitializer.initialize(getApplicationContext());
        
        setContentView(R.layout.activity_main);

        // 获取到这个控件
        mapView = (MapView)findViewById(R.id.bmapView);
        ...

    }

    ...

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
        mapView.onDestroy();
    }
    ...
}
  • 首先调用 SDKInitializer.initialize()方法,里面传入getApplicationContext()获取全局的Context参数,来进行初始化,注意:初始化操作要在setContentView()方法之前调用
  • 获取到这个控件的实例,以后会用到
  • 重写这个onResume()、onPause()、onDestroy()方法,对MapView进行管理,以保证资源能够及时得到释放
  • 运行程序就可以看到,百度地图就显示出来了
  • 但是这个时候报错了,只有网格没有地图
    11特色开发-百度地图_第18张图片
    错误信息.png

    百度查了一大堆,都是什么SHA1 错误,需要根据LogCat打印的去做更换,一脸懵逼了,不知道到哪去改这个东西,最后到百度的API控制中心
    11特色开发-百度地图_第19张图片
    API控制台.png
  • 点击设置,在这里把SHA1换成打印日志里面的,结果就好了


    11特色开发-百度地图_第20张图片
    运行成功.png

    这个坑算是填上了

移动到我的位置

显示是显示出来的,但是出来的是默认的北京市的,怎么才能定位到自己的呢?

  1. 百度LBS SDK的API中提供了一个BaiduMap类,它是地图的总控制器,调用MapView的getMap()方法就可以获取到BaiduMap的实例
    BaiduMap baiduMap = mapView.getMap()
  2. 获取到这个以后,就可以对地图进行各种操作了,比如设置地图的缩放级别以及将地图以哦对那个到某个经纬度上
    • 地图的缩放级别在3到19之间,越大就越精细,也可以是小数点,比如设置为12.5就可以写成
    MapStatusUpdate update = MapStatusUpdateFactory.zoomTo(12.5f);
    baiduMap.animateMapStatus(update);
  • 其中 MapStatusUpdateFactory.zoomTo()方法就收的是一个float参数,设置级别,zoomTo()方法返回的是MapStatusUpdate对象,把这个传入到 BaiduMap.animateMapStatus()方法中就可以设置缩放级别了
  1. 怎么将地图移动到某一个经纬度上呢,这个时候就要借助LatLng类,这个类就是用于存放经纬度的,它的构造方法接收两个参数,第一个是纬度值,第二个是经度值,之后调用MapStatusUpdateFactory的newLatLng()方法将这个LatLng对象传入,这个newLatLng()方法也是返回一个MapStatusUpdate对象,把这个对象传入到BaiduMap的animateMapStatus()方法中,就可以将地图移动到指定的经纬度上了
LatLng ll = new LatLng(111,222);
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMa.animateMapStatus(update);

  1. 继续在这个项目上修改,
package com.example.lbstest;

public class MainActivity extends AppCompatActivity {

    ...

    private BaiduMap baiduMap;
    private boolean isFirstLocate = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 进行初始化
        mLocationClient = new LocationClient(getApplicationContext());
        // 注册监听函数
        mLocationClient.registerLocationListener(myListener);

        SDKInitializer.initialize(getApplicationContext());

        setContentView(R.layout.activity_main);
        mapView = (MapView)findViewById(R.id.bmapView);

        // 获取到实例
        baiduMap = mapView.getMap();


    
    private void navigateTo(BDLocation location){
        if (isFirstLocate){
            // 设置位置
            LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            // 设置缩放级别
            update = MapStatusUpdateFactory.zoomTo(10f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
    }



    // 监听函数
    public class MyLocationListener implements BDLocationListener{
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            
            if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation ||bdLocation.getLocType() == BDLocation.TypeGpsLocation ){
                navigateTo(bdLocation);
            }
        }
    }
}

}

  • 主要添加了navigateTo()方法,这个方法就是用来设置位置和缩放,和上面一摸一样,这里的参数就是我当前的位置
  • 在onReceiveLocation()方法中,当设备定位到当前位置的时候,就直接调用navigateTo()方法就可以了,直接将BDLocation对象传入就可以了


    11特色开发-百度地图_第21张图片
    地图移动到我的位置.png

让我显示在地图上

如果当前的设备正在移动,那么显示我的这个光标就会跟着一起移动

  1. 百度的LBS SDK当中提供了一个MyLocationData.Builder类,这个类就是用来封装设备当前所在的位置,只要将当前位置的经纬度传入进来就可以了
MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
locationBuilder.latitude(50);
locationBuilder.longitude(100);
  1. MyLocationData.Builder类还提供了一个build()方法,当把封装的信息都设置完成后,只需要调用build()方法就可以生成一个MyLocationData的实例,然后把这个实例传入到BaiduMap的setMyLocationData()方法中,就可以了
MyLocationData locationData = locationBuilder.build();
baiduMap.setMyLocationData(locationData);
  1. 具体实现
package com.example.lbstest;

public class MainActivity extends AppCompatActivity {

    ...

    private BaiduMap baiduMap;
    private boolean isFirstLocate = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 进行初始化
        mLocationClient = new LocationClient(getApplicationContext());
        // 注册监听函数
        mLocationClient.registerLocationListener(myListener);

        SDKInitializer.initialize(getApplicationContext());

        setContentView(R.layout.activity_main);
        mapView = (MapView)findViewById(R.id.bmapView);

        // 获取到实例
        baiduMap = mapView.getMap();

         // 开启这个功能
        baiduMap.setMyLocationEnabled(true);

        ...
    
    private void navigateTo(BDLocation location){
        if (isFirstLocate){
            // 设置位置
            LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            // 设置缩放级别
            update = MapStatusUpdateFactory.zoomTo(10f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
           // 
        MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        MyLocationData locationData = locationBuilder.build();
        baiduMap.setMyLocationData(locationData);
    }



   @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
        mapView.onDestroy();
        //
        baiduMap.setMyLocationEnabled(false);
    }
}
}

  • 在navigateTo()方法中,新增了 MyLocationData的逻辑,和上面讲的一样,但是要把这个逻辑放到if语句外面,因为这个是随着我们的移动而移动
  • 要注意: baiduMap.setMyLocationEnabled(true),将此功能开启
    11特色开发-百度地图_第22张图片
    清楚的看到我了.png

    当然了,这只是简单的操作,具体的可以到官网查看

你可能感兴趣的:(11特色开发-百度地图)