添加 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.addGeofences
和 rxLocationProvider.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又好了!
将此权限添加到清单文件中。
- 互联网
- ACCESS_FINE_LOCATION
- WAKE_LOCK
- ACCESS_COARSE_LOCATION
- ACCESS_BACKGROUND_LOCATION
并尝试允许“每次”位置权限,因为有时该权限仅在使用该应用程序时有效。
你应该一直允许权限。
这样你就不会得到 "com.google.android.gms.common.api.ApiException: 13:"
当应用程序的位置访问设置设置为 Allow only while using the app
时,我收到此错误。
要解决此问题,请转到位置设置,找到您的应用并将设置更改为 Allow all the time
最近 运行 遇到一个问题,其中添加地理围栏会随机失败并出现 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.addGeofences
和 rxLocationProvider.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又好了!
将此权限添加到清单文件中。
- 互联网
- ACCESS_FINE_LOCATION
- WAKE_LOCK
- ACCESS_COARSE_LOCATION
- ACCESS_BACKGROUND_LOCATION
并尝试允许“每次”位置权限,因为有时该权限仅在使用该应用程序时有效。 你应该一直允许权限。
这样你就不会得到 "com.google.android.gms.common.api.ApiException: 13:"
当应用程序的位置访问设置设置为 Allow only while using the app
时,我收到此错误。
要解决此问题,请转到位置设置,找到您的应用并将设置更改为 Allow all the time