Open
Description
Before submitting a new issue
- I tested using the latest version of the library, as the bug might be already fixed.
- I tested using a supported version of react native.
- I checked for possible duplicate issues, with possible answers.
Bug summary
Hello,
In Crashlytics, we are seeing the following crash when app is in the background:
Crashed: com.apple.main-thread
0 libswiftCore.dylib 0x215928 __StringStorage.isEqualToString(to:) + 60
1 libswiftCore.dylib 0x215c64 @objc __StringStorage.isEqual(to:) + 92
2 CoreFoundation 0x2114 -[__NSDictionaryM setObject:forKey:] + 348
3 LionWheel 0x777c58 -[RNPermissions lockHandler:] + 300 (RNPermissions.mm:300)
4 LionWheel 0x7782e4 -[RNPermissions request:resolve:reject:] + 341 (RNPermissions.mm:341)
5 CoreFoundation 0x20814 __invoking___ + 148
6 CoreFoundation 0x1f860 -[NSInvocation invoke] + 428
7 CoreFoundation 0x961dc -[NSInvocation invokeWithTarget:] + 64
8 LionWheel 0x828290 -[RCTModuleMethod invokeWithBridge:module:arguments:] + 587 (RCTModuleMethod.mm:587)
9 LionWheel 0x82a394 facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&, int, (anonymous namespace)::SchedulingContext) + 196 (RCTNativeModule.mm:196)
10 LionWheel 0x829fe4 invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) + 247 (optional:247)
11 libdispatch.dylib 0x213c _dispatch_call_block_and_release + 32
12 libdispatch.dylib 0x3dd4 _dispatch_client_callout + 20
13 libdispatch.dylib 0x125a4 _dispatch_main_queue_drain + 988
14 libdispatch.dylib 0x121b8 _dispatch_main_queue_callback_4CF + 44
15 CoreFoundation 0x56710 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
16 CoreFoundation 0x53914 __CFRunLoopRun + 1996
17 CoreFoundation 0x52cd8 CFRunLoopRunSpecific + 608
18 GraphicsServices 0x11a8 GSEventRunModal + 164
19 UIKitCore 0x40a90c -[UIApplication _run] + 888
20 UIKitCore 0x4be9d0 UIApplicationMain + 340
21 LionWheel 0x739c main + 8 (main.m:8)
22 ??? 0x1b01bde4c (Missing)
Podfile config:
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
platform :ios, '13.4'
prepare_react_native_project!
setup_permissions([
# 'AppTrackingTransparency',
#'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
'Camera',
# 'Contacts',
# 'FaceID',
'LocationAccuracy',
'LocationAlways',
'LocationWhenInUse',
#'MediaLibrary',
'Microphone',
# 'Motion',
#'Notifications',
'PhotoLibrary',
# 'PhotoLibraryAddOnly',
# 'Reminders',
# 'Siri',
# 'SpeechRecognition',
# 'StoreKit',
])
Library version
4.1.5
Environment info
React Native: 0.73.6
(for some reason react-native info just stalls on my pc)
Steps to reproduce
Taken from Crashlytics, so not clear reproduction steps.
Reproducible sample code
Config:
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
platform :ios, '13.4'
prepare_react_native_project!
setup_permissions([
# 'AppTrackingTransparency',
#'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
'Camera',
# 'Contacts',
# 'FaceID',
'LocationAccuracy',
'LocationAlways',
'LocationWhenInUse',
#'MediaLibrary',
'Microphone',
# 'Motion',
#'Notifications',
'PhotoLibrary',
# 'PhotoLibraryAddOnly',
# 'Reminders',
# 'Siri',
# 'SpeechRecognition',
# 'StoreKit',
])
Ask for permissions using this code:
import {request, requestMultiple, PERMISSIONS} from 'react-native-permissions'
import {Platform} from 'react-native'
function isPermissionGranted(permission) {
if (permission && typeof permission === 'object') {
return Object.values(permission).every(
(val) => val === 'granted' || val === 'unavailable',
)
}
return permission === 'granted' || permission === 'unavailable'
}
function getCameraPermissions() {
return Platform.OS === 'ios'
? PERMISSIONS.IOS.CAMERA
: PERMISSIONS.ANDROID.CAMERA
}
function getLocationPermisison(useBackgroundLocationApproved) {
if (Platform.OS === 'ios') {
return [PERMISSIONS.IOS.LOCATION_ALWAYS]
} else {
const permissions = [
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION,
]
// For android we show a warning about using background location which the user needs to approve according to
// the play store guidelines
if (useBackgroundLocationApproved) {
permissions.push(PERMISSIONS.ANDROID.ACCESS_BACKGROUND_LOCATION)
}
return permissions
}
}
function getMicrophonePermission() {
return Platform.OS === 'ios'
? PERMISSIONS.IOS.MICROPHONE
: PERMISSIONS.ANDROID.RECORD_AUDIO
}
export const checkPermissions = async (
useBackgroundLocationApproved = true,
recordCalls = false,
) => {
// Android 11 and up doesn't allow background location
if (parseInt(Platform.constants.Release) >= 11) {
useBackgroundLocationApproved = false
}
const location = await requestMultiple(
getLocationPermisison(useBackgroundLocationApproved),
)
const camera = await request(getCameraPermissions())
let voice = null
if (recordCalls) {
voice = await request(getMicrophonePermission())
}
return {
location: isPermissionGranted(location),
camera: isPermissionGranted(camera),
voice: isPermissionGranted(voice),
}
}
export default checkPermissions