package com.zjw.mylocationbasedservices; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; 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.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 com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.model.LatLng; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; //11.1 p379 基于位置的服务简介 /* LBS:基于位置的服务。 主要原理: 一:GPS 基于手机内置GPS硬件直接和卫星交互来获取当前的经纬度信息 优点:精确度高 缺点:适合室外使用,室内基本无法接收卫星信号 二:网络定位 根据手机当前网络附近的三个基站进行测速, 以此计算出手机和每个基站之间的距离, 再通过三角定位确定出一个大概的位置 优点:室内室外都可用 缺点:精确度一般 */ //11.2 p380 申请API Key /* 申请API Key: 1.注册一个百度账号 2.申请成为百度开发者,登陆百度账号后访问http://developer.baidu.com/user/reg 3.访问http://lbsyun.baidu.com/apiconsole/key创建应用,提交信息后获取AK(API Key) 应用名随意 类型选Android SDK 启用服务默认 发布版SHA1,开发版SHA1:打包程序时所用签名文件的SHA1指纹 Android Studio查看方式:点击右侧工具栏的Gradle->项目名->module名->Tasks->android-> signingReport可查看签名文件信息(双击后如果是列表一样的,最近的左上图标切换) cmd查看方式:keytool -list -v -keystore <签名文件路径> 比如默认签名: cmd进入debug.keystore 默认目录:C:\Documents and Settings\Administrator\.androi 输入keytool -list -v -keystore debug.keystore,然后再输入密钥库口令,这里默认是android */ //11.3 p384 使用百度定位 //11.3.1 p384 准备LBS SDK /* 下载SDK地址:http://lbsyun.baidu.com/sdk/download 根据需要下载,这里用到定位,基础地图 我官网下载的一直解压错误,重下n次也没用,如果有相同情况,可去CSDN下载 测试可用下载地址:http://download.csdn.net/download/mr_wzc/9882687 */ /* 下载下来的文件分为jar包和so文件 jar包:Java层使用 so文件:Native层使用,用c/c++语言编写,NDK编译,百度已经做好封装 libs目录:存放jar包 新建jniLibs目录(与res同级):存放so文件 */ /* 我么直接复制jar包,没有修改gradle文件,必须手动同步,不然无法引用到Jar包中提供的接口 */ //11.3.2 p386 确定自己位置的经纬度 //布局:TextView,用于显示当前位置信息 /* 改清单文件:申请权限,AK(写你自己申请到的那个),注册服务(百度SDK中代码都是混淆过的),配置不能错,不然……已亲身试验 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zjw.mylocationbasedservices"> <!-- 这个权限用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <!-- 这个权限用于访问GPS定位--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- 获取运营商信息,用于支持提供运营商信息相关的接口--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <!-- 用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 访问网络,网络定位需要上网--> <uses-permission android:name="android.permission.INTERNET"/> <!-- SD卡读取权限,用户写入离线定位数据--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!--屏幕保持唤醒不锁屏--> <uses-permission android:name="android.permission.WAKE_LOCK"/> <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="com.baidu.lbsapi.API_KEY" android:value="BfIcM8iPqSbinkr3henQD2vMchHmohnG"/> <activity android:name=".UseBaiduLocation"> <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> */ /* 主类: 1.布局 2.获取LocationClient对象 3.注册监听器 4.申请权限,权限回调 5.开始定位,回调监听里获取经纬度,定位方式 */ /* mLocationClient.start();方法只会定位一次 如果正在高速移动中,实时更新位置 改主类代码 注意:最后必须stop()定位,不然程序会在后台不停定位,消耗电量 */ //11.3.3 p391 选择定位模式 /* 手动手机上开GPS后 代码里指定定位模式locationClientOption.setLocationMode() 三种模式: LocationClientOption.LocationMode.Hight_Accuracy 优先GPS,然后网络定位 LocationClientOption.LocationMode.Battery_Saving 省电模式,网络定位 LocationClientOption.LocationMode.Device_Sensors GPS */ //11.3.4 p392 看得懂的位置信息 /* locationClientOption.setIsNeedAddress(true);设置是否需要地址信息,默认为无地址 到监听器里获取国家省市区镇等信息 */ //11.4 p395 使用百度地图 //11.4.1 p395 让地图显示出来 /* 改布局 把之前的TextView设为不可见 android:visibility="gone" 加上 <com.baidu.mapapi.map.MapView android:id="@+id/mv_baidu_map" android:layout_width="match_parent" android:layout_height="match_parent"> </com.baidu.mapapi.map.MapView> */ /* 主类里面: 初始化: SDKInitializer.initialize(getApplicationContext());//初始化 注意:初始化 BaiduMap SDK要在显示界面setContentView()之前 重写: @Override protected void onResume() { super.onResume(); mMvBaiduMap.onResume(); } @Override protected void onPause() { super.onPause(); mMvBaiduMap.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mLocationClient.stop();//停止定位 mMvBaiduMap.onDestroy(); } 此时运行出来地图显示北京市中心 */ //11.4.2 p397 移动到我的位置 /* 1.获取BaiduMap实例 BaiduMap baiduMap= mMvBaiduMap.getMap(); 2.有了BaiduMap实例后可对地图进行各种操作 1.设置地图缩放比例 百度地图将缩放级别取指范围限定在3-19之间,小数也可,值越大,地图越精细 MapStatusUpdate update=MapStatusUpdateFactory.zoomTo(12.5f); mBaiduMap.animateMapStatus(update); 2.让地图移动到某一个经纬度 借助LatLng类(主要用于存放经纬度值) 构造函数参数传入两个参数:一:纬度,二:经度 调用MapStatusUpdateFactory.的newLatLng()方法 LatLng ll=new LatLng(29.915,116.404); MapStatusUpdate update=MapStatusUpdateFactory.newLatLng(ll); mBaiduMap.animateMapStatus(update); 3.这里主要是下面代码navigateTo()方法 */ //11.4.3 p400 让"我"显示在地图上 /* MyLocationData.Builder类,用来封装设备当前所在的位置 将经纬度信息封装入这个类 MyLocationData.Builder locationBuilder=new MyLocationData.Builder(); locationBuilder.latitude(39.915); locationBuilder.longitude(116.404); 封装完后调用build(),然后设置给地图 MyLocationData myLocationData=locationBuilder.build(); mBaiduMap.setMyLocationData(myLocationData); */ /* 可参考网络资料: http://www.cnblogs.com/act262/p/3812840.html,别人的博客,可能需要更全SDK下载 http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/getloc百度官方文档 */ public class UseBaiduLocation extends AppCompatActivity { @BindView(R.id.tv_position) TextView mTvPosition; @BindView(R.id.mv_baidu_map) MapView mMvBaiduMap; private LocationClient mLocationClient; private BaiduMap mBaiduMap; private boolean isFirstLocate=true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLocationClient = new LocationClient(getApplicationContext());//LocationClient对象 mLocationClient.registerLocationListener(new MyLocationListener());//注册监听器 SDKInitializer.initialize(getApplicationContext());//初始化 setContentView(R.layout.activity_use_baidu_location); ButterKnife.bind(this); requestAllPermissions();//请求运行时权限 //获取BaiduMap实例 mBaiduMap = mMvBaiduMap.getMap(); // 开启定位图层 mBaiduMap.setMyLocationEnabled(true); } //开始定位,定位结果会回调到监听器中 private void requestLocation() { //只定位一次 // mLocationClient.start(); //实时更新位置 initLocation(); mLocationClient.start(); } //实时更新位置,以及其他一些定位参数控制 private void initLocation() { LocationClientOption locationClientOption = new LocationClientOption(); locationClientOption.setScanSpan(3 * 1000);//设置更新时间 locationClientOption.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//设置模式 locationClientOption.setOpenGps(true); // 打开GPS locationClientOption.setTimeOut(10 * 1000); // 超时 locationClientOption.setIsNeedAddress(true);//设置是否需要地址信息,默认为无地址 mLocationClient.setLocOption(locationClientOption); } //获取位置信息后回调的监听器 //获取经纬度,定位方式 public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation bdLocation) { StringBuilder currentPositonSB = new StringBuilder(); currentPositonSB.append("纬度:").append(bdLocation.getLatitude()).append("\n"); currentPositonSB.append("经度:").append(bdLocation.getLongitude()).append("\n"); currentPositonSB.append("国家:").append(bdLocation.getCountry()).append("\n"); currentPositonSB.append("省:").append(bdLocation.getProvince()).append("\n"); currentPositonSB.append("市:").append(bdLocation.getCity()).append("\n"); currentPositonSB.append("区:").append(bdLocation.getDistrict()).append("\n"); currentPositonSB.append("街道:").append(bdLocation.getStreet()).append("\n"); currentPositonSB.append("定位方式:"); if (bdLocation.getLocType() == BDLocation.TypeGpsLocation) { currentPositonSB.append("GPS定位"); } else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) { currentPositonSB.append("网络定位"); } else if (bdLocation.getLocType() == BDLocation.TypeOffLineLocation) { currentPositonSB.append("离线定位"); } else if (bdLocation.getLocType() == BDLocation.TypeNetWorkException) { currentPositonSB.append("网络连接失败,一般由于手机无有效网络连接导致,请检查手机是否能够正常上网"); } else { currentPositonSB.append("其他:" + bdLocation.getLocType()); } mTvPosition.setText(currentPositonSB); //11.4.2 p397 移动到我的位置 if(bdLocation.getLocType() == BDLocation.TypeGpsLocation||bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){ navigateTo(bdLocation); } } } //11.4.2 p397 移动到我的位置 private void navigateTo(BDLocation bdLocation) { if(isFirstLocate){ LatLng ll=new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude()); MapStatusUpdate update= MapStatusUpdateFactory.newLatLng(ll); mBaiduMap.animateMapStatus(update); update=MapStatusUpdateFactory.zoomTo(17f); mBaiduMap.animateMapStatus(update); isFirstLocate=false; } //11.4.3 p400 让"我"显示在地图上 MyLocationData.Builder locationBuilder=new MyLocationData.Builder(); locationBuilder.latitude(bdLocation.getLatitude()); locationBuilder.longitude(bdLocation.getLongitude()); MyLocationData myLocationData=locationBuilder.build(); mBaiduMap.setMyLocationData(myLocationData); } @Override protected void onResume() { super.onResume(); mMvBaiduMap.onResume(); } @Override protected void onPause() { super.onPause(); mMvBaiduMap.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mLocationClient.stop();//停止定位 mMvBaiduMap.onDestroy(); mBaiduMap.setMyLocationEnabled(false); } //请求运行时权限 private void requestAllPermissions() { //权限列表 List<String> permissionList = new ArrayList<>(); //运行时权限 //如果用户之前没有允许权限进行的操作,添加到列表中 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION); } if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { permissionList.add(Manifest.permission.READ_PHONE_STATE); } if (ContextCompat.checkSelfPermission(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(this, permissions, 1); } else { //如果用户之前已经允许权限后进行的操作 requestLocation(); //开始定位,定位结果会回调到监听器中 } } //申请权限回调 @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, "You denid the permission,the program will be close", Toast.LENGTH_SHORT).show(); finish(); return; } } requestLocation(); //开始定位,定位结果会回调到监听器中 } else { Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show(); finish(); } break; default: break; } } }
转载于:https://my.oschina.net/u/3620480/blog/1492151