Open Punit30 opened 6 months ago
Any updates on this issue??
Hi @Dev-Devarsh, I am no longer syncing mute with the Twilio Voice package. Instead, I am managing mute at the widget level. If the "call.toggleMute()" function is successful, I handle mute accordingly. Similarly, I have applied the same approach for hold. Previously, checking for the isHold function resulted in triggering the hold/unhold event on iOS devices, leading to an infinite loop that persists until the call ends.
I am unable to understand managing mute at the widget level. Can please explain in brief..!
I am no longer using "TwilioVoice.instance.call.isMuted()" function or check mute/unmute call event to get mute status. Instead, Directly checking success message from "TwilioVoice.instance.call.toggleMute()" and toggle isMute variable inside the widget itself.
await TwilioVoice.instance.call.toogleMute().then((value) {
if(value == true) {
setState(() {
isMute = !isMute;
};
} else {
showSnackBar("Unable to mute/unmute the call. Please try again.", "error", context);
}
});
Hope the above code would be helpful!
Issue Summary
I am developing a custom UI for calling, and I'm facing an issue where the unmute event is triggered when toggling the speaker, but the call remains muted. I am unsure why this is happening. Additionally, when checking with TwilioVoice.instance.call.isMuted(), it returns a false value after the speaker is toggled. Also, the function and Native Call UI of android is not in sync if trigger on native call UI it does not reflect on app UI. I am seeking assistance to understand and resolve these issues.
Steps to Reproduce
import 'package:flutter/material.dart'; import 'package:flutter_libphonenumber/flutter_libphonenumber.dart'; import 'package:ionicons/ionicons.dart'; import 'package:softphone_mobile_app/screens/keypad/controller/keypad_controller.dart'; import 'package:softphone_mobile_app/screens/keypad/widgets/caller_info.dart'; import 'package:softphone_mobile_app/screens/keypad/widgets/circular_button.dart'; import 'package:softphone_mobile_app/screens/keypad/widgets/dial_pad_grid.dart'; import 'package:softphone_mobile_app/screens/keypad/widgets/phone_input_field.dart'; import 'package:softphone_mobile_app/themes/pallete.dart'; import 'package:twilio_voice/twilio_voice.dart';
class OutGoingView extends StatefulWidget { static route() => MaterialPageRoute(builder: (context) => const OutGoingView());
const OutGoingView({super.key});
@override State createState() => _OutGoingViewState();
}
class _OutGoingViewState extends State {
TextEditingController controller = TextEditingController();
KeypadController keypadController = KeypadController();
late final StreamSubscription _subscription;
final _events = [];
bool onMute = false; set stateMute(bool value) { setState(() { onMute = value; }); }
bool onHold = false; set stateHold(bool value) { setState(() { onHold = value; }); }
bool onSpeaker = false; set stateSpeaker(bool value) { setState(() { onSpeaker = value; }); }
bool onBluetooth = false; set stateBluetooth(bool value) { setState(() { onBluetooth = value; }); }
bool isKeypadActive = false; set stateKeypadActive(bool value) { setState(() { isKeypadActive = value; }); }
final _tv = TwilioVoice.instance; bool activeCall = false;
@override void initState() { super.initState(); _subscription = _tv.callEventsListener.listen((event) { _events.add(event); switch (event) { case CallEvent.unmute: print(" +++++++++++ unmute ++++++++"); stateMute = false; break; case CallEvent.mute: print("---------- mute ---------"); stateMute = true; break; case CallEvent.unhold: case CallEvent.hold: case CallEvent.speakerOn: case CallEvent.speakerOff: case CallEvent.bluetoothOn: case CallEvent.bluetoothOff: _updateStates(); break;
}
void _updateStates() { // get all states from call _tv.call.isMuted().then((value) => stateMute = value ?? false); _tv.call.isHolding().then((value) => stateHold = value ?? false); _tv.call.isOnSpeaker().then((value) => stateSpeaker = value ?? false); _tv.call.isBluetoothOn().then((value) => stateBluetooth = value ?? false); }
@override void dispose() { _subscription.cancel(); controller.dispose(); super.dispose(); }
@override Widget build(BuildContext context) { double screenHeight = MediaQuery.of(context).size.height;
} }