Flutter iOS端含*与#的USSD代码无法唤起拨号器(Android正常)
Flutter iOS端USSD代码执行问题(2025/2026)
问题概述
我的Flutter应用用于执行移动货币充值的USSD代码,2026年之前iOS端运行正常,但应用更新后,iPhone上的完整USSD代码无法执行。相同代码此前可正常运行,仅iOS端出现问题(测试iPhone 7、10、12),Android端运行正常。
关键测试发现
- 普通电话号码(如0123456789)可正常唤起拨号器 ✅
- 移除
*的USSD代码可正常唤起拨号器 ✅ - 移除
#的USSD代码可正常唤起拨号器 ✅ - 完整USSD代码(如
*140*1*70000000#)无任何反应 ❌
当前代码
static Future<void> ussd(String ussdCode) async { if (kIsAppleOS) { final Uri uri = Uri( scheme: 'tel', path: ussdCode, // e.g. *140*1*70000000# ); await launchUrl(uri); } else { await DirectCallPlus.makeCall(ussdCode); } }
环境信息
- Flutter版本:3.x
- 依赖包:
url_launcher: ^6.1.7、direct_call_plus: ^1.0.4 - iOS版本:15、16、17
- 测试设备:iPhone 7、10、12
已尝试方案
- 将
#编码为%23→ 仍被拦截 - 设置
mode: LaunchMode.externalApplication→ 无变化 - 使用
Uri.parse('tel:*140%231')替代Uri()→ 仍被拦截 - 尝试
ussd_launcher: ^1.5.0包 → 仅支持Android,无iOS适配
核心问题解答
是否还有办法在iOS端自动执行USSD代码?
没有。Apple在iOS 15及后续版本更新中,出于安全防护(防止恶意应用发起未经用户授权的扣费、权限操作),已完全封禁第三方APP通过tel:// scheme自动执行包含*和#的完整USSD代码。2025/2026年不存在官方或可稳定使用的第三方绕过方案,此限制是系统级的。
最佳UX降级策略
如果无法自动执行,可通过以下优化降低用户操作成本:
- 自动复制USSD代码到剪贴板:使用Flutter的
Clipboard类实现一键复制,复制后弹出提示告知用户代码已复制。 - 唤起拨号器并预填充代码:将编码后的USSD代码传入
tel://scheme,唤起拨号器时代码会自动填充到输入框,用户仅需点击“拨打”按钮即可。 - 清晰的分步引导:通过弹窗或页面说明操作步骤,比如:
1. 点击复制代码 → 2. 打开拨号器粘贴 → 3. 点击拨打,配合图标简化理解。 - 整合操作按钮:提供“复制并打开拨号器”的组合按钮,减少用户跳转步骤。
- 保存常用模板:针对高频使用的用户,允许保存USSD模板,下次调用时直接填充并唤起拨号器。
内容的提问来源于stack exchange,提问作者Abdoul Aziz TAO
相关产品推荐
相关产品推荐

