Expo 35 Android updateContactAsync is failing.

Please provide the following:

  1. SDK Version:

“sdkVersion”: “35.0.0”,

  1. Platforms(Android/iOS/web/all):

iOS - code works fine
Android - code throws an error

The following code in an app adds a new phone number to a contact record on the device by adding another phoneNumber object to the phoneNumber array on the contact record. It works fine in iOS on an actual device and in an iOS simulator but when I build an apk file (with the permissions below) and install the App on an Android phone it fails to update the contact record and instead it throws an error (see below).

Here are the permissions in app.json

"permissions": [
	"android.permission.ACCESS_COARSE_LOCATION",
	"android.permission.ACCESS_FINE_LOCATION",
	"android.permission.CAMERA",
	"android.permission.VIBRATE",
	"android.permission.READ_CONTACTS",
	"android.permission.READ_EXTERNAL_STORAGE",
	"android.permission.READ_PHONE_STATE",
	"android.permission.WRITE_CONTACTS",
	"android.permission.WAKE_LOCK",
	"android.permission.WRITE_EXTERNAL_STORAGE",
	"com.anddoes.launcher.permission.UPDATE_COUNT",
	"com.android.launcher.permission.INSTALL_SHORTCUT",
	"com.google.android.c2dm.permission.RECEIVE",
	"com.google.android.gms.permission.ACTIVITY_RECOGNITION",
	"com.google.android.providers.gsf.permission.READ_GSERVICES",
	"com.htc.launcher.permission.READ_SETTINGS",
	"com.htc.launcher.permission.UPDATE_SHORTCUT",
	"com.majeur.launcher.permission.UPDATE_BADGE",
	"com.sec.android.provider.badge.permission.READ",
	"com.sec.android.provider.badge.permission.WRITE",
	"com.sonyericsson.home.permission.BROADCAST_BADGE"
],

Here is the code. It’s important to note that contactRecord is saved in React State and it’s just a copy of the native contact record with no changes.

const { editPhoneNumberValue, editPhoneNumberLabel, contactRecord } = this.state;
		try {
			let contact = await Contacts.getContactByIdAsync(contactRecord.id);
			let _phoneDigits = editPhoneNumberValue.replace(/[\W_]+/g, '');
			let _label = editPhoneNumberLabel;
			if (Platform.OS === 'android') {
				contact.phoneNumbers.push({
					isPrimary: 0,
					label: _label,
					number: editPhoneNumberValue,
					type: '2'
				});
			} else {
				contact.phoneNumbers.push({
					countryCode: 'us',
					digits: _phoneDigits,
					label: _label,
					number: editPhoneNumberValue
				});
			}
			Contacts.updateContactAsync(contact)
				.then(async response => {
					// 1. Get the updated contact record and do stuff with it...update state, etc
				})
				.catch(error => {
					// 2. Catch the error below here. The then above does not get executed.
				});
		} catch (error) {
		...another error catch point that is not being triggered.
		}

Here is part of the error message thrown by updateContactAsync in Sentry. It’s getting truncated but even when I read the rest of the error it’s pretty useless and doesn’t tell me anything:

{{"framesToPop":1,"nativeStackAndroid":[{"methodName":"readExceptionWithOperationApplicationExceptionFromParcel","lineNumber":156,"file":"DatabaseUtils.java"},{"methodName":"applyBatch","lineNumber":522,"file":"ContentProviderNative.java"},...

Hey @shineforth,

Just for clarity’s sake, does the error occur when testing on Android in the Expo client? Regardless, would you be able to create a minimal reproducible example and create a github issue here so that we can test it on our end.

Cheers,
Adam

When I’m testing in the Expo client app with a Android phone that uses the QR Code I get a different error, I believe the error says this:

Missing write contacts permission.
- node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:104:55 in <unknown>
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:414:4 in __invokeCallback
- ... 4 more stack frames from framework internals

I’ll see if I can create a small working example.

I opened an issue for this - Expo 35 updateContactAsync is failing on Android · Issue #6306 · expo/expo · GitHub

Standalone meaning eject from expo? Or using a bare workflow?

I’ve deployed this as an apk file with permissions in the app.json and it still would not work to use the expo updateContactAsync. Are there no examples of how to do this within expo as a managed app?

My GitHub issue got closed with really nothing helpful being provided.

Hey @shineforth,

As Charlie mentioned in the github issue, the updateContactAsync method is only available on iOS. You can not use it on Android. To make edits to contacts on Android, you need to make use of the presentFormAsync. The issue was closed because what is happening is the expected and intended behavior.

Cheers,
Adam

What I’m unclear on is this statement.

For Android users, the Expo client App does not have the required WRITE_CONTACTS permission to write to Contacts. In order to do this, you must build a standalone app and add permission through there.

I do have a standard alone app and I did add permissions in app.json but there really isn’t any further explanation of what to do next. Is it impossible to update contacts using WRITE_CONTACTS without ejecting from expo entirely?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.