目录
注:百度地图有地图SDK实现的开发指导文档,以下功能的实现基本是参照百度的开发文档实现的。网址为:Android地图SDK | 百度地图API SDK
一.功能
1.定位到当前位置并显示。
2.获取当前方向角并以绘制扇形视野
3.获取服务器数据,实现对视野扇形大小的改变
二.功能实现
1.定位功能的实现:
protected void onCreate(Bundle savedInstanceState) {
//
//权限
List<String> permissionList = new ArrayList<>();
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);
}
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();
mBaiduMap.setMyLocationEnabled(true);
MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, null);
mBaiduMap.setMyLocationConfiguration(configuration);
//定位初始化
mLocationClient = new LocationClient(this);
//创建LocationClientOption对象,用于设置定位方式
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll"); //设置坐标类型
option.setScanSpan(1000); //定位一次时间差
option.setOpenGps(true); //打开GPS
//可选,设置是否需要设备方向结果
//option.setNeedDeviceDirect(true);
mLocationClient.setLocOption(option); //保存定位参数与信息
//定位
//注册监听函数
//创建LocationClient类,定位服务的客户端
mLocationClient.registerLocationListener(myListener);
mLocationClient.start();
//方向角
MyOrientationListener = new MyOrientationListener(this);
MyOrientationListener.setmOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mCurrentX = x;
}
});
}
//我们通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.i("---------------",latitude +" "+longitude);
//发送HTTP请求
System.out.println("建立线程!");
while(result==null){ new Thread(new Runnable() {//创建子线程
@Override
public void run() {
System.out.println("开始发送");
sent=new senthttp();//把路径选到MainActivity中
// 存取http数据
result=sent.result();
}
}).start(); }//启动子线程
//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);
if (isFirstLoc) { //如果是第一次定位,就定位到以自己为中心
LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); //获取用户当前经纬度
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll); //更新坐标位置
mBaiduMap.animateMapStatus(u); //设置地图位置
isFirstLoc = false; //取消第一次定位
}
Angle=90-(int)mCurrentX;//90- 坐标系转换
//正值化
while(Angle<0){
Angle=360+Angle;
}
drawRadius=new drawRadius();
try {
latitudes= result.getDouble("latitude");
} catch (JSONException e) {
e.printStackTrace();
}
try {
longitudes=result.getDouble("longitude");
} catch (JSONException e) {
e.printStackTrace();
}
//获取http返回数据
try {
myangle =result.getDouble("myangle");
} catch (JSONException e) {
e.printStackTrace();
}
try {
myradius=result.getInt("myradius");
} catch (JSONException e) {
e.printStackTrace();
}
//画出所需圆形范围
//drawRadius.drawCircle(latitudes, longitudes);
}
}
2.绘制扇形视野区域:
public class draw {
private double sDegree=Angle-myangle;
private double eDegree=Angle+myangle;
private int flag=0;
private drawRadius() {
while(sDegree<0){
sDegree=360+sDegree;
}
while(eDegree>360){
eDegree=eDegree-360;
}
if(eDegree<sDegree){
flag=1;
}
if (radiuOverlay != null) {
radiuOverlay.remove();//把扇形移除
}
OverlayOptions myop = new PolygonOptions()
.points(point(new LatLng(latitude, longitude), myradius,sDegree ,eDegree))
.stroke(new Stroke(0, Color.parseColor("#ffffff")))
.fillColor(Color.parseColor("#201c3d6f"));
radiuOverlay = mBaiduMap.addOverlay(myop);
}
//扇形的所经过的边的坐标
public List<LatLng> point(LatLng point, long radius, double startAngle, double endAngle) {
//创建构成多边形的坐标点数组
List<LatLng> Points = new ArrayList<>();
Points.add(point);
if(flag==0){
for (int i = (int)sDegree; i < eDegree + 0.001; i ++) {
//循环获取每步的圆弧上点的坐标,存入点数组
Points.add(offsetBearing(point, radius, i));
} }
else{
for (int i = (int)sDegree; i < 360 + 0.001; i ++) {
//循环获取每步的圆弧上点的坐标,存入点数组
Points.add(offsetBearing(point, radius, i));}
for (int i = 0; i < eDegree + 0.001; i ++) {
//循环获取每步的圆弧上点的坐标,存入点数组
Points.add(offsetBearing(point, radius, i));}
}
return Points;
}
//圆弧所需的坐标点,(计算出弧度的坐标点以LatLng 经纬度返回)
public LatLng offsetBearing(LatLng point, long dist, int bearing) {
//计算1经度与原点的距离
double lngConv = DistanceUtil.getDistance(point, new LatLng(point.latitude, point.longitude + 0.1));
//计算1纬度与原点的距离
double latConv = DistanceUtil.getDistance(point, new LatLng(point.latitude + 0.1, point.longitude));
//正弦计算待获取的点的纬度与原点纬度差
double lat = dist * Math.sin(bearing * Math.PI / 180) / latConv;
//余弦计算待获取的点的经度与原点经度差
double lng = dist * Math.cos(bearing * Math.PI / 180) / lngConv;
return new LatLng(point.latitude + lat, point.longitude + lng);
}
}
注: 以上对扇形绘制的实现参考于此博客(此博客对扇形怎么绘制进行了详细的叙述):
Android画扇形区域,Android百度地图画扇形_知乎 MCN 小管家的博客-CSDN博客
3.获取服务器端数据实现对显示的扇形区域大小的修改:
public class senthttp {
StringBuffer buffer = new StringBuffer();
JSONObject json;
public senthttp(){
try {
URL url = new URL("http:/*********/file");//此处为获取数据的目的地址
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(reader);
String temp = null;
while ((temp = bufferedReader.readLine()) != null) {
buffer.append(temp);
}
bufferedReader.close();
reader.close();
inputStream.close();
Log.e("返回结果:",buffer.toString());//打印结果
json= new JSONObject(buffer.toString());
} catch (MalformedURLException e) {
System.out.println("异常1");
e.printStackTrace();
} catch (IOException e) {
System.out.println("异常2");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
public JSONObject result(){
try {
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}
三.效果展示
1.效果展示:
四.不足
1.定位功能,扇形区域显示不稳定。
2.代码杂乱。
六.遇到的问题
1.百度地图SDK的实现需要注册和获取密钥。
2.当前方向角显示存在偏差。
3.扇形区域随当前方向角变化出现反向的问题。
解决:密钥的获取和使用在百度的官方API文档中都有详细的教程,按着他的指导一步一步完成就行。方向角数据的获取和处理存问题,是因为方向角变化的对应数据获取对象错误。手机绘图默认的坐标系和百度地图自己的坐标系存在差异,两者不是重合的,两者的直角坐标系是反向且相差90°(在我这个app里是这样的,并且是根据这个解决的,但是我查阅的资料似乎并不是这样的),因此在绘制扇形时出现了图形与方向角不重合且反向移动。