高德地图——地理围栏

这里使用的SDK为AMap_Location_V2.5.0_20160526.jar
没有接触过高德地图的同学,请参考
加载一张高德地图

1.获取当前位置坐标

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

2.以当前位置,构建地理围栏

测试地理围栏,一直用眼睛盯着手机屏幕挺难受的。这里当地理围栏有变化的时候,让手机发生震动,添加震动权限

    <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!

3.标记地理围栏&&显示我的位置

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);
    }

5.完整代码:

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();
        }

    }
}

这里有一个不大好的地方,就是不能够是地图自动缩放到围栏范围!

经过和高德工程师交流,找到了地图缩放的方法
地图缩放

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在高德地图中,可以通过设置围栏的 Dwell 功能来实现停留时间监听。具体实现步骤如下: 1. 创建地理围栏:使用高德地图提供的 API,调用相应的接口创建地理围栏。在创建地理围栏时,需要指定围栏的中心点、半径、形状等信息。 2. 设置围栏 Dwell 监听器:在创建地理围栏后,需要为其设置 Dwell 监听器。Dwell 监听器是一种特殊的围栏监听器,它可以监听设备在围栏内停留的时间。 3. 处理 Dwell 事件:当设备停留在围栏内的时间超过设定的阈值时,Dwell 监听器会触发相应的事件。可以在事件处理程序中进行相应的处理,比如发送通知、进行数据记录等。 下面是一个示例代码,用于创建一个带有 Dwell 监听器的地理围栏: ```java // 创建围栏中心点 LatLng center = new LatLng(39.123456, 116.234567); // 创建围栏 DPoint dCenter = new DPoint(center.latitude, center.longitude); float radius = 1000; // 半径为1000米 GeoFence fence = new GeoFence.Builder() .setCenter(dCenter) .setRadius(radius) .setDwellDelay(10 * 60 * 1000) // 设置停留时间阈值为10分钟 .build(); // 创建 Dwell 监听器 DwellGeoFenceListener listener = new DwellGeoFenceListener() { @Override public void onDwellStart(String fenceId) { // 设备进入围栏并开始停留 Log.i(TAG, "Device start dwell in fence: " + fenceId); } @Override public void onDwellEnd(String fenceId) { // 设备离开围栏或停留时间不足阈值 Log.i(TAG, "Device end dwell in fence: " + fenceId); } @Override public void onDwellTrigger(String fenceId, int duration) { // 设备停留时间超过阈值 Log.i(TAG, "Device dwell trigger in fence: " + fenceId + ", duration: " + duration); } }; // 添加围栏监听器和 Dwell 监听器 GeoFenceClient client = new GeoFenceClient(getApplicationContext()); client.addGeoFence(fence, listener); ``` 在上面的示例代码中,`setDwellDelay` 方法用于设置停留时间阈值,单位为毫秒。`DwellGeoFenceListener` 是一个特殊的围栏监听器,用于监听围栏内的停留事件。`onDwellStart` 方法用于处理设备进入围栏并开始停留的事件,`onDwellEnd` 方法用于处理设备离开围栏或停留时间不足阈值的事件,`onDwellTrigger` 方法用于处理设备停留时间超过阈值的事件。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值