当前位置:   article > 正文

Android Studio 开发(三)--百度地图定位APP_android studio地图开发(百度地图)

android studio地图开发(百度地图)

Android Studio 开发(三)–百度地图定位APP

本次Github代码仓库 --crcr1013/MyWechat

一、成果要求

根据官方文档,开发百度地图定位APP,显示出当前位置坐标

二、关键步骤

1、注册和获取密钥

注册和获取密钥的开发文档参考如下:
Android地图SDK开发文档获取密钥

1.1创建应用

进入百度地图开发平台的控制台的创建应用界面
填写应用名称、选择应用类型为Android SDK在这里插入图片描述
在这里插入图片描述
想要创建应用需要先获取SHA1值和包名

1.2获取SHA1

调试版本(debug)和发布版本(release)下的 SHA1 值是不同的,发布 apk 时需要根据发布 apk 对应的 keystore 重新配置 Key,在开发时请使用调试版本)。
1、找到keytool所在目录
keytool一般在开发软件AS的安装目录的jre/bin文件夹下
在这里插入图片描述
2、找到keystore所在目录
keytool默认路径为C:\Users<用户名>.Android\debug.keystore
如:我的用户名为dell,我可以在上述路径下找到keystore
在这里插入图片描述
若想更改或确认位置,可以在build->Generated Signed Apk下操作
在这里插入图片描述在这里插入图片描述3、调用keystore命令
进入控制台,切换目录到keytool所在目录

d: 
cd D:\softwares\AndroidStudio_3.1.4\jre\bin
  • 1
  • 2

继续在控制台输入命令

keytool -list -v -keystore C:\Users\dell\.android\debug.keystore -alias androiddebugkey
  • 1

(alias起到设置别名的功能)

4、输入口令:
调试版本默认密码是: android
在这里插入图片描述
得到SHA1值
在这里插入图片描述

SHA1: F3:46:B1:39:22:1D:03:22:14:D5:2A:EC:DC:B2:6A:70:ED:73:2D:B1
  • 1

1.3获取包名

在app目录下的build.gradle文件中找到applicationId,并确保其值与AndroidManifest.xml中定义的package相同。
在这里插入图片描述

package name:com.example.mylbs
  • 1

1.4生产开发密钥AK

点击提交后,成功创建应用,在我的应用中可查看该应用的AK码
在这里插入图片描述

AK码:WMs63oa00am52S77Ph4NTnmRq0T7IyrM
  • 1

2、Android Studio配置

创建一个安卓项目,在项目中集成BaiduMap SDK

2.1下载SDK本地依赖

点击下载开发包
可根据地图功能要求选择功能,在这里我选择基础定位、基础地图、(驾车导航、全景等可不选)开发包格式选择JAR格式、应用发布平台选择标准开发包。

2.2将开发包拷贝至工程

1、将Android切换至Project目录。
2、解压开发包,将开发包下全部的文件夹及文件拷贝至app的libs目录下。
在这里插入图片描述
3、复制libs目录,将Project目录切换至Android,将复制的libs目录拷贝至app目录下。
在这里插入图片描述

2.3往工程中添加jar文件

在libs目录下,选中BaiduLbs_Android.ja,右键,选择Add As Library…
此时会发现在app目录的build.gradle的dependencies块中生成了工程所依赖的jar文件的对应说明,如下所示:
在这里插入图片描述

3、创建地图

3.1配置AndroidManifest.xml文件

1、在application中加入如下代码配置开发密钥(AK)

 <meta-data
            android:name="WMs63oa00am52S77Ph4NTnmRq0T7IyrM"
            android:value="开发者 key" />
  • 1
  • 2
  • 3

android:name值自行修改为创建的应用的AK值。
2、在application外部添加如下权限声明

 <!-- 访问网络,进行地图相关业务数据请求,包括地图数据,路线规划,POI检索等 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 获取网络状态,根据网络状态切换进行数据请求网络转换 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 读取外置存储。如果开发者使用了so动态加载功能并且把so文件放在了外置存储区域,则需要申请该权限,否则不需要 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 写外置存储。如果开发者使用了离线地图,并且数据写在外置存储区域,则需要申请该权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.2设计布局文件

在布局文件中添加地图容器,MapView是View的一个子类,用于在Android View中放置地图。MapView的使用方法与Android提供的其他View一样。
在这里直接使用代码生成地图容器,替换掉原来的textView。

<com.baidu.mapapi.map.MapView  
    android:id="@+id/bmapView"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:clickable="true" />
  • 1
  • 2
  • 3
  • 4
  • 5

3.3地图初始化

1、新建一个自定义的Application,在其onCreate方法中完成SDK的初始化。

package com.example.mylbs;
import android.app.Application;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
public class DemoApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //在使用SDK各组件之前初始化context信息,传入ApplicationContext
        SDKInitializer.initialize(this);
        //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
        //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
        SDKInitializer.setCoordType(CoordType.BD09LL);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2、在AndroidManifest.xml文件中声明该Application

    <application
        android:name=".DemoApplication"
    </application>
  • 1
  • 2
  • 3

3、创建地图Activity,管理MapView生命周期

public class MainActivity extends AppCompatActivity {

    private MapView mMapView = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取地图控件引用
        mMapView = (MapView) findViewById(R.id.bmapView);
    }
    @Override
    protected void onResume() {
        super.onResume();
        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
        mMapView.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
        mMapView.onPause();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
        mMapView.onDestroy();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

3.4启动项目

得到如下效果:
在这里插入图片描述

4、定位当前所在位置

若想使用显示定位功能,需要确保开发包包含基本定位的功能。

4.1配置AndroidManifest.xml文件

1.加入如下权限使用声明

<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • 1
  • 2
  • 3
  • 4

2.在Application标签中声明定位的service组件

<service android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote"/>
  • 1
  • 2
  • 3

4.2进入MainActivity,进行地图初始化

1.初始化相关对象

 private LocationClient mLocClient;
 private BaiduMap mBaiduMap = null;
  • 1
  • 2

2.通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。

	/**
     * 定位SDK监听函数
     */
    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            // MapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null) {
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())// 设置定位数据的精度信息,单位:米
                    .direction(location.getDirection()) // 此处设置开发者获取到的方向信息,顺时针0-360
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();
            // 设置定位数据, 只有先允许定位图层后设置数据才会生效
            mBaiduMap.setMyLocationData(locData);
            if (isFirstLoc) {
                isFirstLoc = false;
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                MapStatus.Builder builder = new MapStatus.Builder();
                builder.target(latLng).zoom(20.0f);
                mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.通过LocationClient发起定位

	/**
     * 定位初始化
     */
    public void initLocation(){

        // 开启定位图层
        mBaiduMap.setMyLocationEnabled(true);
        // 定位初始化
        mLocClient = new LocationClient(this);
        MyLocationListener myListener = new MyLocationListener();
        mLocClient.registerLocationListener(myListener);
        LocationClientOption option = new LocationClientOption();
        // 打开gps
        option.setOpenGps(true);
        // 设置坐标类型
        option.setCoorType("bd09ll");
        option.setScanSpan(1000);
        mLocClient.setLocOption(option);
        mLocClient.start();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

4.修改一下onDestroy,正确管理生命周期

	@Override
    protected void onDestroy() {
        super.onDestroy();
        // 退出时销毁定位
        mLocClient.stop();
        // 关闭定位图层
        mBaiduMap.setMyLocationEnabled(false);
        // 在activity执行onDestroy时必须调用mMapView.onDestroy()
        mMapView.onDestroy();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.3启动项目

得到如下效果:

在这里插入图片描述
发现定位到几内亚湾了,并不是我当前的实际位置,经过查找资料,发现可能还是权限问题,于是我进行了相关配置,主要是添加读取手机状态的权限声明以及申请动态权限的函数checkVersion,如果您也定位到几内亚湾,可参考文章末尾问题总结部分进行相关配置。
修改后效果如下:
在这里插入图片描述
现在在地图上定位到了谷歌公司,经查找资料,可能是虚拟机自身的原因,在真机上或许可以精准定位到当前位置,在这里则不做过多介绍。
下面来添加一下点击定位,回到原位,显示位置信息的功能。

5、点击定位,回到原位,显示位置信息

5.1实现点击定位

1.进行相关变量的初始化

private Marker marker;//标点
private BitmapDescriptor bitmap;//标点的坐标
private double markerLatitude=0;//标点的纬度
private double markerLongitude=0;//标点的经度
  • 1
  • 2
  • 3
  • 4

2.增加点击函数 mapOnClick()
该函数中用到的定位点图片为icon_marka.png,即下面这个图片,可根据喜好自由选择。
在这里插入图片描述
实现点击定位的关键类是BitmapDescriptor和Maker
函数代码:

	/**
     * 地图点击
     */
    private void mapOnClick() {
        // 设置marker图标
        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_marka);
        mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
            @Override
            public void onMapPoiClick(MapPoi mapPoi) {
            }
            //此方法就是点击地图监听
            @Override
            public void onMapClick(LatLng latLng) {
                //获取经纬度
                markerLatitude = latLng.latitude;
                markerLongitude = latLng.longitude;
                //先清除图层
                mBaiduMap.clear();
                // 定义Maker坐标点
                LatLng point = new LatLng(markerLatitude, markerLongitude);
                // 构建MarkerOption,用于在地图上添加Marker
                MarkerOptions options = new MarkerOptions().position(point)
                        .icon(bitmap);
                // 在地图上添加Marker,并显示
                //mBaiduMap.addOverlay(options);
                marker = (Marker) mBaiduMap.addOverlay(options);
                Bundle bundle = new Bundle();
                bundle.putSerializable("info", "纬度:" + markerLatitude + "   经度:" + markerLongitude);
                marker.setExtraInfo(bundle);//将bundle值传入marker中,给baiduMap设置监听时可以得到它
                //点击地图之后重新定位
                initLocation();
            }
        });
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

2.给地图视图初始化函数增加一些属性

        option.setScanSpan(0);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
        option.setOpenGps(true);//可选,默认false,设置是否使用gps
        option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false);//可选,默认false,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认杀死
        option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
        option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.修改定位SDK监听函数

	/**
     * 定位SDK监听函数
     */
    public class MyLocationListener implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            // MapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null) {
                return;
            }
            double resultLatitude;
            double resultLongitude;
            //判断是否为第一次定位
            if (markerLatitude == 0) {//自动定位
                resultLatitude = location.getLatitude();
                resultLongitude = location.getLongitude();
                ibLocation.setVisibility(View.GONE);
            } else {//标点定位
                resultLatitude = markerLatitude;
                resultLongitude = markerLongitude;
                ibLocation.setVisibility(View.VISIBLE);
            }
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())// 设置定位数据的精度信息,单位:米
                    .direction(location.getDirection()) // 此处设置开发者获取到的方向信息,顺时针0-360
                    .latitude(resultLatitude)
                    .longitude(resultLongitude)
                    .build();
            mBaiduMap.setMyLocationData(locData);// 设置定位数据, 只有先允许定位图层后设置数据才会生效
            LatLng latLng = new LatLng(resultLatitude, resultLongitude);
            MapStatus.Builder builder = new MapStatus.Builder();
            builder.target(latLng).zoom(20.0f);
            mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
            String info = (String) marker.getExtraInfo().get("info");
            Toast.makeText(MainActivity.this, info, Toast.LENGTH_SHORT).show();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在该函数中定义两个double类型的变量,分别是标点的经度和纬度,当一开始进来的时候判断是否等于0,如果是,则使用自动的定位,如果不是,则使用标点的定位。
我在点击地图时,将获得的位置坐标通过mapOnClick()中的builder,和marker.setExtraInfo(bundle)传入marker中,在该函数中又通过marker.getExtraInfo().get(“info”)获取并用Toast输出到屏幕上。

5.2实现回到原位

1.进行相关变量的初始化

private ImageButton ibLocation;//重置定位按钮
  • 1

2.新增重置定位函数 resetLocation()

	/**
     * 点切换到其他标点位置时,重置定位显示,点击之后回到自动定位
     *
     * @param view
     */
    public void resetLocation(View view) {
        markerLatitude = 0;
        initLocation();
        marker.remove();//清除标点
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

点击回到原位按钮时,调用该函数,将标点经度重置为0,即回到初始定位,再进行定位初始化initLocation(),清除掉标点,即实现了回到原位。
3.修改总布局文件
根布局改为RelativeLayout
在这里插入图片描述
添加一个ImageButton,用于点击回到原位,点击事件对应MainActivity中的resetLocation函数。

    <ImageButton
        android:id="@+id/ib_location"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_margin="8dp"
        android:background="@drawable/p1"
        android:onClick="resetLocation"
        android:visibility="gone" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里p1为:
在这里插入图片描述
4.在OnCreate函数中确定重置定位按钮

ibLocation = (ImageButton) findViewById(R.id.ib_location);
  • 1

三、效果展示

启动项目,效果如下:
在这里插入图片描述

四、问题总结

1、在添加meta-data配置时,key和value搞错
运行源码之后发现定位到的地方并不是当前的位置,我定位在了几内亚湾海域内,观察Run内信息才发现存在图片所示错误。
在这里插入图片描述
去核查AndroidManifest文件才发现,我错误的将AK码填入name字段,按照开发文档,name不需要做修改,value的值为自己应用的AK值,粗心大意了哇!!
在这里插入图片描述
2、在改正后运行发现,还是在几内亚湾,不过Run中的报错已经没有了,出现了一些乱码错误,如图
在这里插入图片描述
参考相关博客发现应该是权限问题,于是采用进行动态权限申请。
①在app的build.gralde中的android闭包下增加如下jdk1.8的使用代码:

	compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
  • 1
  • 2
  • 3
  • 4

②然后在dependencies闭包下增加如下依赖

	//动态权限请求
    implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
    implementation "io.reactivex.rxjava2:rxjava:2.0.0"
  • 1
  • 2
  • 3
  • 4

③然后点击Sync同步一下,然后进入到MainActivity,新增检查权限的方法
(一定要同步刷新啊啊!要不然RxPermissions会报红,不能调用)

	/**
     * 检查版本
     */
    private void checkVersion() {
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
            RxPermissions rxPermissions = new RxPermissions(this);
            rxPermissions.request(Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.READ_PHONE_STATE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    .subscribe(granted -> {
                        if (granted) {//申请成功
                            //发起连续定位请求
                            initLocation();// 定位初始化
                        } else {//申请失败
                            Toast.makeText(MainActivity.this,"权限未开启",Toast.LENGTH_SHORT).show();
                        }
                    });
        }else {
            initLocation();// 定位初始化
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

④在onCreate中调用

chekVision();
  • 1

再启动,就不是定位在几内亚湾了,但由于虚拟机的影响,是定位到谷歌公司的,有兴趣的可以在真机上运行一下,看是否和自己当前位置一致。

五、心得体会

本次的Project非非非常有意思,开发文档就是好哇,基本的配置以及地图显示部分给出了较完整的参考,让我较顺利的完成了地图显示部分,但在点击定位和回到原位的功能添加时,我参考了开发文档的部分内容,地图相关的API介绍以及网上的博客资源,虽然出现了一些问题,但均已解决并进行总结,在摸索中让功能更加完善很有成就感。

在这一次功能设计中,我先将整体功能构想计划好,地图显示–>点击定位–>回到原位–>显示位置信息,根据功能的改进添加对应函数以及位置监听函数的属性。根据功能添加文件,根据设计诉求添加布局,思路比以往的project实现时更加清晰。

感谢百度地图开发平台,感谢老师,希望在下一次的功能设计中,我可以收获更多,冲鸭!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/297722?site
推荐阅读
相关标签