diff --git a/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt b/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt index ee194a2..fd1b904 100644 --- a/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt +++ b/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt @@ -95,7 +95,6 @@ class MainActivity : FlutterActivity() { pendingIncomingCall = null } } - checkAndRequestDefaultDialer() result.success(true) } "makeGsmCall" -> { @@ -191,6 +190,15 @@ class MainActivity : FlutterActivity() { result.error("SPEAKER_FAILED", "No active call or failed to set speaker", null) } } + "isDefaultDialer" -> { + val isDefault = isDefaultDialer() + Log.d(TAG, "isDefaultDialer called, returning: $isDefault") + result.success(isDefault) + } + "requestDefaultDialer" -> { + checkAndRequestDefaultDialer() + result.success(true) + } else -> result.notImplemented() } } @@ -216,6 +224,13 @@ class MainActivity : FlutterActivity() { } } + private fun isDefaultDialer(): Boolean { + val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager + val currentDefault = telecomManager.defaultDialerPackage + Log.d(TAG, "Checking default dialer: current=$currentDefault, myPackage=$packageName") + return currentDefault == packageName + } + private fun checkAndRequestDefaultDialer() { val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager val currentDefault = telecomManager.defaultDialerPackage diff --git a/dialer/lib/features/home/default_dialer_prompt.dart b/dialer/lib/features/home/default_dialer_prompt.dart new file mode 100644 index 0000000..c2fc0f3 --- /dev/null +++ b/dialer/lib/features/home/default_dialer_prompt.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class DefaultDialerPromptScreen extends StatelessWidget { + const DefaultDialerPromptScreen({super.key}); + + Future _requestDefaultDialer(BuildContext context) async { + const channel = MethodChannel('call_service'); + try { + await channel.invokeMethod('requestDefaultDialer'); + // Navigate to home page after requesting default dialer + Navigator.of(context).pushReplacementNamed('/home'); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error requesting default dialer: $e')), + ); + } + } + + void _exploreApp(BuildContext context) { + // Navigate to home page without requesting default dialer + Navigator.of(context).pushReplacementNamed('/home'); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Set as Default Dialer', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 16), + Text( + 'To handle calls effectively, Icing needs to be your default dialer app. This allows Icing to manage incoming and outgoing calls seamlessly.\n\nWithout the permission, Icing will not be able to encrypt calls.', + style: TextStyle( + fontSize: 16, + color: Colors.white70, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + Row( + children: [ + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: ElevatedButton( + onPressed: () => _exploreApp(context), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey[800], + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 16, vertical: 12), + ), + child: Text('Explore App first'), + ), + ), + ), + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.only(left: 8.0), + child: ElevatedButton( + onPressed: () => _requestDefaultDialer(context), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 16, vertical: 12), + ), + child: Text('Set as Default Dialer'), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/dialer/lib/main.dart b/dialer/lib/main.dart index d3513cf..2cc72e3 100644 --- a/dialer/lib/main.dart +++ b/dialer/lib/main.dart @@ -1,4 +1,5 @@ import 'package:dialer/features/home/home_page.dart'; +import 'package:dialer/features/home/default_dialer_prompt.dart'; import 'package:flutter/material.dart'; import 'package:dialer/features/contacts/contact_state.dart'; import 'package:dialer/services/call_service.dart'; @@ -51,6 +52,17 @@ Future _requestPermissions() async { class Dialer extends StatelessWidget { const Dialer({super.key}); + Future _isDefaultDialer() async { + const channel = MethodChannel('call_service'); + try { + final isDefault = await channel.invokeMethod('isDefaultDialer'); + return isDefault ?? false; + } catch (e) { + print('Error checking default dialer: $e'); + return false; + } + } + @override Widget build(BuildContext context) { return ContactState( @@ -59,7 +71,24 @@ class Dialer extends StatelessWidget { theme: ThemeData( brightness: Brightness.dark, ), - home: SafeArea(child: MyHomePage()), + initialRoute: '/', + routes: { + '/': (context) => FutureBuilder( + future: _isDefaultDialer(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Scaffold( + body: Center(child: CircularProgressIndicator()), + ); + } + if (snapshot.hasError || !snapshot.hasData || snapshot.data == false) { + return DefaultDialerPromptScreen(); + } + return SafeArea(child: MyHomePage()); + }, + ), + '/home': (context) => SafeArea(child: MyHomePage()), + }, ), ); }