You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中正确调用电话Intent?Android 6权限问题求解

解决Android 6上调用CALL_PHONE权限抛出SecurityException的问题

你遇到的问题核心在于Android 6(API 23)引入的运行时权限机制——CALL_PHONE属于危险权限,仅仅在AndroidManifest.xml里声明权限是不够的,必须在代码中主动向用户申请授权,而你之前的代码只做了权限检查,却没有触发实际的授权请求流程。

下面是完整的解决步骤:

1. 确保Manifest中已声明权限(你已经做了,这里再确认下)

在AndroidManifest.xml中添加权限声明:

<uses-permission android:name="android.permission.CALL_PHONE" />

2. 实现完整的运行时权限请求流程

你需要在代码中完成「检查权限→请求权限→处理授权结果」的完整逻辑,替换你之前的权限检查代码:

class ProfileActivity : AppCompatActivity() {
    // 自定义权限请求码,用来区分不同的权限请求
    private val REQUEST_CALL_PERMISSION = 100

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_profile)

        // 给电话图标设置点击事件
        imgPhone.setOnClickListener {
            attemptPhoneCall()
        }
    }

    private fun attemptPhoneCall() {
        val targetNumber = "1122334455"
        // 检查当前是否已获得拨打电话权限
        val hasPermission = ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.CALL_PHONE
        ) == PackageManager.PERMISSION_GRANTED

        if (hasPermission) {
            // 权限已授予,直接启动拨打电话的Intent
            val callIntent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$targetNumber"))
            startActivity(callIntent)
        } else {
            // 权限未授予,向用户发起权限请求
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.CALL_PHONE),
                REQUEST_CALL_PERMISSION
            )
        }
    }

    // 处理用户对权限请求的响应
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CALL_PERMISSION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户同意授权,再次尝试拨打电话
                attemptPhoneCall()
            } else {
                // 用户拒绝授权,提示用户需要权限才能执行操作
                Toast.makeText(this, "需要授予拨打电话权限才能完成此操作", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

为什么你之前的方案无效?

  • 你之前的setupPermissions()方法仅仅检查了权限状态并打印日志,但没有主动发起授权请求,所以系统仍然会阻止你的Intent调用
  • android:exported="true"是用来控制组件是否允许被其他应用调用的,和权限问题完全无关,这个设置对你的场景没有帮助

额外提示

如果用户拒绝权限并勾选了「不再询问」,后续的权限请求会直接被拒绝。这种情况下,你可以引导用户到应用的设置页面手动开启权限:

// 当权限被拒绝且无法再次请求时,跳转到应用设置
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivity(intent)

另外,如果你不需要直接拨打电话,只是想打开拨号界面让用户手动确认,可以使用Intent.ACTION_DIAL,这个Intent不需要任何权限:

val dialIntent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:$targetNumber"))
startActivity(dialIntent)

内容的提问来源于stack exchange,提问作者anta40

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:54:41