GPS定位:基于手机内置的GPS硬件直接和卫星交互来获取当前的经纬度信息,精确度高
网络定位:根据手机当前网络附近的三个基站进行测速,以此计算出手机和每个基站的距离,再通过三角定位确定出一个大概的位置,精确度一般
1 登录百度账号,打开http://developer.baidu.com/user/reg填写注册信息,只需要填写带有“*”号的那部分内容,然后提交。
2 打开自己的邮箱,点击百度发送给我们的验证邮件中的链接,完成注册。
3 访问http://lbsyun.baidu.com/apiconsole/key这个地址,同意百度开发者协议。
4 点击创建应用就可以去申请API Key了,应用名称可以随便填,应用类型选择Android SDK,启动服务保持默认即可。开发版SHA1和发布版SHA1指的是打包程序时所有的签名文件的SHA1指纹,可以通过Android Studio查看到。选中项目,点击右侧工具栏的Gradle——>项目名——>app——>Tasks——>android,其中singingReport这个Task就可以用来查看签名文件信息。
其中的SHA1码是Android自动生成的一个用于测试的签名文件,当你的应用程序发布时还需要创建一个正式的签名文件,如果要得到它的指纹,可以在cmd中输入如下命令:keytool -list -v -keystore <签名文件路径>
5 将SHA1码和项目包名(如:com.example.lbstest)填入,点击提交,应用就创建成功了。其中的长串字符串就是申请到的API Key。
准备LBS SDK
1 先将百度平台提供的SDK准备好,下载地址是:http://lbsyun.baidu.com/sdk/download。后续会用到基础地图和定位功能这两个SDK,将它们勾选上,然后点击"开发包"下载按钮即可。
2 下载后对该压缩包解压,其中会有一个libs目录,libs目录下的内容又分为两部分,BaiduLBS_Android.jar这个文件是Java层要使用到的,其他目录下的so文件是Native层要用到的。
3 我们需要将libs目录下的每个文件都放置到正确的位置上。将BaiduLBS_Android.jar文件复制到app目录下的libs目录中;接下来展开src/main目录,右键新建一个名为jniLibs的目录,专门用来存放so文件,然后将压缩包里的其他所有目录直接复制到这里。
4 手动点击Android Studio顶部工具栏的Sync按钮,之后libs目录下的jar文件就会多出一个向右的箭头,这就表示项目已经能引用到这些包了。
确定自己位置的经纬度
修改AndroidManifest.xml文件代码如下:
...
先申请权限,每一个权限都是LBS SDK内部要用到的。在
修改MainActivity中的代码如下:
class MainActivity extends AppCompatActivity{
public LocationClient mLocationClient;
private TextView positionText;
onCreate(){
//调用getApplicationContext()传入一个全局的Context对象
mLocationClient = new LocationClient(getApplicationContext());
//注册定位监听器,当获取到未知信息时,就会回调这个定位监听器
mLocationClient.registerLocationListener(new MyLocationListener());
List permissionList = new ArrayList<>();
//将未授权的权限添加进list
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()){
//将未授权的权限数组传入ActivityCompat.requestPermissions()
//方法中,批量请求授权
String[] permissions = permissionList.toArray(new String
[permissionList.size()]);
ActivityCompat.requestPermissions(MainActivity.this,permissions,1);
}else{
requestLocation();
}
}
//请求定位,定位的结果会回调到刚才注册的监听器中
requestLocation(){
mLocationClient.start();
}
onRequestPermissionResult(){
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:
}
}
class MyLocationListener implements BDLocationListener{
//每次收到定位信息时执行
void onReceiveLocation(BDLocation location){
runOnUiThread(new Runnable(){
run(){
StringBuilder 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. TypeNewWorkLocation){
currentPosition.append("网络");
}
positionText.setText(currentPosition);
}
});
}
onConnectHotSpotMessage(String s,int i){
}
}
}
在默认情况下,调用LocationClient中的start()方法只会定位一次,百度LBS SDK提供了一系列设置方法,来允许我们更改默认的行为,修改MainActivity如下:
requestLocation(){
initLocation();
mLocationClient.start();
}
initLocation(){
LocationClientOption option = new LocationClientOption();
//设置更新位置的时间间隔
option.setScanSpan(5000);
//为mLocationClient对象设置选项
mLocationClient.setLocOption(option);
}
onDestroy(){
super.onDestroy();
//活动销毁时记得停止定位,否则程序会在后台不断定位,消耗手机电量
mLocationClient.stop();
}
选择定位模式
开启了GPS定位功能后,我们可以在initLocation()方法中对百度LBS SDK的定位模式进行指定,一共有三种模式可以选择:
Hight_accuracy 高精确度模式,会在GPS信号正常的情况下优先使用GPS定位,在无法接收GPS信号的时候使用网络定位。
Battery_Saving 节电模式,只会使用网络定位。
Device_Sensors 传感器模式,只会使用GPS定位。
在手机设置里,可以选择使用哪种定位模式。
当然,我们也可以强制指定只使用GPS进行定位,修改MainActivity如下:
void initLocation(){
LocationClientOption option = new LocationClientOption();
option.setScanSpan(5000);
//指定定位模式为传感器模式
option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
mLocationClient.setLocOption(option);
}
看得懂的位置信息
修改MainActivity如下:
initLocation(){
LocationClientOption option = new LocationClientOption();
option.setScanSpan(5000);
//表示需要获取更详细的信息
option.setIsNeedAddress(true);
mLocationClient.setLocOption(option);
}
class MyLocationListener implements BDLocationListener{
onReceiveLocation(BDLocation location){
runOnUiThread(new Runnable(){
run(){
StringBuilder 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");
urrentPosition.append("街道:").append(location.
getStreet()).append("\n");
currentPosition.append("定位方式:");
if(location.getLocType()==BDLocation.TypeGpsLocation){
currentPosition.append("GPS");
}else if(location.getLocType()==BDLocation. TypeNewWorkLocation){
currentPosition.append("网络");
}
positionText.setText(currentPosition);
}
});
}
}
让地图显示出来
修改activity_main.xml中的代码:
修改MainActivity中的代码:
class MainActivity{
private MapView mapView;
onCreate(){
...
//初始化,必须在setContentView方法前执行
SDKInitializer.initialize(getApplicationContext);
setContentView(R.layout.activity_main);
mapView = (MapView)findViewById(R.id.bmapView);
...
}
onResume(){
super.onResume();
mapView.onResume();
}
onPause(){
super.onPause();
mapView.onPause();
}
onDestroy(){
super.onDestroy();
mLocationClient.stop();
mapView.onDestroy();
}
}
移动到我的位置
百度LBS SDK的API中提供了一个BaiduMap类,它是地图的总控制器:
BaiduMap baiduMap = mapView.getMap();
百度地图缩放级别的值在3~19之间,小数点可取,值越大地图越精细:
//设置缩放级别
MapStatusUpdate update = MapStatusUpdateFactory.zoomTo(12.5f);
//完成缩放
baiduMap.animateMapStatus(update);
借助LatLng类可以让地图移动到一个经纬度上,它的构造方法一共有两个参数,第一个参数存放纬度值,第二个参数存放经度值。之后调用MapStatusUpdateFactory的newLatLng()方法将LatLng对象传入,再将newLatLng()方法返回的MapStatusUpdate对象传入到BaiduMap的animateMapStatus()方法中,就可以将地图移动到指定的经纬度上了。写法如下:
LatLng ll = new LatLng(39.915,116.404);
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(update);
修改MainActivity中的代码如下:
class mainActivity{
private BaiduMap baiduMap;
private boolean isFirstLocate = true;
onCreate(){
...
baiduMap = mapView.getMap();
}
navigateTo(BDLocation location){
//第一次定位的时候移动下地图就够了
if(isFirstLocate){
Latlng ll = new LatLng(location.getLatitude(),location.getLongitude());
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(update);
update = MapStatusUpdateFactory.zoomTo(16f);
baiduMap.animateMapStatus(update);
isFirstLocate = false;
}
}
class MyLocationListener implements BDLocationListener{
onReceiveLocation(BDLocation location){
if(location.getLocType()==BDLocation.TypeGpsLocation
||location.getLocType()==BDLocation.TypeNetworkLocation){
navigateTo(location);
}
}
}
}
将“我”显示在地图上
LBS SDK提供了一个MyLocationData.Builder类,这个类时用来封装设备当前所在位置的,我们只需将经纬度信息传到这个类的相应方法当中就可以了:
MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
locationBuilder.latitude(39.915); locationBuilder.longitude(116.404);
将设备当前的位置显示在地图上:
MyLocationData locationData = locationBuilder.build();
baiduMap.setMyLocationData(locationData);
修改MainActivity代码如下:
class MainActivity{
onCreate(){
...
//必须开启获取当前设备位置的功能
baiduMap.setMyLocationEnabled(true);
}
navigateTo(BDLocation location){
if(isFirstLocate){
...
}
MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
locationBuilder.latitude(location.getLatitude());
locationBuilder.longitude(location.getLongitude());
MyLocationData locationData = locationBuilder.build();
baiduMap.setMyLocationData(locationData);
}
onDestroy(){
...
baiduMap.setMyLocationEnabled(false);
}
}