This commit is contained in:
parent
21f470a464
commit
ae56fc876f
@ -15,7 +15,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:enableOnBackInvokedCallback="true">
|
android:enableOnBackInvokedCallback="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
|
@ -1,22 +1,46 @@
|
|||||||
package com.icing.dialer
|
package com.icing.dialer.activities
|
||||||
|
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.CallLog
|
import android.provider.CallLog
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
import com.icing.dialer.KeystoreHelper
|
import com.icing.dialer.KeystoreHelper
|
||||||
|
import com.icing.dialer.services.CallService
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity: FlutterActivity() {
|
||||||
// Existing channel for keystore operations.
|
// Existing channel for keystore operations.
|
||||||
private val KEYSTORE_CHANNEL = "com.example.keystore"
|
private val KEYSTORE_CHANNEL = "com.example.keystore"
|
||||||
// New channel for call log access.
|
// New channel for call log access.
|
||||||
private val CALLLOG_CHANNEL = "com.example.calllog"
|
private val CALLLOG_CHANNEL = "com.example.calllog"
|
||||||
|
|
||||||
|
private val CALL_CHANNEL = "call_service"
|
||||||
|
|
||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
super.configureFlutterEngine(flutterEngine)
|
super.configureFlutterEngine(flutterEngine)
|
||||||
|
|
||||||
|
// Call service channel
|
||||||
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL).setMethodCallHandler { call, result ->
|
||||||
|
when (call.method) {
|
||||||
|
"makeGsmCall" -> {
|
||||||
|
val phoneNumber = call.argument<String>("phoneNumber")
|
||||||
|
if (phoneNumber != null) {
|
||||||
|
CallService.makeGsmCall(this, phoneNumber)
|
||||||
|
result.success("Calling $phoneNumber")
|
||||||
|
} else {
|
||||||
|
result.error("INVALID_PHONE_NUMBER", "Phone number is required", null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"hangUpCall" -> {
|
||||||
|
CallService.hangUpCall(this)
|
||||||
|
result.success("Call ended")
|
||||||
|
}
|
||||||
|
else -> result.notImplemented()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the keystore channel.
|
// Set up the keystore channel.
|
||||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, KEYSTORE_CHANNEL)
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, KEYSTORE_CHANNEL)
|
||||||
.setMethodCallHandler { call, result ->
|
.setMethodCallHandler { call, result ->
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.icing.dialer.services
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.telecom.TelecomManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
object CallService {
|
||||||
|
|
||||||
|
fun makeGsmCall(context: Context, phoneNumber: String) {
|
||||||
|
try {
|
||||||
|
val intent = Intent(Intent.ACTION_CALL)
|
||||||
|
intent.data = Uri.parse("tel:$phoneNumber")
|
||||||
|
context.startActivity(intent)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("CallService", "Error making GSM call: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hangUpCall(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
|
||||||
|
telecomManager.endCall()
|
||||||
|
} else {
|
||||||
|
Log.e("CallService", "Hangup call is only supported on Android P or later.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
// lib/pages/composition_page.dart
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_contacts/flutter_contacts.dart';
|
import 'package:flutter_contacts/flutter_contacts.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import '../../services/contact_service.dart';
|
import '../../services/contact_service.dart';
|
||||||
import '../../services/obfuscate_service.dart'; // Import ObfuscateService
|
import '../../services/obfuscate_service.dart'; // Import ObfuscateService
|
||||||
|
import '../../services/call_service.dart'; // Import the CallService
|
||||||
import '../contacts/widgets/add_contact_button.dart';
|
import '../contacts/widgets/add_contact_button.dart';
|
||||||
|
|
||||||
class CompositionPage extends StatefulWidget {
|
class CompositionPage extends StatefulWidget {
|
||||||
@ -23,6 +22,9 @@ class _CompositionPageState extends State<CompositionPage> {
|
|||||||
// Instantiate the ObfuscateService
|
// Instantiate the ObfuscateService
|
||||||
final ObfuscateService _obfuscateService = ObfuscateService();
|
final ObfuscateService _obfuscateService = ObfuscateService();
|
||||||
|
|
||||||
|
// Instantiate the CallService
|
||||||
|
final CallService _callService = CallService();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -71,13 +73,15 @@ class _CompositionPageState extends State<CompositionPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to call a contact's number
|
// Function to call a contact's number using the CallService
|
||||||
void _launchPhoneDialer(String phoneNumber) async {
|
void _makeCall(String phoneNumber) async {
|
||||||
final uri = Uri(scheme: 'tel', path: phoneNumber);
|
try {
|
||||||
if (await canLaunchUrl(uri)) {
|
await _callService.makeGsmCall(phoneNumber);
|
||||||
await launchUrl(uri);
|
setState(() {
|
||||||
} else {
|
dialedNumber = phoneNumber;
|
||||||
debugPrint('Could not launch $phoneNumber');
|
});
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("Error making call: $e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,13 +132,13 @@ class _CompositionPageState extends State<CompositionPage> {
|
|||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// Call button
|
// Call button (Now using CallService)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.phone,
|
icon: Icon(Icons.phone,
|
||||||
color: Colors.green[300],
|
color: Colors.green[300],
|
||||||
size: 20),
|
size: 20),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_launchPhoneDialer(phoneNumber);
|
_makeCall(phoneNumber); // Make a call using CallService
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// Message button
|
// Message button
|
||||||
|
@ -5,6 +5,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
import 'package:dialer/widgets/username_color_generator.dart';
|
import 'package:dialer/widgets/username_color_generator.dart';
|
||||||
import '../../../services/block_service.dart';
|
import '../../../services/block_service.dart';
|
||||||
import '../../../services/contact_service.dart';
|
import '../../../services/contact_service.dart';
|
||||||
|
import '../../../services/call_service.dart'; // Import CallService
|
||||||
|
|
||||||
class ContactModal extends StatefulWidget {
|
class ContactModal extends StatefulWidget {
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
@ -28,6 +29,7 @@ class _ContactModalState extends State<ContactModal> {
|
|||||||
late String phoneNumber;
|
late String phoneNumber;
|
||||||
bool isBlocked = false;
|
bool isBlocked = false;
|
||||||
final ObfuscateService _obfuscateService = ObfuscateService();
|
final ObfuscateService _obfuscateService = ObfuscateService();
|
||||||
|
final CallService _callService = CallService(); // Instantiate CallService
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -258,9 +260,9 @@ class _ContactModalState extends State<ContactModal> {
|
|||||||
_obfuscateService.obfuscateData(phoneNumber),
|
_obfuscateService.obfuscateData(phoneNumber),
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
if (widget.contact.phones.isNotEmpty) {
|
if (widget.contact.phones.isNotEmpty) {
|
||||||
_launchPhoneDialer(phoneNumber);
|
await _callService.makeGsmCall(phoneNumber);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -329,12 +331,11 @@ class _ContactModalState extends State<ContactModal> {
|
|||||||
icon: Icon(
|
icon: Icon(
|
||||||
isBlocked ? Icons.block : Icons.block_flipped),
|
isBlocked ? Icons.block : Icons.block_flipped),
|
||||||
label: Text(isBlocked ? 'Unblock' : 'Block'),
|
label: Text(isBlocked ? 'Unblock' : 'Block'),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
26
dialer/lib/services/call_service.dart
Normal file
26
dialer/lib/services/call_service.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
// Service to manage call-related operations
|
||||||
|
class CallService {
|
||||||
|
static const MethodChannel _channel = MethodChannel('call_service');
|
||||||
|
|
||||||
|
// Function to make a GSM call
|
||||||
|
Future<void> makeGsmCall(String phoneNumber) async {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('makeGsmCall', {"phoneNumber": phoneNumber});
|
||||||
|
} catch (e) {
|
||||||
|
print("Error making call: $e");
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to hang up the current call
|
||||||
|
Future<void> hangUpCall() async {
|
||||||
|
try {
|
||||||
|
await _channel.invokeMethod('hangUpCall');
|
||||||
|
} catch (e) {
|
||||||
|
print("Error hanging up call: $e");
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user