feat: speaker option in call
This commit is contained in:
parent
6c5ce1beab
commit
936250829b
@ -178,6 +178,19 @@ class MainActivity : FlutterActivity() {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.telecom.Call
|
||||
import android.telecom.InCallService
|
||||
import android.telecom.CallAudioState
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.icing.dialer.activities.MainActivity
|
||||
@ -32,7 +33,8 @@ class MyInCallService : InCallService() {
|
||||
audioManager.isMicrophoneMute = mute
|
||||
Log.d(TAG, "Set microphone mute state to $mute")
|
||||
channel?.invokeMethod("audioStateChanged", mapOf(
|
||||
"muted" to mute
|
||||
"muted" to mute,
|
||||
"speaker" to audioManager.isSpeakerphoneOn
|
||||
))
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
@ -41,6 +43,24 @@ class MyInCallService : InCallService() {
|
||||
}
|
||||
} ?: 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() {
|
||||
@ -119,7 +139,8 @@ class MyInCallService : InCallService() {
|
||||
Log.d(TAG, "Audio state changed: route=${state.route}, muted=${state.isMuted}")
|
||||
channel?.invokeMethod("audioStateChanged", mapOf(
|
||||
"route" to state.route,
|
||||
"muted" to state.isMuted
|
||||
"muted" to state.isMuted,
|
||||
"speaker" to (state.route == CallAudioState.ROUTE_SPEAKER)
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ class _CallPageState extends State<CallPage> {
|
||||
final ObfuscateService _obfuscateService = ObfuscateService();
|
||||
final CallService _callService = CallService();
|
||||
bool isMuted = false;
|
||||
bool isSpeakerOn = false;
|
||||
bool isSpeaker = false;
|
||||
bool isKeypadVisible = false;
|
||||
bool icingProtocolOk = true;
|
||||
String _typedDigits = "";
|
||||
@ -115,7 +115,8 @@ class _CallPageState extends State<CallPage> {
|
||||
print('CallPage: Failed to toggle mute: ${result['message']}');
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to toggle mute: ${result['message']}')),
|
||||
SnackBar(
|
||||
content: Text('Failed to toggle mute: ${result['message']}')),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -129,10 +130,30 @@ class _CallPageState extends State<CallPage> {
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleSpeaker() {
|
||||
Future<void> _toggleSpeaker() async {
|
||||
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(() {
|
||||
isSpeakerOn = !isSpeakerOn;
|
||||
isSpeaker = !isSpeaker;
|
||||
});
|
||||
} 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() {
|
||||
@ -168,7 +189,8 @@ class _CallPageState extends State<CallPage> {
|
||||
final double nameFontSize = isKeypadVisible ? 24.0 : 24.0;
|
||||
final double statusFontSize = isKeypadVisible ? 16.0 : 16.0;
|
||||
|
||||
print('CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}');
|
||||
print(
|
||||
'CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}');
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
color: Colors.black,
|
||||
@ -256,7 +278,8 @@ class _CallPageState extends State<CallPage> {
|
||||
IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: _toggleKeypad,
|
||||
icon: const Icon(Icons.close, color: Colors.white),
|
||||
icon:
|
||||
const Icon(Icons.close, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -319,7 +342,9 @@ class _CallPageState extends State<CallPage> {
|
||||
onPressed: _toggleMute,
|
||||
icon: Icon(
|
||||
isMuted ? Icons.mic_off : Icons.mic,
|
||||
color: isMuted ? Colors.amber : Colors.white,
|
||||
color: isMuted
|
||||
? Colors.amber
|
||||
: Colors.white,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
@ -354,10 +379,10 @@ class _CallPageState extends State<CallPage> {
|
||||
IconButton(
|
||||
onPressed: _toggleSpeaker,
|
||||
icon: Icon(
|
||||
isSpeakerOn
|
||||
isSpeaker
|
||||
? Icons.volume_up
|
||||
: Icons.volume_off,
|
||||
color: isSpeakerOn
|
||||
color: isSpeaker
|
||||
? Colors.amber
|
||||
: Colors.white,
|
||||
size: 32,
|
||||
|
@ -165,6 +165,21 @@ class CallService {
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
_callStateController.close();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user