feat: can mute mic in call
This commit is contained in:
parent
7339d5982e
commit
6c5ce1beab
@ -165,6 +165,19 @@ class MainActivity : FlutterActivity() {
|
||||
Log.d(TAG, "getCallState called, returning: $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)
|
||||
}
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.telecom.Call
|
||||
import android.telecom.InCallService
|
||||
@ -22,6 +23,24 @@ class MyInCallService : InCallService() {
|
||||
private const val NOTIFICATION_CHANNEL_ID = "incoming_call_channel"
|
||||
private const val NOTIFICATION_ID = 1
|
||||
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
|
||||
))
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to set mute state: $e")
|
||||
false
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
private val callCallback = object : Call.Callback() {
|
||||
@ -60,6 +79,7 @@ class MyInCallService : InCallService() {
|
||||
|
||||
override fun onCallAdded(call: Call) {
|
||||
super.onCallAdded(call)
|
||||
instance = this
|
||||
currentCall = call
|
||||
val stateStr = when (call.state) {
|
||||
Call.STATE_DIALING -> "dialing"
|
||||
@ -90,13 +110,17 @@ class MyInCallService : InCallService() {
|
||||
"wasPhoneLocked" to wasPhoneLocked
|
||||
))
|
||||
currentCall = null
|
||||
instance = null
|
||||
cancelNotification()
|
||||
}
|
||||
|
||||
override fun onCallAudioStateChanged(state: android.telecom.CallAudioState) {
|
||||
super.onCallAudioStateChanged(state)
|
||||
Log.d(TAG, "Audio state changed: route=${state.route}")
|
||||
channel?.invokeMethod("audioStateChanged", mapOf("route" to state.route))
|
||||
Log.d(TAG, "Audio state changed: route=${state.route}, muted=${state.isMuted}")
|
||||
channel?.invokeMethod("audioStateChanged", mapOf(
|
||||
"route" to state.route,
|
||||
"muted" to state.isMuted
|
||||
))
|
||||
}
|
||||
|
||||
private fun showIncomingCallScreen(phoneNumber: String) {
|
||||
|
@ -102,10 +102,31 @@ class _CallPageState extends State<CallPage> {
|
||||
});
|
||||
}
|
||||
|
||||
void _toggleMute() {
|
||||
void _toggleMute() async {
|
||||
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(() {
|
||||
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')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleSpeaker() {
|
||||
@ -298,7 +319,7 @@ class _CallPageState extends State<CallPage> {
|
||||
onPressed: _toggleMute,
|
||||
icon: Icon(
|
||||
isMuted ? Icons.mic_off : Icons.mic,
|
||||
color: Colors.white,
|
||||
color: isMuted ? Colors.amber : Colors.white,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
|
@ -144,6 +144,27 @@ 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()};
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_callStateController.close();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user