合作咨询
我们的专家服务团队将竭诚为您提供专业的合作咨询服务
如果您对某些地点比较关注,您可以根据关注地点的位置,创建地理围栏createGeofenceList,地理围栏可以感知当前设备所在位置和您的关注目标之间的距离,当用户进入围栏区域时,会向应用发起通知。同时,您可以检测用户在围栏内的停留时间,当用户在围栏内停留一段时间之后,再发起通知。
要使用地理围栏服务API,需要确保您的设备已经下载并安装了HMS Core(APK),并将Location Kit的SDK集成到您的项目中。有关详细信息,请参见开发准备。以下仅为代码片段,详情请参见示例代码。
地理围栏设置的位置信息使用WGS-84坐标系。
请参见12.3 支持地理围栏的设备。
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
以上地理围栏相关权限属于危险权限,使用时需要动态申请。
地理围栏触发信息通过广播接收,需要在“AndroidManifest.xml”文件中注册广播接收器。
- <!--注册地理围栏服务广播接收器-->
- <receiver
- android:name=".geofence.GeoFenceBroadcastReceiver"
- android:exported="true">
- <intent-filter>
- <action android:name="com.huawei.hmssample.geofence.GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION" />
- </intent-filter>
- </receiver>
- private GeofenceService geofenceService;
- private ArrayList<String> idList;
- private ArrayList<Geofence> geofenceList;
- private String TAG;
- private PendingIntent pendingIntent;
- // 创建一个新的GeofenceService实例
- geofenceService = LocationServices.getGeofenceService(this);
- // 获取PendingIntent对象
- pendingIntent = getPendingIntent();
- idList = new ArrayList<String>();
- geofenceList = new ArrayList<Geofence>();
- private var geofenceService: GeofenceService? = null
- private var idList: ArrayList<String>? = null
- private var geofenceList: ArrayList<Geofence>? = null
- private var TAG: String? = null
- private var pendingIntent: PendingIntent? = null
- // 创建一个新的GeofenceService实例
- geofenceService = LocationServices.getGeofenceService(this)
- // 获取PendingIntent对象
- pendingIntent = getPendingIntent()
- idList = ArrayList()
- geofenceList = ArrayList()
您可以先创建地理围栏实例,并构建添加地理围栏的请求。在发送请求之后,会通过Task通知您是否添加成功。
- geofenceList.add(new Geofence.Builder()
- .setUniqueId("mGeofence")
- .setValidContinueTime(10000)
- // 传入经纬度信息,圆形地理围栏半径(单位:米)
- .setRoundArea(latitude, longitude, radius)
- // 进入或退出围栏时触发回调
- .setConversions(Geofence.ENTER_GEOFENCE_CONVERSION | Geofence.EXIT_GEOFENCE_CONVERSION)
- .build());
- idList.add("mGeofence");
- geofenceList!!.add(
- Geofence.Builder()
- .setUniqueId("mGeofence")
- // 传入经纬度信息,圆形地理围栏半径(单位:米)
- .setValidContinueTime(10000)
- // 进入或退出围栏时触发回调
- .setRoundArea(latitude, longitude, radius.toFloat())
- .setConversions(Geofence.ENTER_GEOFENCE_CONVERSION or Geofence.EXIT_GEOFENCE_CONVERSION)
- .build()
- )
- idList!!.add("mGeofence")
Geofence.builder的核心方法解析
方法名 | 参数说明 | 返回值说明 | 方法效果 |
|---|---|---|---|
setConversions(int conversions) | 设置地理围栏触发类型,触发类型包含进入(值为1)、退出(值为2)、驻留(值为4)三种,支持“或”位运算 | Geofence.Builder对象 | 设置地理围栏触发类型 |
setDwellDelayTime(int dwellDelayTime) | 设置地理围栏驻留触发时间,当用户在围栏中并停留超过这个时间,则会触发围栏上报 | Geofence.Builder对象 | 设置地理围栏驻留触发时间 |
setNotificationInterval(int notificationInterval) | 设置通知响应能力,默认为0秒,如果设置的值较大,可以相应地降低功耗,但是可能会延迟上报围栏事件。 | Geofence.Builder对象 | 设置通知响应能力 |
setRoundArea(double latitude, double longitude, float radius) | 设置圆形围栏的中心点经纬度和半径 | Geofence.Builder对象 | 设置圆形围栏的中心点经纬度和半径 |
setUniqueId(String uniqueId) | 设置地理围栏的唯一ID。唯一ID是一个字符串,用于标识地理围栏。当创建地理围栏的uniqueId已存在时,新的围栏会替换旧的围栏。 | Geofence.Builder对象 | 设置地理围栏的唯一ID |
setValidContinueTime(long validContinueTime) | 设置地理围栏超时时间。超过该时间,该地理围栏将自动移除。如果值小于0时,地理围栏将会设置为永不过期。 | Geofence.Builder对象 | 设置地理围栏超时时间 |
- private GeofenceRequest getAddGeofenceRequest() {
- GeofenceRequest.Builder builder = new GeofenceRequest.Builder();
- // 当用户在围栏中时,添加围栏后立即触发回调
- builder.setInitConversions(GeofenceRequest.ENTER_INIT_CONVERSION);
- builder.createGeofenceList(geofenceList);
- return builder.build();
- }
- private fun getAddGeofenceRequest(): GeofenceRequest? {
- val builder = GeofenceRequest.Builder()
- // 当用户在围栏中时,添加围栏后立即触发回调
- builder.setInitConversions(GeofenceRequest.ENTER_INIT_CONVERSION)
- builder.createGeofenceList(geofenceList)
- return builder.build()
- }
GeofenceRequest.Builder核心方法解析
方法名 | 参数说明 | 返回值说明 | 方法效果 |
|---|---|---|---|
createGeofence(Geofence geofence) | 添加一个地理围栏。 | GeofenceRequest.Builder对象。 | 添加单个地理围栏。 |
createGeofenceList(List<Geofence> geofences) | 添加多个地理围栏。当前对于每个应用仅支持最多添加100个围栏。 | GeofenceRequest.Builder对象。 | 添加多个地理围栏。 |
setCoordinateType(int coordinateType) | 设置地理围栏坐标系类型,当前仅支持WGS-84坐标系。 | GeofenceRequest.Builder对象。 | 设置地理围栏坐标系。类型 |
setInitConversions(int initConversions) | 初始化触发类型,如果设置为0,则参数失效;默认值为GeofenceRequest.ENTER_INIT_CONVERSION | GeofenceRequest.DWELL_INIT_CONVERSION。 | GeofenceRequest.Builder对象。 | 设置初始化触发类型。 |
- // 通过PendingIntent动态注册GeoFenceBroadcastReceiver广播接收器,当触发围栏的时候,会通过广播通知。
- private PendingIntent getPendingIntent() {
- Intent intent = new Intent(this, GeoFenceBroadcastReceiver.class);
- intent.setAction(GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION);
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
- return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- } else {
- // 针对android12及以上设备需要主动配置pendingIntent的可变性,默认配置PendingIntent.FLAG_MUTABLE
- // 如果compileSdkVersion为30及以下,可将PendingIntent.FLAG_MUTABLE用 1<<25 替换
- // buildToolsVersion为31及以上才可使用PendingIntent.FLAG_MUTABLE
- return PendingIntent.getBroadcast(this, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
- }
- }
- // 通过PendingIntent动态注册GeoFenceBroadcastReceiver广播接收器,当触发围栏的时候,会通过广播通知。
- private fun getPendingIntent(): PendingIntent? {
- val intent = Intent(this, GeoFenceBroadcastReceiver::class.java)
- intent.action = GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION
- return if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
- PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
- } else {
- // 针对android12及以上设备需要主动配置pendingIntent的可变性,默认配置PendingIntent.FLAG_MUTABLE
- // 如果compileSdkVersion为30及以下,可将PendingIntent.FLAG_MUTABLE用 1<<25 替换
- // buildToolsVersion为31及以上才可使用PendingIntent.FLAG_MUTABLE
- PendingIntent.getBroadcast(
- this,
- 0,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
- )
- }
- }
- // 通过传入PendingIntent的方式添加地理围栏,并处理地理围栏添加行为的响应数据
- geofenceService.createGeofenceList(getAddGeofenceRequest(), pendingIntent)
- .addOnCompleteListener(new OnCompleteListener<Void>() {
- @Override
- public void onComplete(Task<Void> task) {
- if (task.isSuccessful()) {
- // TODO: 添加围栏成功处理
- } else {
- // TODO: 添加围栏失败处理
- }
- }
- });
- // 通过传入PendingIntent的方式添加地理围栏,并处理地理围栏添加行为的响应数据
- geofenceService.createGeofenceList(getAddGeofenceRequest(), pendingIntent)
- .addOnCompleteListener(OnCompleteListener<Void?> { task ->
- if (task.isSuccessful) {
- // TODO: 添加围栏成功处理
- } else {
- // TODO: 添加围栏失败处理
- }
- })
- // 地理围栏服务广播接收器
- public class GeoFenceBroadcastReceiver extends BroadcastReceiver {
- public static final String ACTION_PROCESS_LOCATION =
- "com.huawei.hmssample.geofence.GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent != null) {
- final String action = intent.getAction();
- if (ACTION_PROCESS_LOCATION.equals(action)) {
- // 从intent中解析出GeofenceData对象
- GeofenceData geofenceData = GeofenceData.getDataFromIntent(intent);
- if (geofenceData != null) {
- // 获取错误码
- int errorCode = geofenceData.getErrorCode();
- // 获取地理围栏触发类型
- int conversion = geofenceData.getConversion();
- // 获取触发的地理围栏信息
- List<Geofence> list = geofenceData.getConvertingGeofenceList();
- // 获取触发时的位置信息
- Location mLocation = geofenceData.getConvertingLocation();
- // 是否是正常触发围栏事件,返回false时表示出现错误
- boolean status = geofenceData.isSuccess();
- // TODO: 您可以根据返回的地理围栏信息,做相应的
- }
- }
- }
- }
- }
- // 地理围栏服务广播接收器
- class GeoFenceBroadcastReceiver : BroadcastReceiver() {
- override fun onReceive(
- context: Context,
- intent: Intent
- ) {
- if (intent != null) {
- val action = intent.action
- if (ACTION_PROCESS_LOCATION == action) {
- // 从intent中解析出GeofenceData对象
- val geofenceData = GeofenceData.getDataFromIntent(intent)
- if (geofenceData != null) {
- // 获取错误码
- val errorCode = geofenceData.errorCode
- // 获取地理围栏触发类型
- val conversion = geofenceData.conversion
- // 获取触发的地理围栏信息
- val list = geofenceData.convertingGeofenceList
- // 获取触发时的位置信息
- val mLocation: Location = geofenceData.convertingLocation
- // 是否是正常触发围栏事件,返回false时表示出现错误
- val status = geofenceData.isSuccess
- // TODO:您可以根据返回的地理围栏信息,做相应的处理
- }
- }
- }
- }
-
- companion object {
- const val ACTION_PROCESS_LOCATION =
- "com.huawei.hmssample.geofence.GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION"
- }
- }
- // 通过围栏id移除地理围栏,并处理地理围栏移除行为的响应数据
- geofenceService.deleteGeofenceList(idList).addOnCompleteListener(new OnCompleteListener<Void>() {
- @Override
- public void onComplete(Task<Void> task) {
- if (task.isSuccessful()) {
- // TODO: 移除围栏成功处理
- } else {
- // TODO: 移除围栏失败处理
- }
- }
- });
- // 通过围栏id移除地理围栏,并处理地理围栏移除行为的响应数据
- geofenceService.deleteGeofenceList(idList)
- .addOnCompleteListener(OnCompleteListener<Void?> { task ->
- if (task.isSuccessful) {
- // TODO: 移除围栏成功处理
- } else {
- // TODO: 移除围栏失败处理
- }
- })