Flutter多会话USSD请求开发遇RangeError问题求助
问题解决方案
一、解决RangeError错误
报错的直接原因是你调用UssdAdvanced.multisessionUssd时传入的subscriptionId: 1无效。大多数单SIM卡设备的subscriptionId为0,插件内部处理该参数时尝试访问索引1的数组元素,但数组仅包含索引0的元素,导致越界。
修复方法:
- 单SIM设备直接传0:
String? _res = await UssdAdvanced.multisessionUssd( code: _requestCode, subscriptionId: 0); // 将1改为0
- 多SIM设备动态获取ID:
如果需要支持多SIM卡,可先获取设备SIM卡列表,再选择对应ID:
List<SimCard> simCards = await UssdAdvanced.getSimCards(); if (simCards.isNotEmpty) { String? _res = await UssdAdvanced.multisessionUssd( code: _requestCode, subscriptionId: simCards[0].subscriptionId); }
二、多会话USSD的正确实现逻辑
当前代码硬编码发送'0',仅适用于固定流程,无法处理动态USSD菜单。正确的多会话处理需要根据每一步的USSD响应动态交互:
核心步骤:
- 发起多会话请求,获取初始响应
- 将响应展示给用户,提供输入框让用户选择下一步指令
- 发送用户输入的指令,获取新响应
- 重复交互直到用户结束会话或流程终止
- 展示最终结果
修改后的代码示例:
// 在_MultiUssdState中添加变量 bool _inSession = false; String _currentUssdResponse = ""; final TextEditingController _inputController = TextEditingController(); // 修改按钮点击逻辑 onPressed: _requestState == RequestState.ongoing || _inSession ? null : () async { setState(() { _requestState = RequestState.ongoing; }); try { await Permission.phone.request(); if (!await Permission.phone.isGranted) { throw Exception("permission missing"); } // 发起多会话请求 String initialResponse = await UssdAdvanced.multisessionUssd( code: _requestCode, subscriptionId: 0); setState(() { _requestState = RequestState.success; _currentUssdResponse = initialResponse; _inSession = true; }); // 会话交互循环 while (_inSession) { String? userInput = await showDialog<String>( context: context, builder: (context) => AlertDialog( title: const Text("USSD菜单"), content: Column( mainAxisSize: MainAxisSize.min, children: [ Text(_currentUssdResponse), const SizedBox(height: 16), TextField( controller: _inputController, decoration: const InputDecoration(hintText: "输入选项(如1、2)"), keyboardType: TextInputType.number, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context, null), child: const Text("结束会话"), ), TextButton( onPressed: () { Navigator.pop(context, _inputController.text.trim()); _inputController.clear(); }, child: const Text("发送"), ), ], ), ); if (userInput == null) { await UssdAdvanced.cancelSession(); setState(() { _inSession = false; _responseMessage = "会话已结束"; }); break; } String newResponse = await UssdAdvanced.sendMessage(userInput); setState(() { _currentUssdResponse = newResponse; }); // 根据运营商返回判断是否结束会话(需自定义关键词) if (newResponse.contains("成功") || newResponse.contains("完成")) { await UssdAdvanced.cancelSession(); setState(() { _inSession = false; _responseMessage = newResponse; }); break; } } } on PlatformException catch (e) { setState(() { _requestState = RequestState.error; _responseCode = e.code; _responseMessage = e.message ?? ''; _inSession = false; }); } },
三、额外注意事项
- 权限配置:在AndroidManifest.xml中添加
READ_PHONE_STATE和CALL_PHONE权限,USSD操作依赖这些权限。 - 运营商适配:不同运营商的USSD返回格式存在差异,需根据实际返回内容调整菜单解析逻辑。
- 超时处理:添加会话超时机制,避免无响应导致应用卡顿。
内容的提问来源于stack exchange,提问作者eric tiobo
相关产品推荐
相关产品推荐

