英文:
Update UI from callback in flutter
问题
我正在使用Flutter制作电话呼叫应用程序。这里将进行拨出电话。在完成电话呼叫后,必须通过API提交客户反馈。提交按钮将在断开电话呼叫后激活。
我在电话方面使用flutter_phone_direct_caller,在电话呼叫状态方面使用phone_state_background。
class MyCallPage extends StatefulWidget {
const MyCallPage({Key? key});
@override
State<MyCallPage> createState() => _MyCallPageState();
}
class _MyCallPageState extends State<MyCallPage> with WidgetsBindingObserver {
TextEditingController controller = TextEditingController();
bool hasPermission = false;
@override
void initState() {
WidgetsBinding.instance!.addObserver(this);
_hasPermission();
controller.text = '';
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance!.removeObserver(this);
controller.dispose();
super.dispose();
}
Future<void> _hasPermission() async {
final permission = await PhoneStateBackground.checkPermission();
if (mounted) {
setState(() => hasPermission = permission);
}
}
Future<void> _requestPermission() async {
await PhoneStateBackground.requestPermissions();
_init();
}
Future<void> _stop() async {
await PhoneStateBackground.stopPhoneStateBackground();
}
Future<void> _init() async {
if (hasPermission != true) {
await _hasPermission();
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
} else {
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Detected Phone Call'),
),
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 8.0, bottom: 8.0),
child: TextField(
controller: controller,
textAlign: TextAlign.center,
),
),
const SizedBox(height: 15.0),
// ---- call button ----
SizedBox(
width: 150,
child: ElevatedButton(
onPressed: () {
_init();
},
child: const Text('Call'))),
const SizedBox(height: 15.0),
// ---- api button ----
ElevatedButton(
onPressed: () {
// ----- 这里放API逻辑 ----
},
child: const Text('Submit'))
],
),
),
),
);
}
_callPhone() async {
if (controller.text.trim().isNotEmpty) {
await FlutterPhoneDirectCaller.callNumber(controller.text.trim());
} else {
_stop();
}
}
}
回调函数是:
// 请务必在回调函数上添加 @pragma('vm:entry-point') 以避免在Flutter >= 3.3.0的发布模式下出现问题
@pragma('vm:entry-point')
// 定义一个处理所有后台传入事件的回调函数
Future phoneStateBackgroundCallbackHandler(
PhoneStateBackgroundEvent event,
String number,
int duration,
) async {
switch (event) {
case PhoneStateBackgroundEvent.incomingstart:
log('Incoming call start, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingmissed:
log('Incoming call missed, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingreceived:
log('Incoming call received, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingend:
log('Incoming call ended, number: $number, duration $duration s');
break;
case PhoneStateBackgroundEvent.outgoingstart:
log('Outgoing call start, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.outgoingend:
log('Outgoing call ended, number: $number, duration: $duration s');
break;
}
}
现在,我无法启用或禁用提交按钮。尝试使用Riverpod和Provider也无法在这里工作。请帮助我。
英文:
I am making telecall app on flutter. Out going Phone calls will be made here. After complete phone call have to submit customer feedback by API. Sumit button will be activate after disconnect the phone call.
I am using flutter_phone_direct_caller for phone and phone_state_background for Phone Call State.
class MyCallPage extends StatefulWidget {
const MyCallPage({super.key});
@override
State<MyCallPage> createState() => _MyCallPageState();
}
class _MyCallPageState extends State<MyCallPage> with WidgetsBindingObserver {
TextEditingController controller = TextEditingController();
bool hasPermission = false;
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
_hasPermission();
controller.text = '';
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
controller.dispose();
super.dispose();
}
Future<void> _hasPermission() async {
final permission = await PhoneStateBackground.checkPermission();
if (mounted) {
setState(() => hasPermission = permission);
}
}
Future<void> _requestPermission() async {
await PhoneStateBackground.requestPermissions();
_init();
}
Future<void> _stop() async {
await PhoneStateBackground.stopPhoneStateBackground();
}
Future<void> _init() async {
if (hasPermission != true) {
await _hasPermission();
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
} else {
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Detected Phone Call'),
),
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 8.0, bottom: 8.0),
child: TextField(
controller: controller,
textAlign: TextAlign.center,
),
),
const SizedBox(height: 15.0),
// ---- call button ----
SizedBox(
width: 150,
child: ElevatedButton(
onPressed: () {
_init();
},
child: const Text('Call'))),
const SizedBox(height: 15.0),
// ---- api button ----
ElevatedButton(
onPressed: () {
// ----- here goes api logic ----
},
child: const Text('Submit'))
],
),
),
),
);
}
_callPhone() async {
if (controller.text.trim().isNotEmpty) {
await FlutterPhoneDirectCaller.callNumber(controller.text.trim());
} else {
_stop();
}
}
}class MyCallPage extends StatefulWidget {
const MyCallPage({super.key});
@override
State<MyCallPage> createState() => _MyCallPageState();
}
class _MyCallPageState extends State<MyCallPage> with WidgetsBindingObserver {
TextEditingController controller = TextEditingController();
bool hasPermission = false;
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
_hasPermission();
controller.text = '';
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
controller.dispose();
super.dispose();
}
Future<void> _hasPermission() async {
final permission = await PhoneStateBackground.checkPermission();
if (mounted) {
setState(() => hasPermission = permission);
}
}
Future<void> _requestPermission() async {
await PhoneStateBackground.requestPermissions();
_init();
}
Future<void> _stop() async {
await PhoneStateBackground.stopPhoneStateBackground();
}
Future<void> _init() async {
if (hasPermission != true) {
await _hasPermission();
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
} else {
await PhoneStateBackground.initialize(
phoneStateBackgroundCallbackHandler);
_callPhone();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Detected Phone Call'),
),
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 8.0, bottom: 8.0),
child: TextField(
controller: controller,
textAlign: TextAlign.center,
),
),
const SizedBox(height: 15.0),
// ---- call button ----
SizedBox(
width: 150,
child: ElevatedButton(
onPressed: () {
_init();
},
child: const Text('Call'))),
const SizedBox(height: 15.0),
// ---- api button ----
ElevatedButton(
onPressed: () {
// ----- here goes api logic ----
},
child: const Text('Submit'))
],
),
),
),
);
}
_callPhone() async {
if (controller.text.trim().isNotEmpty) {
await FlutterPhoneDirectCaller.callNumber(controller.text.trim());
} else {
_stop();
}
}
}
call back function is
// Be sure to annotate @pragma('vm:entry-point') your callback function to avoid issues in
// release mode on Flutter >= 3.3.0
@pragma('vm:entry-point')
// Defines a callback that will handle all background incoming events
Future phoneStateBackgroundCallbackHandler(
PhoneStateBackgroundEvent event,
String number,
int duration,
) async {
switch (event) {
case PhoneStateBackgroundEvent.incomingstart:
log('Incoming call start, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingmissed:
log('Incoming call missed, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingreceived:
log('Incoming call received, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.incomingend:
log('Incoming call ended, number: $number, duration $duration s');
break;
case PhoneStateBackgroundEvent.outgoingstart:
log('Outgoing call start, number: $number, duration: $duration s');
break;
case PhoneStateBackgroundEvent.outgoingend:
log('Outgoing call ended, number: $number, duration: $duration s');
break;
}
}
Now I can not enable or disable submit button. try with riverpod, provider also not working here. please help me.
答案1
得分: 1
使用隔离服务器,并在其上使用监听器。在初始化时注册隔离服务器,并在处理时将其移除。从您定义的函数中使用回调。
英文:
Use Isolated Server and use a listener on it. Register the Isolated Server from init and remove it from dispose. Use call back from your defined function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论