You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 11:03:09