@@ -8,6 +8,7 @@ import android.content.DialogInterface
88import android.content.Intent
99import android.content.IntentFilter
1010import android.content.pm.PackageManager
11+ import android.os.Build
1112import android.os.Bundle
1213import android.telecom.CallAudioState
1314import android.telecom.PhoneAccountHandle
@@ -95,6 +96,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
9596 private val REQUEST_CODE_CALL_PHONE = 3
9697 private val REQUEST_CODE_READ_PHONE_NUMBERS = 4
9798 private val REQUEST_CODE_READ_PHONE_STATE = 5
99+ private val REQUEST_CODE_MICROPHONE_FOREGROUND = 6
98100
99101 private var isSpeakerOn: Boolean = false
100102 private var isBluetoothOn: Boolean = false
@@ -244,6 +246,9 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
244246 if (requestCode == REQUEST_CODE_MICROPHONE ) {
245247 if (permissions.isNotEmpty() && grantResults[0 ] == PackageManager .PERMISSION_GRANTED ) {
246248 Log .d(TAG , " Microphone permission granted" )
249+ requestPermissionForMicrophoneForeground(onPermissionResult = { granted ->
250+ Log .d(TAG , " onRequestPermissionsResult: Microphone foreground permission granted: $granted " );
251+ });
247252 logEventPermission(" Microphone" , true )
248253 } else {
249254 Log .d(TAG , " Microphone permission not granted" )
@@ -281,6 +286,14 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
281286 Log .d(TAG , " Call Phone permission not granted" )
282287 logEventPermission(" Call Phone State" , false )
283288 }
289+ } else if (requestCode == REQUEST_CODE_MICROPHONE_FOREGROUND ) {
290+ if (permissions.isNotEmpty() && grantResults[0 ] == PackageManager .PERMISSION_GRANTED ) {
291+ Log .d(TAG , " Microphone foreground permission granted" )
292+ logEventPermission(" Microphone" , true )
293+ } else {
294+ Log .d(TAG , " Microphone foreground permission not granted" )
295+ logEventPermission(" Microphone" , false )
296+ }
284297 }
285298 return true
286299 }
@@ -1435,6 +1448,23 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
14351448 )
14361449 }
14371450
1451+ // / Request permission for microphone on Android 14 and higher.
1452+ // / Source: https://developer.android.com/reference/android/Manifest.permission#FOREGROUND_SERVICE_MICROPHONE
1453+ private fun requestPermissionForMicrophoneForeground (onPermissionResult : (Boolean ) -> Unit ) {
1454+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
1455+ Log .d(TAG , " requestPermissionForMicrophoneForeground: Microphone foreground permission automatically requested." );
1456+ return requestPermissionOrShowRationale(
1457+ " Microphone Foreground" ,
1458+ " Microphone Foreground permission is required to make or receive phone calls on Android 14 and higher." ,
1459+ Manifest .permission.FOREGROUND_SERVICE_MICROPHONE ,
1460+ REQUEST_CODE_MICROPHONE_FOREGROUND ,
1461+ onPermissionResult
1462+ )
1463+ } else {
1464+ Log .d(TAG , " requestPermissionForMicrophoneForeground: Microphone foreground permission skipped." );
1465+ }
1466+ }
1467+
14381468 private fun requestPermissionForPhoneState (onPermissionResult : (Boolean ) -> Unit ) {
14391469 return requestPermissionOrShowRationale(
14401470 " Read Phone State" ,
0 commit comments