Unhandled Exception: PlatformException on android.permission.READ_PHONE_NUMBERS
I have an issue that I cannot get around...
Note that using an Android 10 phone, everything works and VoiP and Video calls can be made...
But when attempting to use an Android 12 phone it always fails with the following exception.
E/flutter (16778): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(error, Neither user 10550 nor current process has android.permission.READ_PHONE_NUMBERS., null, java.lang.SecurityException: Neither user 10550 nor current process has android.permission.READ_PHONE_NUMBERS.
E/flutter (16778): at android.os.Parcel.createExceptionOrNull(Parcel.java:3040)
E/flutter (16778): at android.os.Parcel.createException(Parcel.java:3024)
E/flutter (16778): at android.os.Parcel.readException(Parcel.java:3007)
E/flutter (16778): at android.os.Parcel.readException(Parcel.java:2949)
E/flutter (16778): at com.android.internal.telecom.ITelecomService$Stub$Proxy.getPhoneAccount(ITelecomService.java:1672)
E/flutter (16778): at android.telecom.TelecomManager.getPhoneAccount(TelecomManager.java:1436)
E/flutter (16778): at io.wazo.callkeep.CallKeepModule.hasPhoneAccount(CallKeepModule.java:663)
E/flutter (16778): at io.wazo.callkeep.CallKeepModule.hasPhoneAccount(CallKeepModule.java:498)
E/flutter (16778): at io.wazo.callkeep.CallKeepModule.handleMethodCall(CallKeepModule.java:177)
E/flutter (16778): at com.github.cloudwebrtc.flutter_callkeep.FlutterCallkeepPlugin.onMethodCall(FlutterCallkeepPlugin.java:69)
E/flutter (16778): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
E/flutter (16778): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/flutter (16778): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
E/flutter (16778): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/flutter (16778): at android.os.Handler.handleCallback(Handler.java:942)
E/flutter (16778): at android.os.Handler.dispatchMessage(Handler.java:99)
E/flutter (16778): at android.os.Looper.loopOnce(Looper.java:240)
E/flutter (16778): at android.os.Looper.loop(Looper.java:351)
E/flutter (16778): at android.app.ActivityThread.main(ActivityThread.java:8381)
E/flutter (16778): at java.lang.reflect.Method.invoke(Native Method)
E/flutter (16778): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
E/flutter (16778): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)
E/flutter (16778): )
I am calling setup with the following code... note that I have created an additional method invoke within MainActivity.kt to attempt to force the permission request - this does not come back with an error but it also does not put up a request dialog.
final callSetup = <String, dynamic>{
'ios': {
'appName': AppConfig.applicationName,
},
'android': {
'alertTitle': 'Permissions required',
'alertDescription': 'Conciel needs to access your phone accounts',
'cancelButton': 'Cancel',
'okButton': 'ok',
// Required to get audio in background when using Android 11
'foregroundService': {
'channelId': 'chat.talk.conciel.call',
'channelName': 'Conciel Call',
'notificationTitle': 'Conciel is running in the background',
'notificationIcon': 'mipmap/ic_notification_launcher',
},
'additionalPermissions': [''],
},
};
void requestReadPhoneNumbersPermission() async {
try {
await concielPlatform.invokeMethod('requestReadPhoneNumbersPermission');
} on PlatformException catch (e) {
Logs().e('Failed to request READ_PHONE_NUMBERS permission: ${e.message}');
}
}
await Permission.phone.request().isGranted;
requestReadPhoneNumbersPermission();
await _callKeep.setup(
context,
callSetup,
);
in the MainActivity.kt - I have included the following code to invoke permission request on READ_PHONE_NUMBERS...
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_READ_PHONE_NUMBERS) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// The READ_PHONE_NUMBERS permission was granted
Log.d("MainActivity", "READ_PHONE_NUMBERS permission granted")
} else {
// The READ_PHONE_NUMBERS permission was not granted
Log.d("MainActivity", "READ_PHONE_NUMBERS permission not granted")
}
}
}
As it stands, I am unable to use CallKeep to handle calls on a phone above Android 10.
I just noted the Kotlin code was the permission check... this is the invoke permission code...
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "requestReadPhoneNumbersPermission") {
// Check if the READ_PHONE_NUMBERS permission is already granted
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED) {
// Request the READ_PHONE_NUMBERS permission
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_NUMBERS), REQUEST_READ_PHONE_NUMBERS)
}
result.success(null)
} else {
result.notImplemented()
}
}
}
you can just add this to your android manifest file
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
you can just add this to your android manifest file
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
@rashedswen - It is already in the android manifest, all other permissions requested in Android manifest work as expected, this one does not.
Do you try to setup the callkeep in main or first page of your app I do that and that work will and request permission when the app opens
Yes, the setup and permission checks all occur once the app opens. From my understanding CallKeep should allow use of system managed Android ConnectionService - but from my recent research, on some makes and models this is not possible as their Android Settings do not permit access to this, hence the exception.