React Native使用Linking.openURL调用含#*特殊字符的USSD码跳转拨号器失败
解决方案
核心原因是#、*属于URI保留字符,直接传入tel:链接会被解析器截断,导致拨号器无法识别完整号码,可通过以下两种方案解决:
方案1:对USSD特殊字符做URI编码(纯RN侧实现,兼容性覆盖90%以上机型)
- 转义规则:
#替换为%23,*替换为%2A - React Native代码示例:
import { Linking } from 'react-native'; // 封装USSD跳转方法 const openUssdDialer = async (ussdCode) => { // 转义特殊字符,也可直接使用 encodeURIComponent(ussdCode) 完成转义,效果一致 const encodedCode = ussdCode.replace(/#/g, '%23').replace(/\*/g, '%2A'); const dialUrl = `tel:${encodedCode}`; try { const supported = await Linking.canOpenURL(dialUrl); if (supported) { await Linking.openURL(dialUrl); } } catch (error) { console.error('跳转拨号器失败', error); } } // 调用示例 openUssdDialer('#144#'); openUssdDialer('#1*1*4#');
方案2:Android原生模块兼容(针对部分非洲地区定制ROM系统拨号器不识别编码后链接的场景)
- 在Android原生层创建调用拨号器的模块,直接传入编码后的USSD码:
// 原生模块方法示例 @ReactMethod public void openUssd(String ussdCode) { String encoded = ussdCode.replace("#", "%23").replace("*", "%2A"); Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + encoded)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getReactApplicationContext().startActivity(intent); }
注意事项
- 仅跳转拨号器无需申请
CALL_PHONE权限,只有需要应用内直接拨出USSD码才需要申请该权限,直接跳转系统拨号器属于系统行为,无权限风险 - 验证前请确认测试设备的系统拨号器支持USSD码填充,部分老旧定制机型可能存在兼容性问题
内容的提问来源于stack exchange,提问作者Béranger
相关产品推荐
相关产品推荐

