Flutter中如何实现点击手机号弹出通话类应用选择列表的功能?
Flutter 点击手机号弹出多通话渠道选择实现方案
核心思路
不用依赖flutter_launcher的单一通话能力,通过官方维护的url_launcher库调用各通话应用的URL Schema,配合系统自带的底部弹窗组件实现选项选择,全平台兼容。
步骤1:配置依赖与权限
- 安装
url_launcher依赖,执行命令:flutter pub add url_launcher - 安卓权限配置:在
android/app/src/main/AndroidManifest.xml的<manifest>标签(与<application>同级)下添加如下配置,避免安卓11及以上版本跳转失败:
<queries> <!-- 系统电话权限 --> <intent> <action android:name="android.intent.action.DIAL" /> <data android:scheme="tel" /> </intent> <!-- 注册WhatsApp包名 --> <package android:name="com.whatsapp" /> <!-- 注册Skype包名 --> <package android:name="com.skype.raider" /> </queries>
- iOS权限配置:在
ios/Runner/Info.plist的<dict>标签下添加白名单配置:
<key>LSApplicationQueriesSchemes</key> <array> <string>tel</string> <string>whatsapp</string> <string>skype</string> </array>
步骤2:实现点击逻辑与弹窗
直接调用系统自带的showModalBottomSheet实现选项列表,配合各应用的Schema跳转即可,示例代码如下:
import 'package:url_launcher/url_launcher.dart'; // 点击手机号时触发该方法,入参为用户选中的手机号 void _showCallOptionDialog(String rawPhone, BuildContext context) async { // 格式化手机号:清除非数字字符,可根据业务需求自行拼接国家码,比如国内号码加86前缀 final cleanedPhone = rawPhone.replaceAll(RegExp(r'[^0-9]'), ''); // 弹出底部选项列表 await showModalBottomSheet( context: context, builder: (ctx) => SafeArea( child: Wrap( children: [ // 系统电话选项 ListTile( leading: const Icon(Icons.phone), title: const Text('系统电话通话'), onTap: () async { Navigator.pop(ctx); final telUri = Uri(scheme: 'tel', path: cleanedPhone); if (await canLaunchUrl(telUri)) { await launchUrl(telUri); } }, ), // WhatsApp通话选项 ListTile( leading: const Icon(Icons.call), // 可替换为WhatsApp专属图标 title: const Text('WhatsApp通话'), onTap: () async { Navigator.pop(ctx); // 注意:WhatsApp跳转需要带完整国家码,比如国内号码需要拼接前缀86 final whatsappUri = Uri.parse('whatsapp://call?phone=+$cleanedPhone'); if (await canLaunchUrl(whatsappUri)) { await launchUrl(whatsappUri); } else { // 可自行添加未安装应用的提示逻辑,比如Toast提示 } }, ), // Skype通话选项 ListTile( leading: const Icon(Icons.video_call), // 可替换为Skype专属图标 title: const Text('Skype通话'), onTap: () async { Navigator.pop(ctx); final skypeUri = Uri.parse('skype:$cleanedPhone?call'); // 如果需要发起视频通话,将uri替换为 skype:$cleanedPhone?call&video=true 即可 if (await canLaunchUrl(skypeUri)) { await launchUrl(skypeUri); } else { // 可自行添加未安装应用的提示逻辑 } }, ) ], ), ), ); }
注意事项
- 每次跳转前调用
canLaunchUrl做可用性校验,避免用户未安装对应应用时触发崩溃 - WhatsApp的手机号必须带国际区号,否则无法正常识别跳转
- 可根据业务需求扩展其他通话渠道,只要拿到对应应用的公开URL Schema即可适配
内容的提问来源于stack exchange,提问作者Darshan Prajapati
相关产品推荐
相关产品推荐

