来自百度地图官方平台关于坐标系的说明:
Android定位SDK产品,支持全球定位,能够精准的获取经纬度信息。根据开发者的设置,在国内获得的坐标系类型可以是:国测局坐标、百度墨卡托坐标 和 百度经纬度坐标。在海外地区,只能获得WGS84坐标。请开发者在使用过程中注意坐标选择。定位SDK默认输出GCJ02坐标,地图SDK默认输出BD09ll坐标。
实现定位是百度地图开发的第二大基本内容,我在一开始做的时候遇到了挺多坑,主要是因为对代码不熟悉,而且基本是照搬其他博客的代码,所以遇到了一些bug自己很难解决,只有不停的查百度。后来多做了几次之后就基本没出问题了。建议参照百度地图官方开发文档,里面功能介绍还是比较全的,但是不适合刚起步的小白,可以用来了解代码功能,然后具体怎么用看下面的操作过程。尽可能把每一步都说明清楚。
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在AndroidManifest.xml中添加
2. 在AndroidManifest.xml中添加serves组件
<service android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote"/>
注意这是在AndroidManifest.xml中的Application中添加,如下:
前期准备完成,接下来就是添加代码
方向传感器的类就是能够感应方向,实时调节箭头的指向。
代码如下:
public class MyOrientationListener implements SensorEventListener
{
private SensorManager mSensorManager;
private Context mContext;
private Sensor mSensor;
private float lastX;
public MyOrientationListener(Context context)
{
this.mContext = context;
}
@SuppressWarnings("deprecation")
public void start()
{
mSensorManager = (SensorManager) mContext
.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null)
{
// 获得方向传感器
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
if (mSensor != null)
{
mSensorManager.registerListener(this, mSensor,
SensorManager.SENSOR_DELAY_UI);
}
}
public void stop()
{
mSensorManager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1)
{
// TODO Auto-generated method stub
}
@SuppressWarnings(
{ "deprecation" })
@Override
public void onSensorChanged(SensorEvent event)
{
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
float x = event.values[SensorManager.DATA_X];
if (Math.abs(x - lastX) > 1.0)
{
if (mOnOrientationListener != null)
{
mOnOrientationListener.onOrientationChanged(x);
}
}
lastX = x;
}
}
private OnOrientationListener mOnOrientationListener;
public void setOnOrientationListener(
OnOrientationListener mOnOrientationListener)
{
this.mOnOrientationListener = mOnOrientationListener;
}
public interface OnOrientationListener
{
void onOrientationChanged(float x);
}
}
这就是一个正常的类,直接复制粘贴即可。不用创建Layout布局文件。注意放在和MainActivity或者你需要实现定位的Activity同一个包中,不过不是必须。
在需要实现定位的布局文件中添加如下空间,以回到当前定位。
<ImageView
android:id="@+id/image_loc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/pic_locate_init"
android:layout_marginTop="540dp"
android:layout_marginLeft="320dp"/>
这里用一个ImageView来做为回到当前定位的button,图标样式:
也可以自己设置成其他button或者其他样式。
Button代码如下:
<Button
android:id="@+id/but_Loc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="定位"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="127dp"/>
在Layout布局文件中如图:
为了让image可以在地图右下角展示我将地图控件和image空降放在了同一个RelativeLayout相对布局里面。
效果如下:
定位资源图标下载:链接:https://pan.baidu.com/s/1tWRIM53g8_HIHniUOFAhiQ
提取码:ma06
下载后打开:
全部复制到res文件目录下:
mBaiduMap.setMyLocationEnabled(true);
我们通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//mapView 销毁后不在处理新接收的位置
if (location == null || mMapView == null){
return;
}
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(location.getDirection()).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
mBaiduMap.setMyLocationData(locData);
}
}
//定位初始化
mLocationClient = new LocationClient(this);
//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
//设置locationClientOption
mLocationClient.setLocOption(option);
//注册LocationListener监听器
MyLocationListener myLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
//开启地图定位图层
mLocationClient.start();
@Override
protected void onResume() {
mMapView.onResume();
super.onResume();
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mLocationClient.stop();
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
以上是百度地图官方文档的说明,读者可以阅读了解。以下是MainActivity中的完整代码:
相对于官方文档有一定的修改:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private MapView mMapView = null;
private BaiduMap mBaiduMap = null;
private Context context;
//定位相关
private double mLatitude;
private double mLongtitude;
//方向传感器
private MyOrientationListener mMyOrientationListener;
private float mCurrentX;
//自定义图标
private BitmapDescriptor mIconLocation;
private LocationClient mLocationClient;
public BDAbstractLocationListener myListener;
private LatLng mLastLocationData;
private boolean isFirstin = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
SDKInitializer.setCoordType(CoordType.BD09LL);
this.context = this;
mMapView = (MapView) findViewById(R.id.bmapView);
//获取地图控件引用
mBaiduMap = mMapView.getMap();
initMyLocation();
button();
}
protected void onStart() {
super.onStart();
//开启定位
mBaiduMap.setMyLocationEnabled(true);
if (!mLocationClient.isStarted())
mLocationClient.start();
//开启方向传感器
mMyOrientationListener.start();
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
//停止定位
mBaiduMap.setMyLocationEnabled(false);
mLocationClient.stop();
//停止方向传感器
mMyOrientationListener.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
}
@Override
public void onClick(View v) {
SDKInitializer.initialize(getApplicationContext());
switch (v.getId()) {
case R.id.image_loc: {
centerToMyLocation(mLatitude, mLongtitude);
break;
}
}
}
//按钮响应
private void button() {
//按钮
Button mbut_Loc = (Button) findViewById(R.id.image_loc);
//按钮处理
mbut_Loc.setOnClickListener(this);
}
//定位
private class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//mapView 销毁后不在处理新接收的位置
if (location == null || mMapView == null){
return;
}
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(mCurrentX).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
mBaiduMap.setMyLocationData(locData);
//设置自定义图标
MyLocationConfiguration config = new
MyLocationConfiguration(
MyLocationConfiguration.LocationMode.NORMAL, true, mIconLocation);
mBaiduMap.setMyLocationConfiguration(config);
//更新经纬度
mLatitude = location.getLatitude();
mLongtitude = location.getLongitude();
//设置起点
mLastLocationData = new LatLng(mLatitude, mLongtitude);
if (isFirstin) {
centerToMyLocation(location.getLatitude(), location.getLongitude());
if (location.getLocType() == BDLocation.TypeGpsLocation) {
// GPS定位结果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
// 网络定位结果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
// 离线定位结果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeServerError) {
Toast.makeText(context, "定位:服务器错误", Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
Toast.makeText(context, "定位:网络错误", Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
Toast.makeText(context, "定位:手机模式错误,请检查是否飞行", Toast.LENGTH_SHORT).show();
}
isFirstin = false;
}
}
}
//初始化定位
private void initMyLocation() {
//缩放地图
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);
//开启定位
mBaiduMap.setMyLocationEnabled(true);
//声明LocationClient类
mLocationClient = new LocationClient(this);
//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setIsNeedAddress(true);//设置是否需要地址信息
option.setScanSpan(1000);
//设置locationClientOption
mLocationClient.setLocOption(option);
myListener = new MyLocationListener();
//注册监听函数
mLocationClient.registerLocationListener(myListener);
//初始化图标
mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps);
initOrientation();
//开始定位
mLocationClient.start();
}
//回到定位中心
private void centerToMyLocation(double latitude, double longtitude) {
mBaiduMap.clear();
mLastLocationData = new LatLng(latitude, longtitude);
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(mLastLocationData);
mBaiduMap.animateMapStatus(msu);
}
//传感器
private void initOrientation() {
//传感器
mMyOrientationListener = new MyOrientationListener(context);
mMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mCurrentX = x;
}
});
}
}
运行后的效果:
第一次运行时会显示请求定位权限的弹窗,全部同意,然后可能会定位到几内亚湾,因为在还没同意权限前,后台定位就完成了,但是定位失败,就飞到了几内亚湾。点击定位按钮 Image,就回到了当前定位。 如果不希望在没有开启定位时出现飞到几内亚湾的情况,可以设置初始定位地址。代码如下:
//设置地图默认定位位置,地图中心位target的经纬度
MapStatusUpdate mapStatusUpdate= MapStatusUpdateFactory.newLatLng(target);
InitialBaiduMap.setMapStatus(mapStatusUpdate);
需要定义一个target变量:
//设置变量target,表示默认定位的地方 默认地点华理
protected LatLng target = new LatLng(30.83673,121.510342);
——————————————————————————
版权所有,转载请标明出处
借鉴的博客:
https://blog.csdn.net/qq_38605488/article/details/87040264
官方文档:
http://lbsyun.baidu.com/index.php?title=androidsdk/guide/create-map/location