LBS(Location Based Service)(基于位置的服务)
Android 中定位方式基本可以分为两种:GPS定位,网络定位。
GPS定位的工作原理是基于手机内置的GPS硬件直接和卫星进行交互来获取当前的经纬度信息,这种方式的精确度非常高,但是缺点是只能在室外使用,而且费电。
网络定位的工作原理是根据手机当前的网络附近的三个基站进行测速,以此计算出手机和每个基站之间的距离,再通过三角定位确定出一个带盖的位置,这种方式优点是在室内外都可以使用,但是精确度一般。
百度地图类参考:http://wiki.lbsyun.baidu.com/cms/androidsdk/doc/v4_4_1/index.html?overview-summary.html
1.获取API Key
接下来,我们将基于百度地图SDK来开发。该SDK免费对外开发,且使用无次数限制。不过使用前需要申请秘钥(AK)才可以使用。
首先需要注册一个百度账号然后申请API Key, 申请地址: http://lbsyun.baidu.com/apiconsole/key
Android 定位SDK 官方指南:http://lbsyun.baidu.com/index.php?title=android-locsdk
创建应用:
http://lbsyun.baidu.com/apiconsole/key
关于获取SHA1:
(1) cd c:\Users\用户名\.android
(2) keytool -list -v -keystore debug.keystore
(3)直接回车,不需要输入密码
(4)然后就可以查看到 SHA1
注意这个SHA1为开发版SHA1指纹
提交之后就可以看到我们申请到的AK了:
2.下载 LBS SDK
下载地址:http://lbsyun.baidu.com/sdk/download
选择我们需要的功能,然后点击开发包开始下载
下载时候解压,包文件下载到对应目录下:
注意jniLibs目录需要自己创建;
解压后的 so 文件为C/C++语言进行编写,然后在用NDK 编译出来的。
3.开发
获取当前位置信息官方文档: http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/getloc
- 获取位置信息, MainActivity 类:
public class MainActivity extends AppCompatActivity {
public LocationClient mLocationClient;
private TextView tvPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(new MyLocationListener()); //注册调用函数
tvPosition = (TextView) findViewById(R.id.activity_main_tv_position);
/**
* 运行时权限申请 */
List<String> permissionList = new ArrayList<>(); //存储需要申请的所有权限
//GPS 定位信息
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();
}
}
/**
* 开始定位
*/
private void requestLocation() {
initLocation();
// 开始定位,回调结果会返回我们注册的监听器中 MyLocationListener
mLocationClient.start();
}
private void initLocation(){
//LocationClientOption类,该类用来设置定位SDK的定位方式
LocationClientOption option=new LocationClientOption();
/**设置发起定位请求的时间间隔,默认0,即仅定位一次 */
option.setScanSpan(5000);
//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,设置是否需要地址信息,默认不需要
option.setIsNeedAddress(true);
//可选,默认false,设置是否使用gps
option.setOpenGps(true);
//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京*附近”
option.setIsNeedLocationDescribe(true);
//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.setIgnoreKillProcess(false);
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;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocationClient.stop(); //活动销毁后停止定位,减少电量消耗
}
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
StringBuilder currentPosition = new StringBuilder();
currentPosition.append("纬度:" + bdLocation.getLatitude() + "\n");
currentPosition.append("经度:" + bdLocation.getLongitude() + "\n");
currentPosition.append("定位方式:");
int locType= bdLocation.getLocType(); //获取定位方式
if (locType== BDLocation.TypeGpsLocation) {
currentPosition.append("GPS\n");
} else if (locType == BDLocation.TypeNetWorkLocation) {
currentPosition.append("网络\n");
}
currentPosition.append("LocationDescribe:" + bdLocation.getLocationDescribe() + "\n");
currentPosition.append("Country:" + bdLocation.getCountry() + "\n");
currentPosition.append("Province:" + bdLocation.getProvince() + "\n");
currentPosition.append("City:" + bdLocation.getCity() + "\n");
currentPosition.append("District:" + bdLocation.getDistrict() + "\n");
currentPosition.append("Street:" + bdLocation.getStreet() + "\n");
currentPosition.append("StreetNumber:" + bdLocation.getStreetNumber() + "\n");
currentPosition.append("AddrStr:" + bdLocation.getAddrStr() + "\n");
tvPosition.setText(currentPosition); //显示到界面当中
}
}
}
-
在地图中显示位置
首先地图中添加 MapView控件
<com.baidu.mapapi.map.MapView
android:id="@+id/activity_map_mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"/>
MapActivity :
public class MapActivity extends AppCompatActivity {
public LocationClient mLocationClient;
private MapView mapView;
private BaiduMap baiduMap;
private boolean isFirstLocate=true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(new MyLocationListener());
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_map);
getSupportActionBar().hide();//隐藏ActionBar
mapView=(MapView)findViewById(R.id.activity_map_mapView);
baiduMap=mapView.getMap();
baiduMap.setMyLocationEnabled(true); //显示当前设备位置
baiduMap.setCompassEnable(true); //是否显示指南针
//baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);//卫星地图
requestLocation();
}
/**
* 设置地图显示位置
*/
private void navigateTo(BDLocation location){
if(isFirstLocate){
LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude()); //用于存放经纬度
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(latLng);
baiduMap.animateMapStatus(update);
update =MapStatusUpdateFactory.zoomTo(16f); //设置缩放级别
baiduMap.animateMapStatus(update);
isFirstLocate=false;
}
//显示当前位置图标
MyLocationData.Builder builder=new MyLocationData.Builder();
builder.latitude(location.getLatitude());
builder.longitude(location.getLongitude());
MyLocationData locationData=builder.build();
baiduMap.setMyLocationData(locationData);
}
/**
* 开始定位
*/
private void requestLocation() {
initLocation();
// 开始定位,回调结果会返回我们注册的监听器中 MyLocationListener
mLocationClient.start();
}
private void initLocation(){
//LocationClientOption类,该类用来设置定位SDK的定位方式
LocationClientOption option=new LocationClientOption();
/**设置发起定位请求的时间间隔,默认0,即仅定位一次 */
option.setScanSpan(5000);
mLocationClient.setLocOption(option);
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
public class MyLocationListener implements BDLocationListener{
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//如果已经定位成功
if(bdLocation.getLocType()==BDLocation.TypeGpsLocation
||bdLocation.getLocType()==BDLocation.TypeNetWorkLocation){
navigateTo(bdLocation);
}
}
}
}