添加 Geofence 使 ApiException 状态为 13

Adding Geofence gives ApiException status 13

最近 运行 遇到一个问题,其中添加地理围栏会随机失败并出现 ApiException,状态代码 13 定义为 "ERROR" 未提供额外的详细信息。

通常错误代码是特定于地理围栏的,但这似乎是一个普遍的失败。有没有人知道为什么 GeofencingClient 会 return 状态代码 13?我找不到遇到同样问题的人。

这似乎影响了应用程序的旧版本,之前它可以正常运行。

我已经仔细检查了 latitude/longitude 是有效坐标,相同的数据有时可以正常工作。我已经尝试使用不同的 API 键进行初始化,以防 maps/location 服务出现问题,但这没有任何区别。

我也试过从 GeofencingClient(context)LocationServices.getGeofencingClient(context) 没有变化。

我试过升级库版本,没有区别。

具有播放服务版本和 API 键定义的典型清单设置;

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version"/>

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="@string/maps_api_key"/>

<service android:name=".GeofenceTransitionsIntentService"/>

这里添加了地理围栏,没有任何结果到达意图服务

private val geofencingClient = GeofencingClient(context)

private val geofencePendingIntent =
            PendingIntent.getService(context, 0, Intent(context, GeofenceTransitionsIntentService::class.java), PendingIntent.FLAG_UPDATE_CURRENT)

fun setGeofence(latitude: Double, longitude: Double, radius: Float, geofenceId: String) {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            val geofenceList = listOf(buildGeofence(latitude, longitude, radius, geofenceId))
            geofencingClient.addGeofences(getGeofencingRequest(geofenceList), geofencePendingIntent)?.run {
                addOnFailureListener {
                    // Failed to add geofences
                    geofenceErrorListener?.invoke("Failed to add Geofence: ${it.message}")
                }
            }
        }
    }

这直到最近才成为问题,现在几乎 100% 的时间都在发生。

com.google.android.gms.common.api.ApiException: 13:

编辑:从 PlayServices 版本 17.7.85(在我的设备上)开始,问题似乎已在 Google 端解决

我正在使用 Android Q Beta 进行一些测试,并注意到如果我的应用程序具有新的 "Allow only while using the app" 位置权限,我总是会收到此错误。即使应用程序在前台,我也永远无法添加任何位置权限设置为 "Allow only while using the app" 的地理围栏,但是一旦我将应用程序的位置权限设置为 "Allow all the time",我就可以毫无问题地添加地理围栏.

不过,我在其他 API 版本上仍然看到这个问题,所以不幸的是它并没有真正完全解决问题。我有一台设备 运行 Android 8.0 和一台 运行 Android 9.0,我仍然偶尔会看到状态错误 #13。我不确定在这些设备上可以做什么,因为它们没有新的 "Allow only while using the app" 权限。他们都有完整的位置访问权限。

我添加这个答案是因为它可能会帮助一些 运行 Android Q Beta 用户,或者至少阐明可能导致问题的原因。我确实认为它与最新的 Google Play 服务版本有关,因为我认为我们所做的一切都是正确的。

编辑: 如果有人有兴趣关注,我已经在 Google 的问题跟踪器上添加了一个问题... https://issuetracker.google.com/issues/135771329

尽管我没有对应用程序进行任何更改,但 addGeofences StatusException: 13 错误开始经常发生在我自己和我的应用程序用户身上。在各种设备上观察 运行 Android 9. 用户在 mid-June 左右开始报告该问题。

在这里阅读之后 - 感谢 @Ldawg@StephenRuda - 并将我的评论添加到 google 问题中,我决定在添加时对应用程序进行一些推测性更改地理围栏。做了一些测试,在问题无法重现后,发布了 Beta,然后 Production 发布到 Play 商店。新版本尚未观察到该问题。

我正在发布我修改后的解决方案以防它对任何人有帮助,但它在概念上看起来与 Ldawg 最初发布的错误相似。此外,我还没有能够对以前的版本进行回归测试,看看它是否仍然像以前一样发生。由于这是一个没有描述的不透明错误,因此它并非不可想象,它是由 gms 中的不同状态引起的多个触发器。在 Google 他们自己证实这一点之前,修复是推测性的,问题有点难以捉摸。

我的修复中的基本变化是之前, rxLocationProvider.addGeofencesrxLocationProvider.removeGeofences 在每个位置的循环中多次调用,并观察到 ​​status 13 错误。

更改后,rxLocationProvider.addGeofences 仅使用 Geofence 对象列表调用一次。 rxLocationProvider.removeGeofences 也采用位置列表而不是单个位置。该应用程序使用 mcharmas android 反应式位置库 https://github.com/mcharmas/Android-ReactiveLocation

StatusException: 13

之前的代码
private GeofencingRequest createGeofencingRequest(String requestId) {
        Geofence geofence = new Geofence.Builder()
                .setRequestId(requestId)
                .setCircularRegion(stationInfo.getLat(), stationInfo.getLon(), GEOFENCE_RADIUS_METRES)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                .build();
        return new GeofencingRequest.Builder().addGeofence(geofence).build();
    }

public void addGeofence(String locationCrs) {
        final GeofencingRequest geofencingRequest = createGeofencingRequest(locationCrs);
        final PendingIntent pendingIntent = createNotificationBroadcastPendingIntent();

        ArrayList<String> lists = new ArrayList<>();
        lists.add(locationCrs);
        rxLocationProvider
                .removeGeofences(lists)
                .flatMap((Function<Status, Observable<Status>>)
                        status -> rxLocationProvider.addGeofences(pendingIntent, geofencingRequest))
                .subscribe(addGeofenceResult -> {

                }, throwable -> {
                    // **Status 13 here**
                }));
    }

之后的代码 - 没有观察到错误

private GeofencingRequest getGeofencingRequest() {
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofences(geofenceList);
        return builder.build();
    }

private Geofence createGeofence(String requestId) {
        return new Geofence.Builder()
                .setRequestId(requestId)
                .setCircularRegion(stationInfo.getLat(), stationInfo.getLon(), GEOFENCE_RADIUS_METRES)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                .build();
    }

public void addGeofences(List<String> locs) {
        for (String loc : locs) {
            Geofence request = createGeofence(loc);
            geofenceList.add(request);
        }

        final PendingIntent pendingIntent = createNotificationBroadcastPendingIntent();

        disposable.add(rxLocationProvider
                .removeGeofences(locs)
                .flatMap((Function<Status, Observable<Status>>)
                        status -> rxLocationProvider.addGeofences(pendingIntent, getGeofencingRequest()))
                .subscribe(addGeofenceResult -> {

                }, throwable -> {
                    // **No Errors observed**
                }));
    }

Google 回复我们,让我们知道他们已经推出了针对此问题的修复程序。我能够确认我的 non-working 设备现在可以正常工作。

如果你用的是API29或者android10phonethi就是这样。您需要在清单中声明使用:

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

而且,如果你请求权限,你必须同时请求:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

在您的代码意图中调用 android 8 9 10 或更高权限以使地理围栏工作 我用 dexter

Dexter.withActivity(this@Activity_Map)
        .withPermissions(
                Manifest.permission.ACCESS_COARSE_LOCATION
                ,Manifest.permission.ACCESS_FINE_LOCATION
                ,Manifest.permission.ACCESS_BACKGROUND_LOCATION
        )
        .withListener(object: MultiplePermissionsListener {
            override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                report?.let {
                    if(report.areAllPermissionsGranted()){
                        aktifkangps()
                        ambilshareddprefnip()
                        geofencingClient = LocationServices.getGeofencingClient(this@Activity_Map)      //drawgeo()
                        cekInternet()
                        with(sharedPreferences) {
                            status = getString(loginmasuk.SP_NIP   , "0").toString()
                        }
                        if (status == "failed"){
                            val imap = Intent(this@Activity_Map, Activity_ambil_lokasi::class.java)
                            startActivity(imap)
                            finish()
                        }
            }

在我将编译和targetSdkVersion 更改为29 后,我遇到了同样的问题。首先它说 com.google.android.gms.common.api.apiexception 13
对于这个错误,我将 build.gradle 中的所有依赖项更改为最新版本。
在那之后,我发现了新的错误com.google.android.gms.common.api.apiexception 1004
然后我按上面的方式添加权限ACCESS_BACKGROUND_LOCATION,终于我的app又好了!

将此权限添加到清单文件中。

  1. 互联网
  2. ACCESS_FINE_LOCATION
  3. WAKE_LOCK
  4. ACCESS_COARSE_LOCATION
  5. ACCESS_BACKGROUND_LOCATION

并尝试允许“每次”位置权限,因为有时该权限仅在使用该应用程序时有效。 你应该一直允许权限。

这样你就不会得到 "com.google.android.gms.common.api.ApiException: 13:"

当应用程序的位置访问设置设置为 Allow only while using the app 时,我收到此错误。

要解决此问题,请转到位置设置,找到您的应用并将设置更改为 Allow all the time