这里使用的SDK为AMap_Location_V2.5.0_20160526.jar
没有接触过高德地图的同学,请参考
加载一张高德地图
package com.pansoft.oilgas.gaodenavigation;
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.v7.app.AppCompatActivity;
import android.util.Log;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
public class SimpleGeoFenceActivity extends AppCompatActivity implements AMapLocationListener {
final String tag = SimpleGeoFenceActivity.class.getSimpleName();
final int REQ_LOCATION = 0x12;
private AMapLocationClient mLocationClient;
private AMapLocationClientOption mLocationOption;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//实例化定位客户端
mLocationClient = new AMapLocationClient(this);
mLocationOption = new AMapLocationClientOption();
mLocationOption.setOnceLocation(true);
//设置定位监听
mLocationClient.setLocationListener(this);
//设置为高精度定位模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mLocationOption.setInterval(2000);
mLocationClient.setLocationOption(mLocationOption);
applyPermission();
}
public void applyPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQ_LOCATION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQ_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationClient.startLocation();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onLocationChanged(AMapLocation loc) {
if (loc != null && loc.getErrorCode() == 0) {
double latitude = loc.getLatitude();
double longitude = loc.getLongitude();
Log.d(tag, "当前经纬度: " + latitude + "," + longitude);
}
}
}
获取经纬度为:36.67237,117.13576
测试地理围栏,一直用眼睛盯着手机屏幕挺难受的。这里当地理围栏有变化的时候,让手机发生震动,添加震动权限
<uses-permission android:name="android.permission.VIBRATE">uses-permission>
java代码如下:
package com.pansoft.oilgas.gaodenavigation;
import android.Manifest;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
public class SimpleGeoFenceActivity extends AppCompatActivity implements AMapLocationListener {
final String tag = SimpleGeoFenceActivity.class.getSimpleName();
final int REQ_LOCATION = 0x12;
final int REQ_GEO_FENCE = 0x13;
final String ACTION_GEO_FENCE = "geo fence action";
private AMapLocationClient mLocationClient;
private AMapLocationClientOption mLocationOption;
private IntentFilter intentFilter;
private Vibrator vibrator;
private TextView textView;
private LatLng centerLatLng;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
setContentView(textView);
//1.获取震动服务
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
mLocationClient = new AMapLocationClient(this);
mLocationOption = new AMapLocationClientOption();
//2.注意这里需要持续定位,屏蔽掉下面这句话
// mLocationOption.setOnceLocation(true);
mLocationClient.setLocationListener(this);
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mLocationOption.setInterval(2000);
mLocationClient.setLocationOption(mLocationOption);
applyPermission();
//通过上一步骤获取的当前位置,设置地理围栏中心
centerLatLng = new LatLng(36.67237, 117.13576);
Intent intent = new Intent(ACTION_GEO_FENCE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, REQ_GEO_FENCE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
/*100:是围栏半径(测试发现,设置的太小,不会发出广播);-1:是超时时间(单位:ms,-1代表永不超时) */
mLocationClient.addGeoFenceAlert("fenceId", centerLatLng.latitude, centerLatLng.longitude, 100, -1, pendingIntent);
intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_GEO_FENCE);
}
@Override
protected void onResume() {
super.onResume();
//注册监听,进出地理围栏事件
this.registerReceiver(broadcastReceiver, intentFilter);
}
BroadcastReceiver
broadcastReceiver = new BroadcastReceiver() {
//处理进出地理围栏事件
@Override
public void onReceive(Context context, Intent intent) {
// 接收广播
if (intent.getAction().equals(ACTION_GEO_FENCE)) {
Bundle bundle = intent.getExtras();
// 根据广播的event来确定是在区域内还是在区域外
int status = bundle.getInt("event");
String geoFenceId = bundle.getString("fenceId");
if (status == 1) {
Toast.makeText(SimpleGeoFenceActivity.this, "进入地理围栏~", Toast.LENGTH_LONG).show();
vibrator.vibrate(3000);
textView.setText("In");
} else if (status == 2) {
// 离开围栏区域
Toast.makeText(SimpleGeoFenceActivity.this, "离开地理围栏~", Toast.LENGTH_LONG).show();
vibrator.vibrate(3000);
textView.setText("Out");
}
}
}
};
@Override
protected void onStop() {
super.onStop();
//取消监听
this.unregisterReceiver(broadcastReceiver);
}
public void applyPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQ_LOCATION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQ_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationClient.startLocation();
} else {
Toast.makeText(SimpleGeoFenceActivity.this, "没有权限,无法获取位置信息~", Toast.LENGTH_LONG).show();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onLocationChanged(AMapLocation loc) {
if (loc != null && loc.getErrorCode() == 0) {
double latitude = loc.getLatitude();
double longitude = loc.getLongitude();
Log.d(tag, "当前经纬度: " + latitude + "," + longitude);
LatLng endLatlng = new LatLng(loc.getLatitude(), loc.getLongitude());
// 计算量坐标点距离
double distances = AMapUtils.calculateLineDistance(centerLatLng, endLatlng);
//展示当前和地理围栏中心点的位置
textView.setText("当前距离:" + distances);
}
}
}
ok!
1.优化获取当前位置的方法——在第二步的基础上,直接获取当前位置,调整的主要逻辑是:
将centerLatLng的获取&&地理围栏的设置都调整到onLocationChanged里面
if (centerLatLng == null) {
centerLatLng = new LatLng(loc.getLatitude(), loc.getLongitude());
Intent intent = new Intent(ACTION_GEO_FENCE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, REQ_GEO_FENCE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//100:是围栏半径(测试发现,设置的太小,不会发出广播);-1:是超时时间(单位:ms,-1代表永不超时)
mLocationClient.addGeoFenceAlert("fenceId", centerLatLng.latitude, centerLatLng.longitude, 100, -1, pendingIntent);
} else{
...
2.在地图上显示我的位置
在onCreate中添加代码
//show my location
aMap.setLocationSource(this);
aMap.getUiSettings().setMyLocationButtonEnabled(true);
aMap.setMyLocationEnabled(true);
aMap.setMyLocationType(AMap.LOCATION_TYPE_MAP_FOLLOW);
LocationSource接口的实现如下:
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
this.onLocationChangedListener = onLocationChangedListener;
}
@Override
public void deactivate() {
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
}
在onLocationChanged刷新我的位置
if (onLocationChangedListener != null) {
onLocationChangedListener.onLocationChanged(loc);
}
3.标出地理围栏的范围
对标记不熟悉的同学,请参考
高德地图——标记
主要代码如下:
public void addCircle(LatLng latLng,int radius){
CircleOptions circleOptions=new CircleOptions();
circleOptions.center(latLng);
circleOptions.radius(radius);
circleOptions.strokeWidth(4);
circleOptions.strokeColor(Color.RED);
circleOptions.fillColor(Color.BLUE);
aMap.addCircle(circleOptions);
}
package com.pansoft.oilgas.gaodenavigation;
import android.Manifest;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Vibrator;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
public class SimpleGeoFenceActivity extends AppCompatActivity implements AMapLocationListener, LocationSource {
final String tag = SimpleGeoFenceActivity.class.getSimpleName();
final int REQ_LOCATION = 0x12;
final int REQ_GEO_FENCE = 0x13;
final String ACTION_GEO_FENCE = "geo fence action";
private AMapLocationClient mLocationClient;
private AMapLocationClientOption mLocationOption;
private IntentFilter intentFilter;
private Vibrator vibrator;
private LatLng centerLatLng;
private MapView mapView;
private AMap aMap;
private OnLocationChangedListener onLocationChangedListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mapView = new MapView(this);
setContentView(mapView);
mapView.onCreate(savedInstanceState);
aMap = mapView.getMap();
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
mLocationClient = new AMapLocationClient(this);
mLocationOption = new AMapLocationClientOption();
mLocationClient.setLocationListener(this);
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mLocationOption.setInterval(2000);
mLocationClient.setLocationOption(mLocationOption);
applyPermission();
//处理进出地理围栏事件
intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_GEO_FENCE);
//show my location
aMap.setLocationSource(this);
aMap.getUiSettings().setMyLocationButtonEnabled(true);
aMap.setMyLocationEnabled(true);
aMap.setMyLocationType(AMap.LOCATION_TYPE_MAP_FOLLOW);
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
this.registerReceiver(broadcastReceiver, intentFilter);
}
BroadcastReceiver
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 接收广播
if (intent.getAction().equals(ACTION_GEO_FENCE)) {
Bundle bundle = intent.getExtras();
// 根据广播的event来确定是在区域内还是在区域外
int status = bundle.getInt("event");
String geoFenceId = bundle.getString("fenceId");
if (status == 1) {
Toast.makeText(SimpleGeoFenceActivity.this, "进入地理围栏~", Toast.LENGTH_LONG).show();
vibrator.vibrate(3000);
} else if (status == 2) {
// 离开围栏区域
Toast.makeText(SimpleGeoFenceActivity.this, "离开地理围栏~", Toast.LENGTH_LONG).show();
vibrator.vibrate(3000);
}
}
}
};
@Override
protected void onStop() {
super.onStop();
this.unregisterReceiver(broadcastReceiver);
}
public void applyPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQ_LOCATION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQ_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationClient.startLocation();
} else {
Toast.makeText(SimpleGeoFenceActivity.this, "没有权限,无法获取位置信息~", Toast.LENGTH_LONG).show();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onLocationChanged(AMapLocation loc) {
if (loc != null && loc.getErrorCode() == 0) {
//设置地理围栏
if (centerLatLng == null) {
centerLatLng = new LatLng(loc.getLatitude(), loc.getLongitude());
Intent intent = new Intent(ACTION_GEO_FENCE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, REQ_GEO_FENCE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//100:是围栏半径(测试发现,设置的太小,不会发出广播);-1:是超时时间(单位:ms,-1代表永不超时)
mLocationClient.addGeoFenceAlert("fenceId", centerLatLng.latitude, centerLatLng.longitude, 100, -1, pendingIntent);
addCircle(centerLatLng,100);
} else {
double latitude = loc.getLatitude();
double longitude = loc.getLongitude();
Log.d(tag, "当前经纬度: " + latitude + "," + longitude);
LatLng endLatlng = new LatLng(loc.getLatitude(), loc.getLongitude());
// 计算量坐标点距离
double distances = AMapUtils.calculateLineDistance(centerLatLng, endLatlng);
Toast.makeText(SimpleGeoFenceActivity.this, "当前距离中心点:" + ((int) distances), Toast.LENGTH_LONG).show();
if (onLocationChangedListener != null) {
onLocationChangedListener.onLocationChanged(loc);
}
}
}
}
public void addCircle(LatLng latLng,int radius){
CircleOptions circleOptions=new CircleOptions();
circleOptions.center(latLng);
circleOptions.radius(radius);
circleOptions.strokeWidth(4);
circleOptions.strokeColor(Color.RED);
circleOptions.fillColor(Color.BLUE);
aMap.addCircle(circleOptions);
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
this.onLocationChangedListener = onLocationChangedListener;
}
@Override
public void deactivate() {
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
}
}
这里有一个不大好的地方,就是不能够是地图自动缩放到围栏范围!
经过和高德工程师交流,找到了地图缩放的方法
地图缩放