If permissions are not granted, the callback should be called, with the error field being non-null/undefined.
Contacts.getAll((err, contacts) => {
// err should be defined
})
App crashes completely. React Native does not even have the chance to catch the error.
async function requestPermissions() {
let status = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_CONTACTS)
console.log('status', status)
}
async function contactsGetAll(): Promise<Contact[]> {
await requestPermissions()
console.log('permissions')
return new Promise((res, rej) => {
Contacts.getAll((err, contacts) => {
console.log('err', err)
if (err) { rej(err) }
else { res(contacts) }
})
})
}
contacts: Contact[] = await contactsGetAll()
status: never_ask_again
permissions
// crashes
Check permissions before calling Contacts.getAll()
let status = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_CONTACTS)
if (status === 'denied' || status === 'never_ask_again') {
throw Error('Permissions not granted to access Contacts')
}
Contacts.getAll((err, contacts) => {})
I'm not sure if there's anything we can/should do about this. Checking for permissions before performing privileged actions seems fine to me.
I think, just crashing silently is not a way to go either. Maybe provide some kind of error handling which will prevent a crash.
I'm not the most Java literate person at a moment, but will try to provide some PR with a fix, if be able to scrape some free time, to help with that issue.
I'm not sure if there's anything we can/should do about this. Checking for permissions before performing privileged actions seems fine to me.
There is inconsistent behaviour on Android vs iOS though.
In iOS, permissions aren't granted, it will be handled in the error block:
Contacts.getAll((err, contacts) => {
// iOS permission errors will be caught here
})
In Android, if permissions are not granted, errors do not get caught by this block. It crashes the entire app entirely.
1) Why provide an error handler for when the error handler only catches iOS errors and not Android errors? It's misleading to developers to see an error handler block that does not catch errors. I feel it would be better if both Android & iOS were handled the same way.
2) It does not seem appropriate that calling a ReactNative function can cause an entire Android app to crash. I feel errors should be handled at the ReactNative boundary.
I solved it by the using the below piece of "try catch" code logic:
The app will not crash, since all the cases are handled .
try {
const andoidContactPermission = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
title: "Contacts Permission",
message:
"This app would like to view your contacts.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (andoidContactPermission === PermissionsAndroid.RESULTS.GRANTED) {
console.log("Contacts Permission granted");
Contacts.getAll((andoidContactPermission, contacts) => {
console.log(contacts);
});
} else {
console.log("Contacts permission denied");
}
} catch (err) {
console.log(err);
}
Hope this helps :+1:
It's still crashing working fine on some phones but on few phones it's crashing
Crashing on following devices
Samsung S8 plus
Android Version 5 : Hawaii P8 lite
in android manifest file use
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission
android:name="android.permission.READ_PROFILE"
android:maxSdkVersion="22"
tools:targetApi="donut" />
Btw, just sharing my code if anyone just wants a quick copy and paste:
Usage:
import { Contacts } from './Contacts'
Contacts.getAll().then(contacts => {
contacts.forEach(contact => {
console.log(contact)
console.log(contact.givenName)
console.log(contact.phoneNumbers)
})
})
Contacts.ts
// Wrapper for permissions as original function does not throw
const requestPermissions = async (): Promise<void> => {
// If app would like to display the rational for requesting permissions,
// then place it as second param in PermissionsAndroid.request().
if (Platform.OS === 'android') {
let status = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_CONTACTS)
if (status === 'denied' || status === 'never_ask_again') {
throw Error('Permission not granted to access contacts')
}
}
}
// Wrapper for requesting contacts as original function returns callback instead of Promise
const getAll = async (): Promise<Contact[]> => {
await requestPermissions()
return new Promise((res, rej) => {
RNContacts.getAll((err, contacts) => {
if (err) {
rej(Error('Permission not granted to access contacts'))
} else {
res(contacts)
}
})
})
}
export const Contacts = { getAll }
This issue is stale, please provide more information about the status
I ran into this too and it was super weird, I found you need both WRITE_CONTACTS and READ_CONTACTS regardless of API version. The README sections them off as if READ was a part of WRITE for Api 23+, that's what confused me at least.
The weirdest part was how getAll did not throw an error, it just hung indefintiely, while addContact would create the contact in the mobile app BUT THEN throw an error on READ permission not granted, which was very difficult to reason through.
@cvharris not sure. If you want to update the readme that would be welcome.
My PermissionsAndroid is granted and i cannot catch the error , still have the crash with API 22 when i make a getAll call . Any Suggestions Guys ?
My PermissionsAndroid is granted and i cannot catch the error , still have the crash with API 22 when i make a
getAllcall . Any Suggestions Guys ?
You must use read profile permission in android platform.
Most helpful comment
There is inconsistent behaviour on Android vs iOS though.
In iOS, permissions aren't granted, it will be handled in the error block:
In Android, if permissions are not granted, errors do not get caught by this block. It crashes the entire app entirely.
1) Why provide an error handler for when the error handler only catches iOS errors and not Android errors? It's misleading to developers to see an error handler block that does not catch errors. I feel it would be better if both Android & iOS were handled the same way.
2) It does not seem appropriate that calling a ReactNative function can cause an entire Android app to crash. I feel errors should be handled at the ReactNative boundary.