Android Google Geofence偶尔无法触发区域检测的问题求助
Android Google Geofence偶尔无法触发区域检测的问题求助
大家好,我最近基于Google Geofence实现了一个功能:用前台服务配合BroadcastReceiver监听地理围栏的进入、停留和离开事件,一共设置了两个地理围栏区域。但测试三天后发现,地理围栏偶尔会出现不触发的情况——明明已经进入/离开目标区域,却收不到预期的通知提醒。
我把目前实现的核心代码贴在下面,麻烦各位帮忙排查一下可能的问题点?
GeofenceBroadcastReceiver 代码
class GeofenceBroadcastReceiver : BroadcastReceiver() { private val tag = "Broadcast =>" private val channel_id = "Geofence Channel" override fun onReceive(context: Context?, intent: Intent?) { // 初始化地理围栏事件 val geofencingEvent = GeofencingEvent.fromIntent(intent!!) if (geofencingEvent!!.hasError()) { val errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.errorCode) Log.e(tag, errorMessage) return } // 根据围栏状态切换处理逻辑 when (geofencingEvent.geofenceTransition) { Geofence.GEOFENCE_TRANSITION_ENTER -> { sendNotification(context!!,"Enterance",geofencingEvent.triggeringLocation) } Geofence.GEOFENCE_TRANSITION_DWELL -> { sendNotification(context!!,"Dwell",geofencingEvent.triggeringLocation) } Geofence.GEOFENCE_TRANSITION_EXIT -> { sendNotification(context!!, "Exit",geofencingEvent.triggeringLocation) } else -> { Log.e(tag, "Error in setting up the geofence") } } } private fun sendNotification(context: Context, type: String, location: Location?) { val channelId = "Geofence" val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val priority = NotificationCompat.PRIORITY_HIGH val channelPriority = NotificationManager.IMPORTANCE_HIGH val notificationManager = getSystemService(context, NotificationManager::class.java) as NotificationManager // Android O及以上创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val mChannel = NotificationChannel(channel_id, channelId, NotificationManager.IMPORTANCE_HIGH) mChannel.enableLights(true) mChannel.lightColor = Color.GREEN mChannel.enableVibration(false) notificationManager.createNotificationChannel(mChannel) } // 点击通知跳转主页面 val contentIntent = Intent(context, MainActivity::class.java) val random = Random() val NOTIFICATION_ID: Int = random.nextInt(9999 - 1000) + 1000 val pendingIntent = PendingIntent.getActivity( context, NOTIFICATION_ID, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE ) // 构建通知 val notification = NotificationCompat.Builder(context, channel_id) .setContentTitle("GeoFence App") .setContentText("You have $type the geofence area : ${location?.latitude} , ${location?.longitude}") .setSmallIcon(R.drawable.ic_launcher_foreground) .setAutoCancel(true) .setDefaults(Notification.DEFAULT_ALL) .setLights(ContextCompat.getColor(context, R.color.purple_200), 50, 10) .setContentIntent(pendingIntent) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .build() // 补充创建第二个通知渠道(原代码逻辑) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "Channel Culpability", channelPriority ) notificationManager.createNotificationChannel(channel) } val notificationCode = (Math.random() * 1000).toInt() notificationManager.notify(notificationCode, notification) } }
GeofenceService 代码
class GeofenceService : Service() { companion object { private const val TAG = "GeofenceService" } private lateinit var geofencingClient: GeofencingClient private val geofenceList = mutableListOf<Geofence>() // private var latitude: Double? = null // private var longitude: Double? = null // 懒加载地理围栏触发的PendingIntent private val geofencePendingIntent: PendingIntent by lazy { val intent = Intent(this, GeofenceBroadcastReceiver::class.java) PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE ) } override fun onCreate() { super.onCreate() } override fun onBind(intent: Intent?): IBinder? { return null } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { intent?.action.let { when (it) { Actions.START_SERVICE.toString() -> { try { // 启动前台定位服务 ServiceCompat.startForeground( this@GeofenceService, 100, notification(), if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION } else { 0 } ) startGeofence() } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { if (e is ForegroundServiceTypeException) { println(" $TAG onStartCommand Action : START_SERVICE : exception : ${e.localizedMessage}") } } } } Actions.STOP_SERVICE.toString() -> { stopSelf() } else -> {} } } return START_STICKY } private fun startGeofence() { geofencingClient = LocationServices.getGeofencingClient(this) createGeofence() } private fun notification(): Notification { val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val channel = NotificationChannel( "geofence_default_channel", "FCM Notifications", NotificationManager.IMPORTANCE_HIGH ) notificationManager.createNotificationChannel(channel) // 补充完整通知构建逻辑(原代码未写完) return NotificationCompat.Builder(this, "geofence_default_channel") .setContentTitle("Geofence Service Active") .setSmallIcon(R.drawable.ic_launcher_foreground) .setPriority(NotificationCompat.PRIORITY_HIGH) .build() } // 原代码中该方法未实现完整逻辑,此处保留示例注释 private fun createGeofence() { // 示例:构建地理围栏并添加到客户端 // val geofence1 = Geofence.Builder() // .setRequestId("geofence_1") // .setCircularRegion(31.2304, 121.4737, 100f) // 自定义经纬度和半径 // .setExpirationDuration(Geofence.NEVER_EXPIRE) // .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT or Geofence.GEOFENCE_TRANSITION_DWELL) // .setLoiteringDelay(30000) // 停留30秒触发Dwell事件 // .build() // geofenceList.add(geofence1) // // val geofencingRequest = GeofencingRequest.Builder() // .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) // .addGeofences(geofenceList) // .build() // // geofencingClient.addGeofences(geofencingRequest, geofencePendingIntent) // .addOnSuccessListener { Log.d(TAG, "Geofences added successfully") } // .addOnFailureListener { Log.e(TAG, "Failed to add geofences: ${it.message}") } } }
补充说明:我已经添加了必要的权限(ACCESS_FINE_LOCATION、Android 10+的ACCESS_BACKGROUND_LOCATION),前台服务也能正常在通知栏显示,就是偶尔会出现地理围栏不触发的情况,实在找不到原因了…
内容来源于stack exchange
相关产品推荐
相关产品推荐

