add
All checks were successful
/ mirror (push) Successful in 4s

This commit is contained in:
Bartosz 2025-02-15 14:35:47 +00:00
parent 90cea674d4
commit 1867c025fd
2 changed files with 100 additions and 13 deletions

View File

@ -1,4 +1,3 @@
// File: android/app/src/main/kotlin/com/example/dialer/MainActivity.kt
package com.example.dialer
import android.app.role.RoleManager
@ -7,6 +6,7 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
@ -14,6 +14,8 @@ import android.telecom.PhoneAccount
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
@ -25,6 +27,9 @@ class MainActivity : FlutterActivity() {
// Request code for the default-dialer request.
private val DEFAULT_DIALER_REQUEST_CODE = 1001
// Request code for runtime permissions.
private val PERMISSION_REQUEST_CODE = 1002
// BroadcastReceiver to catch incoming call events from our ConnectionService.
private val incomingCallReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
@ -49,6 +54,9 @@ class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Request runtime permissions.
checkAndRequestPermissions()
// Create the intent filter for incoming calls.
val filter = IntentFilter("com.example.dialer.INCOMING_CALL")
// Register the receiver. (For Android 13+ we must specify not exported.)
@ -121,16 +129,30 @@ class MainActivity : FlutterActivity() {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == DEFAULT_DIALER_REQUEST_CODE) {
Log.d("MainActivity", "onActivityResult received: resultCode=$resultCode")
// Delay a short time before checking the role.
Handler(mainLooper).postDelayed({
if (isDefaultDialer()) {
Log.d("MainActivity", "Default dialer successfully set")
registerManagedPhoneAccount()
notifyDefaultDialerSet()
} else {
Log.d("MainActivity", "Default dialer not set")
when (resultCode) {
RESULT_OK -> {
Log.d("MainActivity", "User granted default dialer role")
Handler(mainLooper).postDelayed({
if (isDefaultDialer()) {
Log.d("MainActivity", "Default dialer successfully set")
registerManagedPhoneAccount()
notifyDefaultDialerSet()
} else {
Log.d("MainActivity", "Default dialer not set")
// Notify Flutter that the default dialer role was not set
methodChannel.invokeMethod("onDefaultDialerNotSet", null)
}
}, 500)
}
}, 500)
RESULT_CANCELED -> {
Log.d("MainActivity", "User denied default dialer role")
// Notify Flutter that the user denied the request
methodChannel.invokeMethod("onDefaultDialerDenied", null)
}
else -> {
Log.d("MainActivity", "Unknown resultCode: $resultCode")
}
}
}
}
@ -146,6 +168,7 @@ class MainActivity : FlutterActivity() {
.setShortDescription("Icing Custom Dialer")
.build()
telecomManager.registerPhoneAccount(phoneAccount)
Log.d("MainActivity", "PhoneAccount registered")
}
// Notify Flutter that we are now the default dialer.
@ -157,4 +180,39 @@ class MainActivity : FlutterActivity() {
private fun notifyIncomingCall(phoneNumber: String) {
methodChannel.invokeMethod("onIncomingCall", phoneNumber)
}
}
// Check and request runtime permissions.
private fun checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val permissionsNeeded = mutableListOf<String>()
val permissionsToRequest = mutableListOf<String>()
// Check if permissions are granted
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.READ_PHONE_STATE)
}
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.CALL_PHONE)
}
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ANSWER_PHONE_CALLS) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(android.Manifest.permission.ANSWER_PHONE_CALLS)
}
// Request permissions if needed
if (permissionsToRequest.isNotEmpty()) {
ActivityCompat.requestPermissions(this, permissionsToRequest.toTypedArray(), PERMISSION_REQUEST_CODE)
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
Log.d("MainActivity", "All permissions granted")
} else {
Log.d("MainActivity", "Some permissions denied")
}
}
}
}

View File

@ -1,4 +1,3 @@
// File: lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -25,6 +24,8 @@ class _IcingDialerAppState extends State<IcingDialerApp> {
platform.setMethodCallHandler(handleMethodCalls);
}
Future<void> handleMethodCalls(MethodCall call) async {
switch (call.method) {
case 'onDefaultDialerSet':
@ -33,6 +34,10 @@ class _IcingDialerAppState extends State<IcingDialerApp> {
isDefaultDialer = true;
});
break;
case 'onDefaultDialerDenied':
// Show a message to the user when they deny the request.
_showDefaultDialerDeniedDialog();
break;
case 'onIncomingCall':
final phoneNumber = call.arguments as String? ?? "Unknown";
_showIncomingCallDialog(phoneNumber);
@ -42,6 +47,26 @@ class _IcingDialerAppState extends State<IcingDialerApp> {
}
}
// Show a dialog when the user denies the default dialer request.
void _showDefaultDialerDeniedDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Permission Denied'),
content: const Text(
'To use this app as your default dialer, please grant the permission when prompted.'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
),
);
}
// Show a dialog when an incoming call is intercepted.
void _showIncomingCallDialog(String phoneNumber) {
showDialog(
@ -76,6 +101,10 @@ class _IcingDialerAppState extends State<IcingDialerApp> {
await platform.invokeMethod('requestDefaultDialer');
} catch (e) {
print('Error requesting default dialer: $e');
// Show an error message if the request fails.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error requesting default dialer: $e')),
);
}
}
@ -135,4 +164,4 @@ class CallScreen extends StatelessWidget {
),
);
}
}
}