feat: open dialer on top of locked screen when incoming call
This commit is contained in:
parent
16d759bc4e
commit
ffbd7bdfaa
@ -28,7 +28,9 @@
|
|||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
android:showWhenLocked="true"
|
||||||
|
android:turnScreenOn="true">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
|
@ -9,6 +9,8 @@ import android.database.Cursor
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.provider.CallLog
|
import android.provider.CallLog
|
||||||
import android.telecom.TelecomManager
|
import android.telecom.TelecomManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -27,6 +29,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
private val TAG = "MainActivity"
|
private val TAG = "MainActivity"
|
||||||
private val REQUEST_CODE_SET_DEFAULT_DIALER = 1001
|
private val REQUEST_CODE_SET_DEFAULT_DIALER = 1001
|
||||||
private val REQUEST_CODE_CALL_LOG_PERMISSION = 1002
|
private val REQUEST_CODE_CALL_LOG_PERMISSION = 1002
|
||||||
|
private var pendingIncomingCall: Pair<String?, Boolean>? = null // Store incoming call data
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -57,12 +60,10 @@ class MainActivity : FlutterActivity() {
|
|||||||
"makeGsmCall" -> {
|
"makeGsmCall" -> {
|
||||||
val phoneNumber = call.argument<String>("phoneNumber")
|
val phoneNumber = call.argument<String>("phoneNumber")
|
||||||
if (phoneNumber != null) {
|
if (phoneNumber != null) {
|
||||||
try {
|
val success = CallService.makeGsmCall(this, phoneNumber) // Use CallService
|
||||||
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$phoneNumber"))
|
if (success) {
|
||||||
startActivity(intent)
|
|
||||||
result.success(mapOf("status" to "calling", "phoneNumber" to phoneNumber))
|
result.success(mapOf("status" to "calling", "phoneNumber" to phoneNumber))
|
||||||
} catch (e: Exception) {
|
} else {
|
||||||
Log.e(TAG, "Failed to make GSM call: ${e.message}")
|
|
||||||
result.error("CALL_FAILED", "Failed to initiate call", null)
|
result.error("CALL_FAILED", "Failed to initiate call", null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -98,6 +99,18 @@ class MainActivity : FlutterActivity() {
|
|||||||
result.error("ANSWER_FAILED", "No active call to answer", null)
|
result.error("ANSWER_FAILED", "No active call to answer", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"flutterReady" -> { // New method to signal Flutter is initialized
|
||||||
|
Log.d(TAG, "Flutter is ready")
|
||||||
|
pendingIncomingCall?.let { (phoneNumber, showScreen) ->
|
||||||
|
if (showScreen) {
|
||||||
|
MyInCallService.channel?.invokeMethod("incomingCallFromNotification", mapOf(
|
||||||
|
"phoneNumber" to phoneNumber
|
||||||
|
))
|
||||||
|
pendingIncomingCall = null // Clear after handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.success(true)
|
||||||
|
}
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,9 +230,15 @@ class MainActivity : FlutterActivity() {
|
|||||||
val showScreen = it.getBooleanExtra("showIncomingCallScreen", false)
|
val showScreen = it.getBooleanExtra("showIncomingCallScreen", false)
|
||||||
Log.d(TAG, "Received incoming call intent for $phoneNumber, showScreen=$showScreen")
|
Log.d(TAG, "Received incoming call intent for $phoneNumber, showScreen=$showScreen")
|
||||||
if (showScreen) {
|
if (showScreen) {
|
||||||
MyInCallService.channel?.invokeMethod("incomingCallFromNotification", mapOf(
|
if (MyInCallService.channel != null) {
|
||||||
"phoneNumber" to phoneNumber
|
MyInCallService.channel?.invokeMethod("incomingCallFromNotification", mapOf(
|
||||||
))
|
"phoneNumber" to phoneNumber
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// Store the intent data if Flutter isn't ready yet
|
||||||
|
pendingIncomingCall = Pair(phoneNumber, true)
|
||||||
|
Log.d(TAG, "Flutter channel not ready, storing pending call: $phoneNumber")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,17 +85,15 @@ class MyInCallService : InCallService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showIncomingCallScreen(phoneNumber: String) {
|
private fun showIncomingCallScreen(phoneNumber: String) {
|
||||||
// Launch MainActivity with intent to show IncomingCallPage
|
|
||||||
val intent = Intent(this, MainActivity::class.java).apply {
|
val intent = Intent(this, MainActivity::class.java).apply {
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
putExtra("phoneNumber", phoneNumber)
|
putExtra("phoneNumber", phoneNumber)
|
||||||
putExtra("isIncomingCall", true)
|
putExtra("isIncomingCall", true)
|
||||||
putExtra("showIncomingCallScreen", true) // New flag to signal immediate UI
|
putExtra("showIncomingCallScreen", true)
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
Log.d(TAG, "Launched MainActivity to show incoming call screen for $phoneNumber")
|
Log.d(TAG, "Launched MainActivity to show incoming call screen for $phoneNumber")
|
||||||
|
|
||||||
// Optional: Keep notification as a fallback
|
|
||||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val channel = NotificationChannel(
|
val channel = NotificationChannel(
|
||||||
@ -116,7 +114,7 @@ class MyInCallService : InCallService() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
|
val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
|
||||||
.setSmallIcon(android.R.drawable.ic_dialog_alert) // Replace with your app icon
|
.setSmallIcon(android.R.drawable.ic_dialog_alert)
|
||||||
.setContentTitle("Incoming Call")
|
.setContentTitle("Incoming Call")
|
||||||
.setContentText("Call from $phoneNumber")
|
.setContentText("Call from $phoneNumber")
|
||||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
|
@ -55,6 +55,10 @@ class CallService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Signal Flutter is ready
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
_channel.invokeMethod("flutterReady");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _navigateToCallPage(BuildContext context) {
|
void _navigateToCallPage(BuildContext context) {
|
||||||
|
Loading…
Reference in New Issue
Block a user