高德地图——地理围栏

这里使用的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();
        }

    }
}

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

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

### 高德地图 API 创建地理围栏教程 #### 地理围栏概述 地理围栏是一种基于位置的服务,允许应用程序定义虚拟边界。当设备进入或离开此区域时触发特定事件。高德地图提供了强大的API支持来创建和管理这些地理围栏。 #### 导入 SDK 库文件 为了在 Java 项目中使用高德地图的相关功能,需先从高德开放平台的开发者中心下载并引入 SDK[^4]。 #### 初始化 Map 对象 在页面上显示地图之前,需要实例化 `AMap` 类的对象。这一步骤通常通过 JavaScript 实现,在 HTML 文件内完成配置: ```html <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=<Your_Key>"></script> <div id="container" style="width:800px;height:600px;"></div> <script type="text/javascript"> var map = new AMap.Map('container', { zoom: 10, center: [116.397428, 39.90923] }); </script> ``` #### 添加地理围栏 要向地图添加圆形或多边形形式的地理围栏,可以利用 `CircleEditor` 或者 `PolygonEditor` 工具来进行绘制,并设置监听器捕捉进出范围内的变化情况。下面是一个简单的例子,展示了如何构建一个固定的圆形单位作为地理围栏: ```javascript // 定义一个圆心坐标点 var circleCenter = new AMap.LngLat(116.397428, 39.90923); // 构建一个新的圆形对象 var circle = new AMap.Circle({ center: circleCenter, // 设置圆心的位置 radius: 1000, // 半径大小(单位米) strokeColor: "#FF33FF", // 边框颜色 strokeOpacity: 1, // 边框透明度 strokeWeight: 3, // 边框宽度 fillColor: "#FFCC66", // 填充颜色 fillOpacity: 0.5 // 填充透明度 }); // 将该圆形添加至地图层面上 circle.setMap(map); ``` #### 处理地理围栏事件 一旦设置了地理围栏,则可以通过监听用户的移动轨迹判断是否进入了预设区域内。为此目的,可采用 `Geolocation` 插件获取当前位置信息并与已知的地理围栏进行匹配测试。 ```javascript function initGeoFence() { AMap.plugin(['AMap.Geolocation'], function () { geolocation = new AMap.Geolocation({ enableHighAccuracy: true,// 是否使用高精度定位默认:true timeout: 10000 // 超过10秒后停止定位默认:无穷大 }); map.addControl(geolocation); // 开始定位 geolocation.getCurrentPosition(function (status, result) { if (!result || !result.position){ console.log("无法获得当前位置"); return; } let lnglat = result.position; // 判断当前经纬度是否位于指定范围内 if(circle.contains(lnglat)){ alert("您已经进入到设定好的地理围栏内部!"); }else{ alert("您的位置不在地理围栏之内"); } }); }); } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值