Detect coming back from app settings/background with React Native

Viewed 3078

My app asks permission to use location services.

If a user denies permission, they can click a button to go to the settings page and grant permissions.

On ios, they are given the option to return directly to the app. on Android, I think they can do something similar.

Is there a way to detect arriving back at the app so I can check their permissions again?

I've tried with React Navigation's useFocusEffect hook:

useFocusEffect(
    React.useCallback(() => {
        console.log("navigated")
        return () => getPosition()
    }, [])
)

But unfortunately, that only works when navigating between screens/routes in the app.

Is there a way to detect the app transitioning from background to foreground?

3 Answers

Ciao, when I want to manage permission, I use react-native-permissions. In this way you can manage all permissions directly in your app without exit from it.

Works well for iOs and Android. In your case, you could something like:

import {check, PERMISSIONS, RESULTS} from 'react-native-permissions';

check(<permission you need>)
  .then((result) => {
    switch (result) {
      case RESULTS.UNAVAILABLE:
        console.log(
          'This feature is not available (on this device / in this context)',
        );
        break;
      case RESULTS.DENIED:
        console.log(
          'The permission has not been requested / is denied but requestable',
        );
        break;
      case RESULTS.GRANTED:
        console.log('The permission is granted');
        break;
      case RESULTS.BLOCKED:
        console.log('The permission is denied and not requestable anymore');
        break;
    }
  })
  .catch((error) => {
    // …
  });

Use this hook:

// hooks/useAppIsActive.ts

import { useCallback, useEffect, useRef } from "react";
import { AppState } from "react-native";

export default (callback: Function) => {
  const appStateRef = useRef(AppState.currentState);
  const handleAppStateChange = useCallback((nextAppState) => {
    if (
      appStateRef.current.match(/inactive|background/) &&
      nextAppState === "active"
    ) {
      callback();
    }

    appStateRef.current = nextAppState;
  }, []);

  useEffect(() => {
    AppState.addEventListener("change", handleAppStateChange);
    return () => {
      AppState.removeEventListener("change", handleAppStateChange);
    };
  }, []);
};

And from the component you want to detect "the come back", pass by parameter the callback you want to run:

const MyView = () => {
  const requestLocationAccess = useCallback(() => {
    // request permissions...
  }, [])

  useAppIsActive(() => requestLocationAccess());
}
Related