diff --git a/dialer/android/app/src/main/AndroidManifest.xml b/dialer/android/app/src/main/AndroidManifest.xml
index fcaf71f..4c1cb5f 100644
--- a/dialer/android/app/src/main/AndroidManifest.xml
+++ b/dialer/android/app/src/main/AndroidManifest.xml
@@ -12,6 +12,8 @@
+
+
? = null
+ private var wasPhoneLocked: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate started")
- Log.d(TAG, "Waiting for Flutter to signal permissions")
+ wasPhoneLocked = intent.getBooleanExtra("wasPhoneLocked", false)
+ Log.d(TAG, "Was phone locked at start: $wasPhoneLocked")
+ updateLockScreenFlags(intent)
+ handleIncomingCallIntent(intent)
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ setIntent(intent)
+ wasPhoneLocked = intent.getBooleanExtra("wasPhoneLocked", false)
+ Log.d(TAG, "onNewIntent, wasPhoneLocked: $wasPhoneLocked")
+ updateLockScreenFlags(intent)
+ handleIncomingCallIntent(intent)
+ }
+
+ private fun updateLockScreenFlags(intent: Intent?) {
+ val isIncomingCall = intent?.getBooleanExtra("isIncomingCall", false) ?: false
+ if (isIncomingCall && wasPhoneLocked) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ setShowWhenLocked(true)
+ setTurnScreenOn(true)
+ } else {
+ @Suppress("DEPRECATION")
+ window.addFlags(
+ android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
+ android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ )
+ }
+ Log.d(TAG, "Enabled showWhenLocked and turnScreenOn for incoming call")
+ } else {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ setShowWhenLocked(false)
+ setTurnScreenOn(false)
+ } else {
+ @Suppress("DEPRECATION")
+ window.clearFlags(
+ android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
+ android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ )
+ }
+ Log.d(TAG, "Disabled showWhenLocked and turnScreenOn for normal usage")
+ }
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
Log.d(TAG, "Configuring Flutter engine")
-
MyInCallService.channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL)
+
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"permissionsGranted" -> {
Log.d(TAG, "Received permissionsGranted from Flutter")
+ pendingIncomingCall?.let { (phoneNumber, showScreen) ->
+ if (showScreen) {
+ MyInCallService.channel?.invokeMethod("incomingCallFromNotification", mapOf(
+ "phoneNumber" to phoneNumber,
+ "wasPhoneLocked" to wasPhoneLocked
+ ))
+ pendingIncomingCall = null
+ }
+ }
checkAndRequestDefaultDialer()
result.success(true)
}
@@ -60,37 +112,66 @@ class MainActivity : FlutterActivity() {
}
}
"hangUpCall" -> {
- val success = CallService.hangUpCall(this)
+ val success = MyInCallService.currentCall?.let {
+ it.disconnect()
+ Log.d(TAG, "Call disconnected")
+ MyInCallService.channel?.invokeMethod("callEnded", mapOf(
+ "callId" to it.details.handle.toString(),
+ "wasPhoneLocked" to wasPhoneLocked
+ ))
+ true
+ } ?: false
if (success) {
result.success(mapOf("status" to "ended"))
+ if (wasPhoneLocked) {
+ Log.d(TAG, "Finishing and removing task after hangup, phone was locked")
+ finishAndRemoveTask()
+ }
} else {
- result.error("HANGUP_FAILED", "Failed to end call", null)
+ Log.w(TAG, "No active call to hang up")
+ result.error("HANGUP_FAILED", "No active call to hang up", null)
}
}
"answerCall" -> {
val success = MyInCallService.currentCall?.let {
- it.answer(0) // 0 for default video state (audio-only)
+ it.answer(0)
Log.d(TAG, "Answered call")
true
} ?: false
if (success) {
result.success(mapOf("status" to "answered"))
} else {
+ Log.w(TAG, "No active call to answer")
result.error("ANSWER_FAILED", "No active call to answer", null)
}
}
+ "callEndedFromFlutter" -> {
+ Log.d(TAG, "Call ended from Flutter, wasPhoneLocked: $wasPhoneLocked")
+ if (wasPhoneLocked) {
+ finishAndRemoveTask()
+ Log.d(TAG, "Finishing and removing task after call ended, phone was locked")
+ }
+ result.success(true)
+ }
else -> result.notImplemented()
}
}
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, KEYSTORE_CHANNEL)
- .setMethodCallHandler { call, result -> KeystoreHelper(call, result).handleMethodCall() }
+ .setMethodCallHandler { call, result ->
+ KeystoreHelper(call, result).handleMethodCall()
+ }
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALLLOG_CHANNEL)
.setMethodCallHandler { call, result ->
if (call.method == "getCallLogs") {
- val callLogs = getCallLogs()
- result.success(callLogs)
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED) {
+ val callLogs = getCallLogs()
+ result.success(callLogs)
+ } else {
+ requestPermissions(arrayOf(Manifest.permission.READ_CALL_LOG), REQUEST_CODE_CALL_LOG_PERMISSION)
+ result.error("PERMISSION_DENIED", "Call log permission not granted", null)
+ }
} else {
result.notImplemented()
}
@@ -109,8 +190,6 @@ class MainActivity : FlutterActivity() {
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER)
startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER)
Log.d(TAG, "Launched RoleManager intent for default dialer on API 29+")
- } else {
- Log.d(TAG, "RoleManager: Available=${roleManager.isRoleAvailable(RoleManager.ROLE_DIALER)}, Held=${roleManager.isRoleHeld(RoleManager.ROLE_DIALER)}")
}
} else {
val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
@@ -148,6 +227,18 @@ class MainActivity : FlutterActivity() {
}
}
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_CODE_CALL_LOG_PERMISSION) {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ Log.d(TAG, "Call log permission granted")
+ MyInCallService.channel?.invokeMethod("callLogPermissionGranted", null)
+ } else {
+ Log.w(TAG, "Call log permission denied")
+ }
+ }
+ }
+
private fun getCallLogs(): List