flutter-webrtc / callkeep

iOS CallKit and Android ConnectionService for Flutter
MIT License
130 stars 139 forks source link

Java Exception android.permission.READ_PHONE_NUMBERS on Android > 11 #156

Open elbriga opened 1 year ago

elbriga commented 1 year ago

I call setup as in the example, to acquire permissions. The first time a run the App the permissions are asked.

When I call "displayIncomingCall" the Excpetion is thrown:

E/flutter ( 8787): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(error, Neither user 10159 nor current process has android.permission.READ_PHONE_NUMBERS., null, java.lang.SecurityException: Neither user 10159 nor current process has android.permission.READ_PHONE_NUMBERS.
E/flutter ( 8787):  at android.os.Parcel.createExceptionOrNull(Parcel.java:3011)
E/flutter ( 8787):  at android.os.Parcel.createException(Parcel.java:2995)
E/flutter ( 8787):  at android.os.Parcel.readException(Parcel.java:2978)
E/flutter ( 8787):  at android.os.Parcel.readException(Parcel.java:2920)
E/flutter ( 8787):  at com.android.internal.telecom.ITelecomService$Stub$Proxy.getPhoneAccount(ITelecomService.java:1628)
E/flutter ( 8787):  at android.telecom.TelecomManager.getPhoneAccount(TelecomManager.java:1415)
E/flutter ( 8787):  at io.wazo.callkeep.CallKeepModule.hasPhoneAccount(CallKeepModule.java:636)
E/flutter ( 8787):  at io.wazo.callkeep.CallKeepModule.displayIncomingCall(CallKeepModule.java:258)
E/flutter ( 8787):  at io.wazo.callkeep.CallKeepModule.handleMethodCall(CallKeepModule.java:114)
E/flutter ( 8787):  at com.github.cloudwebrtc.flutter_callkeep.FlutterCallkeepPlugin.onMethodCall(FlutterCallkeepPlugin.java:69)
E/flutter ( 8787):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
E/flutter ( 8787):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/flutter ( 8787):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/flutter ( 8787):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/flutter ( 8787):  at android.os.Handler.handleCallback(Handler.java:942)
E/flutter ( 8787):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/flutter ( 8787):  at android.os.Looper.loopOnce(Looper.java:201)
E/flutter ( 8787):  at android.os.Looper.loop(Looper.java:288)
E/flutter ( 8787):  at android.app.ActivityThread.main(ActivityThread.java:7872)
E/flutter ( 8787):  at java.lang.reflect.Method.invoke(Native Method)
E/flutter ( 8787):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/flutter ( 8787):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
E/flutter ( 8787): Caused by: android.os.RemoteException: Remote stack trace:
E/flutter ( 8787):  at android.app.ContextImpl.enforce(ContextImpl.java:2240)
E/flutter ( 8787):  at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:2268)
E/flutter ( 8787):  at android.content.ContextWrapper.enforceCallingOrSelfPermission(ContextWrapper.java:948)
E/flutter ( 8787):  at com.android.server.telecom.TelecomServiceImpl.canGetPhoneAccount(TelecomServiceImpl.java:2640)
E/flutter ( 8787):  at com.android.server.telecom.TelecomServiceImpl.-$$Nest$mcanGetPhoneAccount(Unknown Source:0)
E/flutter ( 8787):
E/flutter ( 8787): )
E/flutter ( 8787): #0      StandardMethodCodec.decodeEnvelope
package:flutter/…/services/message_codecs.dart:653
E/flutter ( 8787): #1      MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:296
E/flutter ( 8787): <asynchronous suspension>
E/flutter ( 8787): #2      FlutterCallkeep.displayIncomingCall
ahmetbora commented 1 year ago

Use this Working Function

`
Future displayIncomingCall(String number) async { final String callUUID = newUUID(); setState(() { calls[callUUID] = Call(number); }); print('Display incoming call now'); await Permission.phone.request(); // ADD THIS REQUEST

final bool hasPhoneAccount = await _callKeep.hasPhoneAccount();
if (!hasPhoneAccount) {
  await _callKeep.hasDefaultPhoneAccount(context, <String, dynamic>{
    'alertTitle': 'Permissions required',
    'alertDescription':
        'This application needs to access your phone accounts',
    'cancelButton': 'Cancel',
    'okButton': 'ok',
    'additionalPermissions': <String>[], // ADD Empty String array
    'foregroundService': {
      'channelId': 'com.company.my',
      'channelName': 'Foreground service for my app',
      'notificationTitle': 'My app is running on background',
      'notificationIcon': 'Path to the resource icon of the notification',
    },
  });
}

print('[displayIncomingCall] $callUUID number: $number');
_callKeep.displayIncomingCall(callUUID, number,
    handleType: 'number', hasVideo: false);

}

Also required READ_PHONE_NUMBERS permission

`

`

elbriga commented 1 year ago

Thanks, I've found the answer too:

Just add: if (await Permission.phone.request().isGranted) { print('OKkkkkkkkkkkkk'); } else { print('ERROoooooooooo'); } just before the callkeep setup()