Compare commits

..

No commits in common. "936250829be1aa5d6d84ee6836fddbb2e5fd24af" and "7339d5982ef2b39a9b17cdcc3b7529ec140fd5cc" have entirely different histories.

4 changed files with 17 additions and 170 deletions

View File

@ -165,32 +165,6 @@ class MainActivity : FlutterActivity() {
Log.d(TAG, "getCallState called, returning: $stateStr") Log.d(TAG, "getCallState called, returning: $stateStr")
result.success(stateStr) result.success(stateStr)
} }
"muteCall" -> {
val mute = call.argument<Boolean>("mute") ?: false
val success = MyInCallService.currentCall?.let {
MyInCallService.toggleMute(mute)
} ?: false
if (success) {
Log.d(TAG, "Mute call set to $mute")
result.success(mapOf("status" to "success"))
} else {
Log.w(TAG, "No active call or failed to mute")
result.error("MUTE_FAILED", "No active call or failed to mute", null)
}
}
"speakerCall" -> {
val speaker = call.argument<Boolean>("speaker") ?: false
val success = MyInCallService.currentCall?.let {
MyInCallService.toggleSpeaker(speaker)
} ?: false
if (success) {
Log.d(TAG, "Speaker call set to $speaker")
result.success(mapOf("status" to "success"))
} else {
Log.w(TAG, "No active call or failed to set speaker")
result.error("SPEAKER_FAILED", "No active call or failed to set speaker", null)
}
}
else -> result.notImplemented() else -> result.notImplemented()
} }
} }

View File

@ -6,11 +6,9 @@ import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.AudioManager
import android.os.Build import android.os.Build
import android.telecom.Call import android.telecom.Call
import android.telecom.InCallService import android.telecom.InCallService
import android.telecom.CallAudioState
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.icing.dialer.activities.MainActivity import com.icing.dialer.activities.MainActivity
@ -24,43 +22,6 @@ class MyInCallService : InCallService() {
private const val NOTIFICATION_CHANNEL_ID = "incoming_call_channel" private const val NOTIFICATION_CHANNEL_ID = "incoming_call_channel"
private const val NOTIFICATION_ID = 1 private const val NOTIFICATION_ID = 1
var wasPhoneLocked: Boolean = false var wasPhoneLocked: Boolean = false
private var instance: MyInCallService? = null
fun toggleMute(mute: Boolean): Boolean {
return instance?.let { service ->
try {
val audioManager = service.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.isMicrophoneMute = mute
Log.d(TAG, "Set microphone mute state to $mute")
channel?.invokeMethod("audioStateChanged", mapOf(
"muted" to mute,
"speaker" to audioManager.isSpeakerphoneOn
))
true
} catch (e: Exception) {
Log.e(TAG, "Failed to set mute state: $e")
false
}
} ?: false
}
fun toggleSpeaker(speaker: Boolean): Boolean {
return instance?.let { service ->
try {
val audioManager = service.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.isSpeakerphoneOn = speaker
Log.d(TAG, "Set speakerphone state to $speaker")
channel?.invokeMethod("audioStateChanged", mapOf(
"muted" to audioManager.isMicrophoneMute,
"speaker" to speaker
))
true
} catch (e: Exception) {
Log.e(TAG, "Failed to set speaker state: $e")
false
}
} ?: false
}
} }
private val callCallback = object : Call.Callback() { private val callCallback = object : Call.Callback() {
@ -99,7 +60,6 @@ class MyInCallService : InCallService() {
override fun onCallAdded(call: Call) { override fun onCallAdded(call: Call) {
super.onCallAdded(call) super.onCallAdded(call)
instance = this
currentCall = call currentCall = call
val stateStr = when (call.state) { val stateStr = when (call.state) {
Call.STATE_DIALING -> "dialing" Call.STATE_DIALING -> "dialing"
@ -130,18 +90,13 @@ class MyInCallService : InCallService() {
"wasPhoneLocked" to wasPhoneLocked "wasPhoneLocked" to wasPhoneLocked
)) ))
currentCall = null currentCall = null
instance = null
cancelNotification() cancelNotification()
} }
override fun onCallAudioStateChanged(state: android.telecom.CallAudioState) { override fun onCallAudioStateChanged(state: android.telecom.CallAudioState) {
super.onCallAudioStateChanged(state) super.onCallAudioStateChanged(state)
Log.d(TAG, "Audio state changed: route=${state.route}, muted=${state.isMuted}") Log.d(TAG, "Audio state changed: route=${state.route}")
channel?.invokeMethod("audioStateChanged", mapOf( channel?.invokeMethod("audioStateChanged", mapOf("route" to state.route))
"route" to state.route,
"muted" to state.isMuted,
"speaker" to (state.route == CallAudioState.ROUTE_SPEAKER)
))
} }
private fun showIncomingCallScreen(phoneNumber: String) { private fun showIncomingCallScreen(phoneNumber: String) {

View File

@ -25,7 +25,7 @@ class _CallPageState extends State<CallPage> {
final ObfuscateService _obfuscateService = ObfuscateService(); final ObfuscateService _obfuscateService = ObfuscateService();
final CallService _callService = CallService(); final CallService _callService = CallService();
bool isMuted = false; bool isMuted = false;
bool isSpeaker = false; bool isSpeakerOn = false;
bool isKeypadVisible = false; bool isKeypadVisible = false;
bool icingProtocolOk = true; bool icingProtocolOk = true;
String _typedDigits = ""; String _typedDigits = "";
@ -102,58 +102,16 @@ class _CallPageState extends State<CallPage> {
}); });
} }
void _toggleMute() async { void _toggleMute() {
try {
print('CallPage: Toggling mute, current state: $isMuted');
final result = await _callService.muteCall(context, mute: !isMuted);
print('CallPage: Mute call result: $result');
if (mounted && result['status'] == 'success') {
setState(() { setState(() {
isMuted = !isMuted; isMuted = !isMuted;
}); });
} else {
print('CallPage: Failed to toggle mute: ${result['message']}');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to toggle mute: ${result['message']}')),
);
}
}
} catch (e) {
print('CallPage: Error toggling mute: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error toggling mute: $e')),
);
}
}
} }
Future<void> _toggleSpeaker() async { void _toggleSpeaker() {
try {
print('CallPage: Toggling speaker, current state: $isSpeaker');
final result =
await _callService.speakerCall(context, speaker: !isSpeaker);
print('CallPage: Speaker call result: $result');
if (result['status'] == 'success') {
setState(() { setState(() {
isSpeaker = !isSpeaker; isSpeakerOn = !isSpeakerOn;
}); });
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to toggle speaker: ${result['message']}')),
);
}
} catch (e) {
print('CallPage: Error toggling speaker: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error toggling speaker: $e')),
);
}
}
} }
void _toggleKeypad() { void _toggleKeypad() {
@ -189,8 +147,7 @@ class _CallPageState extends State<CallPage> {
final double nameFontSize = isKeypadVisible ? 24.0 : 24.0; final double nameFontSize = isKeypadVisible ? 24.0 : 24.0;
final double statusFontSize = isKeypadVisible ? 16.0 : 16.0; final double statusFontSize = isKeypadVisible ? 16.0 : 16.0;
print( print('CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}');
'CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}');
return Scaffold( return Scaffold(
body: Container( body: Container(
color: Colors.black, color: Colors.black,
@ -278,8 +235,7 @@ class _CallPageState extends State<CallPage> {
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: _toggleKeypad, onPressed: _toggleKeypad,
icon: icon: const Icon(Icons.close, color: Colors.white),
const Icon(Icons.close, color: Colors.white),
), ),
], ],
), ),
@ -342,9 +298,7 @@ class _CallPageState extends State<CallPage> {
onPressed: _toggleMute, onPressed: _toggleMute,
icon: Icon( icon: Icon(
isMuted ? Icons.mic_off : Icons.mic, isMuted ? Icons.mic_off : Icons.mic,
color: isMuted color: Colors.white,
? Colors.amber
: Colors.white,
size: 32, size: 32,
), ),
), ),
@ -379,10 +333,10 @@ class _CallPageState extends State<CallPage> {
IconButton( IconButton(
onPressed: _toggleSpeaker, onPressed: _toggleSpeaker,
icon: Icon( icon: Icon(
isSpeaker isSpeakerOn
? Icons.volume_up ? Icons.volume_up
: Icons.volume_off, : Icons.volume_off,
color: isSpeaker color: isSpeakerOn
? Colors.amber ? Colors.amber
: Colors.white, : Colors.white,
size: 32, size: 32,

View File

@ -144,42 +144,6 @@ class CallService {
} }
} }
Future<Map<String, dynamic>> muteCall(BuildContext context, {required bool mute}) async {
try {
print('CallService: Toggling mute to $mute');
final result = await _channel.invokeMethod('muteCall', {'mute': mute});
print('CallService: muteCall result: $result');
final resultMap = Map<String, dynamic>.from(result as Map);
if (resultMap['status'] != 'success') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to toggle mute')),
);
}
return resultMap;
} catch (e) {
print('CallService: Error toggling mute: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error toggling mute: $e')),
);
return {'status': 'error', 'message': e.toString()};
}
}
Future<Map<String, dynamic>> speakerCall(BuildContext context, {required bool speaker}) async {
try {
print('CallService: Toggling speaker to $speaker');
final result = await _channel.invokeMethod('speakerCall', {'speaker': speaker});
print('CallService: speakerCall result: $result');
return Map<String, dynamic>.from(result);
} catch (e) {
print('CallService: Error toggling speaker: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to toggle speaker: $e')),
);
return {'status': 'error', 'message': e.toString()};
}
}
void dispose() { void dispose() {
_callStateController.close(); _callStateController.close();
} }