实现方式
Android 中拨打电话主要通过 Intent 机制实现,有两种常见方式:

- 直接拨打电话:
Intent.ACTION_CALL,会直接启动拨号盘并拨出号码,需要CALL_PHONE权限。 - 跳到拨号界面:
Intent.ACTION_DIAL,仅打开拨号盘并显示号码,由用户手动点击拨打,无需额外权限。
权限要求
直接拨打电话(ACTION_CALL)需要在 AndroidManifest.xml 中声明权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
在 Android 6.0(API 23)及以上,CALL_PHONE 属于危险权限,必须在运行时动态申请。ACTION_DIAL 不需要任何权限。
运行时权限处理(Java 示例)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CODE);
} else {
// 已授权,直接拨打电话
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(intent);
}
在 onRequestPermissionsResult 中处理用户授权结果。

代码示例
使用 ACTION_DIAL(无权限需求)
val intent = Intent(Intent.ACTION_DIAL).apply {
data = Uri.parse("tel:10086")
}
startActivity(intent)
使用 ACTION_CALL(需权限)
val intent = Intent(Intent.ACTION_CALL).apply {
data = Uri.parse("tel:10086")
}
startActivity(intent)
两种方式对比
| 特性 | ACTION_CALL |
ACTION_DIAL |
|---|---|---|
| 权限 | 需要 CALL_PHONE |
不需要 |
| 行为 | 直接拨出号码 | 显示拨号盘,用户确认后拨打 |
| 用户体验 | 立即拨出,用户无法修改号码 | 用户可自行修改或取消 |
| 推荐使用 | 内部应用、紧急场景 | 大多数场景,更尊重用户控制 |
注意事项
- Android 10(API 29)开始,系统限制了后台应用启动
ACTION_CALL,前台应用不受影响。 - 对于
ACTION_CALL,如果号码格式不正确或权限被拒绝,会抛出SecurityException或ActivityNotFoundException,建议捕获异常。 - 若只需要打开拨号盘但不带号码,可以直接使用
Intent.ACTION_DIAL不带数据。 - 部分定制 ROM 可能对
ACTION_CALL有额外限制,测试时需覆盖多机型。
相关问题与解答
问题1:为什么我的 ACTION_CALL 总是报错 “Permission Denied”?
解答:
通常原因是未正确声明或请求权限,请确保:
- 在
AndroidManifest.xml中添加<uses-permission android:name="android.permission.CALL_PHONE" />。 - 在 Android 6.0+ 设备上,必须 运行时动态申请权限,仅在清单声明不够。
- 检查是否在授权后才调用
startActivity,如果用户拒绝授权,应给出友好提示,而不是直接尝试拨号。
问题2:如何在不使用 CALL_PHONE 权限的情况下拨打电话?
解答:
使用 Intent.ACTION_DIAL 替代 ACTION_CALL,该 Intent 不会直接拨出电话,而是打开系统拨号界面并填入号码,由用户手动点击拨打,这样既无需权限,也完全符合用户预期,示例:
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"))
startActivity(intent)
这是实现“拨打电话”功能最安全、最推荐的方式。

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/511172.html