expo: expo-location crashes with Unable to resume activity

Summary

https://forums.expo.dev/t/unable-to-resume-activity/63114

I’ve decided to create this here, hoping for some kind of answer, since the expo forums are a no-go, most of the time.

The bug is surely with the expo-location module, and not with the app, since there are multiple users having the same issue, and the crash occurs thousands of times on our customer’s devices, as we have about ~50K devices with the app installed, so it affects quite a lot of people.

I’ve tried describing it into the forum thread, so I’m not sure if I should paste it here as well, but as a summary, this seems to happen when you leave the app in the background during the night, and open it in the morning, since it mostly occurs during the morning, as another developer mentioned on the forum.

Caused by java.lang.NullPointerException
       at java.util.Objects.requireNonNull(Objects.java:220)
       at expo.modules.location.LocationModule.handleForegroundLocationPermissions(LocationModule.java:839)
       at expo.modules.location.LocationModule.lambda$requestForegroundPermissionsAsync$2$LocationModule(LocationModule.java:195)
       at expo.modules.location.-$$Lambda$LocationModule$D--6Q7JrlKjA_yBo0ZZZH8hwBGk.onResult(:4)
       at org.unimodules.adapters.react.permissions.PermissionsService$createListenerWithPendingPermissionsRequest$1.onRequestPermissionsResult(PermissionsService.kt:255)
       at com.facebook.react.ReactActivityDelegate$2.invoke(ReactActivityDelegate.java:171)
       at com.facebook.react.ReactActivityDelegate.onResume(ReactActivityDelegate.java:102)

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

managed

What platform(s) does this occur on?

Android, iOS

SDK Version (managed workflow only)

44 and 45

Environment

This is applicable to all devices … not environment dependent

Reproducible demo

It’s hard to reproduce, but the stack traces from all the users mentioning the issue I guess should be enough.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 13
  • Comments: 24 (9 by maintainers)

Commits related to this issue

Most upvoted comments

This is how to reproduce this issue -> request location permission -> Do not wait for dialog -> press home -> press lock screen -> Unlock the lock screen -> open app from launcher.

@edi - I’ve been running into this in my team’s app too, maybe my experiences will help you out too.

For us, the problem seems to come up mostly when users have location permissions denied. We were seeing all kinds of weird behaviour, buggy slow performance in the app, the constant crashes above with the same stack trace, etc, but only when a user had denied location permissions.

We had built some logic to enable/disable location watching when the app was foregrounded/backgrounded, and when re-enabling that location watching, we were calling requestForegroundPermissionsAsync. Turns out this seems to be the cause of the problem for us - repeated calls to requestForegroundPermissionsAsync appear to hang on Android when a user has denied location permissions.

I updated our app to only call requestForegroundPermissionsAsync once when the app starts up, and all subsequent re-enabling of our location watching makes use of getForegroundPermissionsAsync instead. In my own testing on my device this seems to have eliminated the problem entirely, though of course I’m just testing this myself on one device so I don’t know if it’ll fix everything. Regardless, it seems to help with what we’re doing.

In any event, hope that helps anyone who is dealing with this too.

at org.unimodules.adapters.react.permissions...

This indicates that you still have react-native-unimodules installed. This is deprecated since October 2021, see npm. You can check if you have this installed in your project somewhere with:

  • $ yarn why react-native-unimodules
  • $ npm list react-native-unimodules

Please make sure that this is not within your project.

Temporary patch that works for now:

diff --git a/node_modules/expo-location/android/src/main/java/expo/modules/location/LocationModule.java b/node_modules/expo-location/android/src/main/java/expo/modules/location/LocationModule.java
index 9a66033..14cfa41 100644
--- a/node_modules/expo-location/android/src/main/java/expo/modules/location/LocationModule.java
+++ b/node_modules/expo-location/android/src/main/java/expo/modules/location/LocationModule.java
@@ -841,6 +841,16 @@ public class LocationModule extends ExportedModule implements LifecycleEventList
   private Bundle handleForegroundLocationPermissions(Map<String, PermissionsResponse> result) {
     PermissionsResponse accessFineLocation = result.get(Manifest.permission.ACCESS_FINE_LOCATION);
     PermissionsResponse accessCoarseLocation = result.get(Manifest.permission.ACCESS_COARSE_LOCATION);
+    /**
+     * Missing permissions from OS callback should be considered as denied permissions
+     */
+    if(accessFineLocation == null) {
+      accessFineLocation = new PermissionsResponse(PermissionsStatus.DENIED, true);
+    }
+    if(accessCoarseLocation == null) {
+      accessCoarseLocation = new PermissionsResponse(PermissionsStatus.DENIED, true);
+    }
+
     Objects.requireNonNull(accessFineLocation);
     Objects.requireNonNull(accessCoarseLocation);

@jayshah123 I can do it if you don’t have time

Let me raise a PR. Will do by EOD

@endruuu I cannot do anything about that because this method is called by the react-native-maps screen, when you bring the app to foreground. I can’t do much about it there, so there must be a more graceful way to avoid a simple crash, directly in the native code from within Expo.