Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location permission manual request not always works #2201

Open
Crysp opened this issue Nov 7, 2024 · 12 comments
Open

Location permission manual request not always works #2201

Crysp opened this issue Nov 7, 2024 · 12 comments

Comments

@Crysp
Copy link

Crysp commented Nov 7, 2024

Option disableLocationAuthorizationAlert doesn't work as expected. Permission is requested at app startup.

Your Environment

  • Plugin version: 4.16.2
  • Platform: iOS
  • OS version: 18.0.0
  • Device manufacturer / model: iPhone 15
  • React Native version (react-native -v): 0.75.3
  • Plugin config
{
  reset: true,
  stopOnTerminate: false,
  disableLocationAuthorizationAlert: true,
  locationAuthorizationRequest: 'Any',
}

Standalone component to reproduce

import React, { useCallback, useEffect, useState } from 'react';
import { Button } from 'react-native';
import RNBG from 'react-native-background-geolocation';

export const BugReportExample = () => {
  const [enabled, setEnabled] = useState(false);
  const onStart = useCallback(() => {
    RNBG.start(state => {
      setEnabled(state.enabled);
    });
  }, []);
  const onStop = useCallback(() => {
    RNBG.stop(state => {
      setEnabled(state.enabled);
    });
  }, []);

  useEffect(() => {
    RNBG.ready({
      reset: true,
      stopOnTerminate: false,
      disableLocationAuthorizationAlert: true,
      locationAuthorizationRequest: 'Any',
    }).then(state => {
      setEnabled(state.enabled);
    });
  }, []);

  return (
    <Button
      title={enabled ? 'Stop' : 'Start'}
      onPress={enabled ? onStop : onStart}
    />
  );
};

Expected Behavior

If some requirement is missed (for proper plug-in work) and I tell that I manually controlling requests (disableLocationAuthorizationAlert: true), there should be some warning or error during plug-in preparation (inside ready).

Actual Behavior

If location permission is missed (for "permanent" mode), plug-in will request it at app startup.

Steps to Reproduce

  1. Plug-in works in "permanent" mode (launches in background)
  2. Revoke all app permissions
  3. Launch the app
  4. Location permission appears at app startup

Context

I want to request location permission my own no matter the plug-in state is

Debug logs

Logs
PASTE_YOUR_LOGS_HERE
@christocracy
Copy link
Member

disableLocationAuthorizationAlert

This option doesn’t do what you think it does. Read about it in the api docs.

if you do not want the plug-in to request permission, don’t tell it to .start(). Calling .start() always requests permission.

listen to .onProviderChange event to learn about changes in permission.

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

No, you probably didn't understand me. Permission request at start is ok and pretty transparent.

Steps:

  1. Call start
  2. Grant necessary permission
  3. Plug-in works in "permanent" mode
  4. Terminate the app
  5. Revoke permission
  6. Launch the app
  7. Permission request appears at app startup (without any actions)

@christocracy
Copy link
Member

christocracy commented Nov 7, 2024

The plugin's State.enabled is persisted throughout app restarts / device reboots.

  • Calling .start() sets State.enabled -> true
  • Calling .stop() sets State.enabled -> false.
  • When you call .ready(config), if the plugin finds State.enabled == true, it will call .start() upon itself.
  • Calling .start() automatically requests permission.

Therefore, before calling .ready(config), you must analyze the current state of permissions using .getProviderState().

var providerState = await BackgroundGeolocation.getProviderState();

if (!providerState.enabled) {
  // If you find location-services is disabled, you must tell the plugin to .stop(), 
  // which sets State.enabled -> false
  BackgoundGeolocation.stop();
}
.
.
.
BackgroundGeolocation.ready(config)

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

It doesn't work as you write. Request still appears at app startup

import React, { useCallback, useEffect, useState } from 'react';
import { Button } from 'react-native';
import RNBG from 'react-native-background-geolocation';

export const BugReportExample = () => {
  const [enabled, setEnabled] = useState(false);
  const onStart = useCallback(() => {
    RNBG.start(state => {
      setEnabled(state.enabled);
    });
  }, []);
  const onStop = useCallback(() => {
    RNBG.stop(state => {
      setEnabled(state.enabled);
    });
  }, []);

  useEffect(() => {
    RNBG.getProviderState().then(async providerState => {
      if (providerState.enabled) {
        await RNBG.stop();
      }

      RNBG.ready({
        reset: true,
        stopOnTerminate: false,
        disableLocationAuthorizationAlert: true,
        locationAuthorizationRequest: 'Any',
      }).then(state => {
        setEnabled(state.enabled);
      });
    });
  }, []);

  return (
    <Button
      title={enabled ? 'Stop' : 'Start'}
      onPress={enabled ? onStop : onStart}
    />
  );
};

@christocracy
Copy link
Member

christocracy commented Nov 7, 2024

It doesn't work as you write

That’s not how I wrote it.

The plug-in API is asynchronous. You need to await the call to .getProviderState() within an async function, guaranteeing it executes before calling .ready.

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

I'm calling ready inside getProviderState promise resolve callback. So I think code is identical

@christocracy
Copy link
Member

Compare your logic:

if (providerState.enabled)

with mine:

if (!providerState.enabled) {

if NOT enabled. If location-services are disabled, then .stop().

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

Ah, thx. But permission still requesting 🤷‍♂️

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

Provider state resolves to

{
  "accuracyAuthorization": 0,
  "enabled": false,
  "gps": true,
  "network": true,
  "status": 0
}

I think there is some logic in native code that requests permission

@christocracy
Copy link
Member

The plugin only requests permission if the plugin is State.enabled.

Are you observing the plugin logs in $ adb logcat? See Wiki "Debugging".

@Crysp
Copy link
Author

Crysp commented Nov 7, 2024

iOS Logs at the app startup with "unexpected" permission request

[Info, common]: Using Mapbox Common SDK v24.6.1(562d5cb0e)
[Info, maps-core]: Using Mapbox Core Maps SDK v11.6.1(dae86f79c0)
[TSBackgroundFetch load]: (
)
[TSBGAppRefreshSubscriber load]: {
    TSLocationManager = "<TSBGAppRefreshSubscriber identifier=TSLocationManager, executed=0, enabled=1>";
}
10.25.0 - [FirebaseInstallations][I-FIS002000] -[FIRInstallationsIDController createGetInstallationItemPromise], appName: __FIRAPP_DEFAULT
10.25.0 - [FirebaseMessaging][I-FCM043000] Info is not found in Keychain. OSStatus: -25300. Keychain query: {
    acct = "com.teemco.meetinger";
    class = genp;
    gena = "com.google.iid";
    "m_Limit" = "m_LimitAll";
    nleg = 1;
    "r_Attributes" = 1;
    "r_Data" = 1;
    svce = "com.google.iid.checkin";
}
10.25.0 - [FirebaseMessaging][I-FCM033009] App reset detected but no valid checkin auth preferences found. Will not delete server token registrations.
10.25.0 - [FirebaseMessaging][I-FCM002000] FIRMessaging library version 10.25.0
10.25.0 - [GULReachability][I-REA902003] Monitoring the network status
10.25.0 - [FirebaseMessaging][I-FCM043000] Info is not found in Keychain. OSStatus: -25300. Keychain query: {
    acct = "com.teemco.meetinger";
    class = genp;
    gena = "com.google.iid-tokens";
    "m_Limit" = "m_LimitAll";
    nleg = 1;
    "r_Attributes" = 1;
    "r_Data" = 1;
    svce = "684149350965:*";
}
10.25.0 - [FirebaseMessaging][I-FCM001000] FIRMessaging Remote Notifications proxy enabled, will swizzle remote notification receiver handlers. If you'd prefer to manually integrate Firebase Messaging, add "FirebaseAppDelegateProxyEnabled" to your Info.plist, and set it to NO. Follow the instructions at:
https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in_firebase_messaging
to ensure proper integration.
10.25.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001008] Successfully created App Delegate Proxy automatically. To disable the proxy, set the flag GoogleUtilitiesAppDelegateProxyEnabled to NO (Boolean) in the Info.plist
10.25.0 - [FirebaseAnalytics][I-ACS024000] Debug mode is on
10.25.0 - [GULReachability][I-REA902003] Monitoring the network status
10.25.0 - [FirebaseAnalytics][I-ACS023007] Analytics v.10.25.0 started
Running application meetinger ({
    initialProps =     {
        concurrentRoot = 0;
    };
    rootTag = 1;
})
10.25.0 - [FirebaseAnalytics][I-ACS023008] To disable debug logging set the following application argument: -noFIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r)
10.25.0 - [FirebaseAnalytics][I-ACS023009] Debug logging enabled
10.25.0 - [FirebaseAnalytics][I-ACS023207] To enable verbose logging set the following application argument: -FIRAnalyticsVerboseLoggingEnabled (see http://goo.gl/RfcP7r)
10.25.0 - [GULReachability][I-REA902003] Monitoring the network status
10.25.0 - [FirebaseAnalytics][I-ACS044000] GoogleAppMeasurementIdentitySupport dependency is linked.
10.25.0 - [FirebaseAnalytics][I-ACS044002] The AdSupport Framework is not currently linked. Some features will not function properly. Learn more at http://goo.gl/9vSsPb
10.25.0 - [FirebaseAnalytics][I-ACS031010] Tracking view controller. Class, ID: UIViewController, 7070580397397364186
10.25.0 - [FirebaseCore][I-COR000033] Data Collection flag is not set.
10.25.0 - [GULReachability][I-REA902004] Network status has changed. Code:2, status:Connected
10.25.0 - [GULReachability][I-REA902004] Network status has changed. Code:2, status:Connected
10.25.0 - [GULReachability][I-REA902004] Network status has changed. Code:2, status:Connected
ℹ️-[TSLocationManager init] 
╔═════════════════════════════════════════════
║ TSLocationManager (build 388)
╠══════════════════════════════════════════════
{
    activityRecognitionInterval = 10000;
    activityType = 1;
    authorization =     {
    };
    autoSync = 1;
    autoSyncThreshold = 0;
    batchSync = 0;
    debug = 0;
    desiredAccuracy = "-1";
    desiredOdometerAccuracy = 100;
    didDeviceReboot = 0;
    didLaunchInBackground = 0;
    didRequestUpgradeLocationAuthorization = 0;
    disableAutoSyncOnCellular = 0;
    disableElasticity = 0;
    disableLocationAuthorizationAlert = 1;
    disableMotionActivityUpdates = 0;
    disableStopDetection = 0;
    distanceFilter = 10;
    elasticityMultiplier = 1;
    enableTimestampMeta = 0;
    enabled = 1;
    extras =     {
    };
    geofenceInitialTrig
ℹ️-[GeofenceDAO init] CREATE TABLE IF NOT EXISTS geofences (id INTEGER PRIMARY KEY AUTOINCREMENT, identifier TEXT NOT NULL UNIQUE, latitude DOUBLE NOT NULL, sin_latitude DOUBLE NOT NULL, cos_latitude DOUBLE NOT NULL, longitude DOUBLE NOT NULL, sin_longitude DOUBLE NOT NULL, cos_longitude DOUBLE NOT NULL, radius DOUBLE NOT NULL, notifyOnEntry BOOLEAN NOT NULL DEFAULT 0, notifyOnExit BOOLEAN NOT NULL DEFAULT 0, notifyOnDwell BOOLEAN NOT NULL DEFAULT 0, loiteringDelay DOUBLE NOT NULL DEFAULT 0, extras TEXT, vertices TEXT)
ℹ️-[GeofenceDAO init] CREATE index IF NOT EXISTS identifier ON geofences (identifier);CREATE index IF NOT EXISTS latitude ON geofences (latitude);CREATE index IF NOT EXISTS longitude ON geofences (longitude);CREATE index IF NOT EXISTS sin_latitude ON geofences (sin_latitude);CREATE index IF NOT EXISTS cos_latitude ON geofences (cos_latitude);CREATE index IF NOT EXISTS sin_longitude ON geofences (sin_longitude);CREATE index IF NOT EXISTS cos_longitude ON geofences (cos_longitude);
-[RNFBAppModule setLogLevel:] [Line 254] RNFBSetLogLevel: setting level to 3 from error.
+[RNFBAppModule getCustomDomain:] [Line 239] authDomains:
ℹ️-[TSConfig persist]
🔵-[TSLocationManager locationManager:didChangeAuthorizationStatus:] status 0
🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 0
🔵-[PolygonGeofencingService locationManager:didChangeAuthorizationStatus:] 0
🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 0
🔵-[BackgroundTaskManager locationManager:didChangeAuthorizationStatus:] 0
🔵-[LocationManager locationManager:didChangeAuthorizationStatus:] 0
ℹ️+[LocationAuthorization run:onCancel:] status: 0
🔵+[LocationAuthorization run:onCancel:] Request: requestAnyAuthorization
10.25.0 - [FirebaseMessaging][I-FCM012002] Error in application:didFailToRegisterForRemoteNotificationsWithError: no valid “aps-environment” entitlement string found for application
ℹ️-[Logger writeNative:] Application - Resign active - provider: native
nw_socket_handle_socket_event [C4.1.1:1] Socket SO_ERROR 61
nw_endpoint_flow_failed_with_error [C4.1.1 ::1.8097 in_progress socket-flow (satisfied (Path is satisfied), interface: lo0)] already failing, returning
nw_socket_handle_socket_event [C4.1.2:1] Socket SO_ERROR 61
nw_endpoint_flow_failed_with_error [C4.1.2 127.0.0.1:8097 in_progress socket-flow (satisfied (Path is satisfied), interface: lo0)] already failing, returning
nw_endpoint_flow_failed_with_error [C4.1.2 127.0.0.1:8097 cancelled socket-flow ()] already failing, returning
nw_connection_get_connected_socket_block_invoke [C4] Client called nw_connection_get_connected_socket on unconnected nw_connection
TCP Conn 0x10727f330 Failed : error 0:61 [61]
Unbalanced calls start/end for tag 19
Running "meetinger" with {"rootTag":1,"initialProps":{"concurrentRoot":false}}
nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
ℹ️-[TSConfig persist]
ℹ️-[TSLocationManager clearLastOdometerLocation]
🔴-[TSGeofenceManager stop]
🔴-[TSGeofenceManager stopMonitoringGeofences]
🔴-[PolygonGeofencingService stop]
ℹ️-[PolygonGeofencingService persistMonitoredPolygons] {
}
🔴-[TSLocationManager stopUpdatingLocation]
🔴-[TSLocationManager stopMonitoringBackgroundFetch] BackgroundFetch: OFF
🔴-[TSLocationManager stopMonitoringSignificantLocationChanges]
ℹ️-[TSLocationManager on:success:failure:] location
ℹ️-[TSLocationManager on:success:failure:] motionchange
ℹ️-[TSLocationManager on:success:failure:] activitychange
ℹ️-[TSLocationManager on:success:failure:] heartbeat
ℹ️-[TSGeofenceManager onGeofence:]
ℹ️-[TSGeofenceManager onGeofencesChange:]
ℹ️-[TSLocationManager on:success:failure:] http
ℹ️-[TSLocationManager on:success:failure:] providerchange
ℹ️-[TSLocationManager on:success:failure:] schedule
ℹ️-[TSLocationManager on:success:failure:] powersavechange
ℹ️-[TSHttpService onConnectivityChange:]
ℹ️-[TSLocationManager on:success:failure:] enabledchange
ℹ️-[TSHttpService onAuthorization:]
ℹ️-[TSConfig persist]
ℹ️-[TSConfig persist]
🔵-[TSLocationManager ready]

@christocracy
Copy link
Member

These logs and your simple reproduction app are helpful. I’ll look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants