当前位置: 首页 > 知识库问答 >
问题:

Android 8或9的后台地理Geofence不起作用

朱令
2023-03-14

我尝试在用户到达定义的区域时向其显示推送警报。

所以我在https://developer.android.com/training/location/geofencing编写了我的应用程序

如果我的应用使用遵循用户位置的服务运行,则它可以正常工作。

例如,如果我启动谷歌地图,它也会跟踪我的位置。推送会出现。

但是,如果我关闭我的应用程序,推送将不会显示,因此如果没有应用程序跟踪我的位置,则不会检测到地理Geofence。

这正常吗?如何使其始终有效?如果您需要跟踪您的位置的前台服务,地理Geofence的意义何在?

 public void createGeofenceAlerts(LatLng latLng, int radius) {
    final Geofence enter = buildGeofence(ID_ENTER, latLng, radius, Geofence.GEOFENCE_TRANSITION_ENTER);
    final Geofence exit = buildGeofence(ID_EXIT, latLng, radius, Geofence.GEOFENCE_TRANSITION_EXIT);
    final Geofence dwell = buildGeofence(ID_DWELL, latLng, radius, Geofence.GEOFENCE_TRANSITION_DWELL);

    GeofencingRequest request = new GeofencingRequest.Builder()
            .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofence(enter)
            .addGeofence(exit)
            .addGeofence(dwell)
            .build();

    fencingClient.addGeofences(request, getGeofencePendingIntent()).addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Timber.i("succes");
            Toast.makeText(mContext, "Geofence added", Toast.LENGTH_LONG).show();
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Timber.e(e,"failure");
            Toast.makeText(mContext, "Geofence ERROR", Toast.LENGTH_LONG).show();
        }
    });
}

private PendingIntent getGeofencePendingIntent() {
    Intent intent = new Intent(mContext, GeofenceTransitionsIntentService.class);
    PendingIntent pending = PendingIntent.getService(
            mContext,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    return pending;
}

private Geofence buildGeofence(String id, LatLng center, int radius, int transitionType) {
    Geofence.Builder builder = new Geofence.Builder()
            // 1
            .setRequestId(id)
            // 2
            .setCircularRegion(
                    center.getLatitude(),
                    center.getLongitude(),
                    radius)
            // 3
            .setTransitionTypes(transitionType)
            // 4
            .setExpirationDuration(Geofence.NEVER_EXPIRE);
    if (transitionType == Geofence.GEOFENCE_TRANSITION_DWELL) {
        builder.setLoiteringDelay(LOITERING_DELAY);
    }

    return builder.build();
}

共有3个答案

滕璞瑜
2023-03-14

我发现我的地理Geofence短信接收器开始在模拟器中正常工作,当我打开谷歌地图。我根本无法弄清楚问题出在哪里,事实证明,我显然错过了一块拼图。这个问题(标题恰如其分):地理Geofence广播接收器没有被触发,但当我打开谷歌地图时,它的工作原理,以及在Android位置样本项目中多次提交问题问题239,问题247问题266。

我没有看到这个问题的实际答案作为答案发布在这里,所以对于后代,我将提供一些建议。第264期似乎指向了解决方案,即使用JobIntentService

地理Geofence示例位置更新本服务中有一个代码注释

注意:当应用不再处于前台时,在“O”设备上运行的应用程序(无论目标SdkVersion如何)接收更新的频率可能低于{@linkcom.google.android.gms.location.LocationRequest}中指定的间隔。

这似乎证实了@Vinayak在他的回答中所指出的

O. S将不允许应用程序从后台获取位置更新。在前台服务上实现地理Geofence位置代码。它将按预期运行

不允许地理Geofence广播接收器及时获取位置更新(显然即使在意图服务中也是如此)。您必须在前台服务中运行位置客户端,该服务请求精细的位置访问,以获得更准确/更及时的地理Geofence触发。因此,似乎正确的答案是在前台服务中运行地理Geofence。

如果您选择foreGroundService路由,您还需要创建一个通知通道,否则,您将遇到像这样的问题。

另见:

https://developer.android.com/guide/components/foreground-services

https://developer.android.com/training/location/change-location-settings#location-请求

https://developer.android.com/training/location/request-updates

https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient.html#requestLocationUpdates(com.google.android.gms.location.LocationRequest,com.google.android.gms.location.LocationCallback)

贺佑运
2023-03-14

我想我找到了一个解决方案,在Android 9上进行了测试。我使用了Google文档 https://developer.android.com/training/location/geofencing 但我用广播接收器替换了该服务。

我的地理Geofence经理 :

private val braodcastPendingIntent: PendingIntent
    get() {
        val intent = Intent(mContext, GeofenceTransitionsBroadcastReceiver::class.java)
        val pending = PendingIntent.getBroadcast(
                mContext.applicationContext,
                0,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT)
        return pending
    }

 fun createGeofenceAlerts(latLng: LatLng, radiusMeter: Int, isBroadcast: Boolean) {
    val enter = buildGeofence(ID_ENTER, latLng, radiusMeter, Geofence.GEOFENCE_TRANSITION_ENTER)
    val exit = buildGeofence(ID_EXIT, latLng, radiusMeter, Geofence.GEOFENCE_TRANSITION_EXIT)
    val dwell = buildGeofence(ID_DWELL, latLng, radiusMeter, Geofence.GEOFENCE_TRANSITION_DWELL)

    val request = GeofencingRequest.Builder()
            .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofence(enter)
            .addGeofence(exit)
            .addGeofence(dwell)
            .build()

    val pending = if (isBroadcast) {
        braodcastPendingIntent
    } else {
        servicePendingIntent
    }
    fencingClient.addGeofences(request, pending).addOnSuccessListener {
        Timber.i("succes")
        Toast.makeText(mContext, "Geofence added", Toast.LENGTH_LONG).show()
    }.addOnFailureListener { e ->
        Timber.e(e, "failure")
        Toast.makeText(mContext, "Geofence ERROR", Toast.LENGTH_LONG).show()
    }
}

private fun buildGeofence(id: String, center: LatLng, radius: Int, transitionType: Int): Geofence {
    val builder = Geofence.Builder()
            // 1
            .setRequestId(id)
            // 2
            .setCircularRegion(
                    center.latitude,
                    center.longitude,
                    radius.toFloat())
            // 3
            .setTransitionTypes(transitionType)
            // 4
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
    if (transitionType == Geofence.GEOFENCE_TRANSITION_DWELL) {
        builder.setLoiteringDelay(LOITERING_DELAY)
    }

    return builder.build()
}

我的广播接收器,显然你需要在最短时间内声明:

class GeofenceTransitionsBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
    Timber.i("received")
    val geofencingEvent = GeofencingEvent.fromIntent(intent)
    if (geofencingEvent.hasError()) {
        Timber.e("Geofence error")
        return
    }

    // Get the transition type.
    val geofenceTransition = geofencingEvent.geofenceTransition

    // Test that the reported transition was of interest.
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT
            || geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) {

        // Get the geofences that were triggered. A single event can trigger
        // multiple geofences.
        val triggeringGeofences = geofencingEvent.triggeringGeofences

        // Get the transition details as a String.
        val geofenceTransitionDetails = GeofenceManager.getGeofenceTransitionDetails(
                geofenceTransition,
                triggeringGeofences, true
        )

        // Send notification and log the transition details.
        GeofenceManager.sendNotification(context, geofenceTransition, geofenceTransitionDetails)
        Timber.i(geofenceTransitionDetails)
    } else {
        // Log the error.
        Timber.e("Unknown geo event : %d", geofenceTransition)
    }
}

重要的是要知道,在Android 8和9上,地理Geofence的延迟为2分钟。

孙经艺
2023-03-14

我与GeoFence合作了很长时间,我有同样的问题,在尝试了不同的解决方案后,我自己找到了答案,所以基本上,GeoFence只有在手机中的任何应用程序在某个x持续时间内获取位置时才会得到触发。如果你测试谷歌提供的GeoFence示例应用程序,那么你可以看到该应用程序只有在你打开谷歌地图应用程序时才能工作,因为谷歌地图是设备中唯一被动请求位置的应用程序。

为了证明,您可以从下面的链接克隆GeoFence示例和LocationUpdateForGroundService示例https://github.com/googlesamples/android-play-location同时运行GeoFence和LocationUpdateForGroundService,您会注意到,通过更改模拟器中的lat和long,现在您不再需要打开Google地图,因为现在有另一个应用程序正在请求位置。

因此,请在 GeoFence 应用程序中创建前台服务,并使用 Fuse 位置客户端请求一定 x 持续时间的位置更新。

 类似资料:
  • 为了创建一个位置跟踪系统(基于fusedlocationprovider),该系统必须跟踪一个人在特定时间段内的位置。 在特定的时间间隔内,需要广播位置,即使应用程序关闭,也不应终止服务。 我应该使用前台还是后台服务,或者两者结合使用,再加上一个解释会很有帮助。

  • 如何从多个地理位置(长,晚值)创建多边形地理围栏。也可以在Android上跟踪用户进入或退出该地理区域的情况。

  • 我有一个包含许多文档集合,其结构如下: 纬度范围为[25;55] 该收藏包含大约60万条记录。 我设置了2D_Sphere索引:db.myCollection.createIndex({location:“2DSphere”}) 我获得了所有的记录,但我只期望有几个记录(靠近我的坐标!) 有什么建议吗?提前致谢

  • 问题内容: 我在iOS上的FCM通知有问题。 我收到成功通知时,我的应用程序是在前台(回调中被激发),但是当应用程序在后台(我看不出在iOS中的通知栏的任何东西)我没有收到通知。 因此,我认为问题在于FCM发送的消息格式。我的服务器发送到FCM的json格式如下: 如您所见,我的json中有两个块:一个通知块(用于在后台接收通知)和一个数据块(用于在前台接收通知)。 我不明白为什么没有收到后台通知

  • 根据API文件,只允许圆形土工篱笆: 但我有4个位置,代表矩形的4个角,我想让我的地理围栏是那个矩形。 我想避免建立我的自定义位置监控服务的解决方案扩展的功能监测地理围栏,因为我认为这类服务是CPU和功耗消耗。 谢谢,