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

如何从RecyclerView Adapter中调用OnRequestPermissionResult实现拨打电话

解决方案

核心思路是通过接口回调解耦点击事件、权限申请、拨号逻辑,Adapter只负责传递点击的对应手机号,权限和拨号逻辑全部放到宿主Activity处理。

1. 给RecyclerView.Adapter定义回调接口

在你的Adapter类内部新增回调接口,同时在构造函数中接收接口实例:

class UserAdapter(
    private val userList: List<User>,
    private val onCallClickListener: (phoneNumber: String) -> Unit
) : RecyclerView.Adapter<UserAdapter.MyViewHolder>() {
    // 内部原有其他代码不变
}

2. 修改Adapter的点击事件逻辑

删掉Adapter中原来的权限申请、拨号相关代码,点击拨号按钮时仅触发回调传递当前项的手机号:

override fun onBindViewHolder(holder: MyViewholder, position: Int) {
    val currentItem = userlist[position]
    holder.txtFirstName.text = currentItem.firstName
    holder.txtLastName.text = currentItem.lastName
    holder.txtAge.text = currentItem.phonenumber.toString()

    holder.call.setOnClickListener {
        // 直接回调手机号给宿主Activity
        onCallClickListener.invoke(currentItem.phonenumber.toString())
    }
}

3. 宿主Activity实现回调,处理权限和拨号

在宿主Activity中声明一个成员变量存储待拨号的手机号,实现Adapter的回调接口,同时重写onRequestPermissionsResult处理权限结果:

class UserListActivity : AppCompatActivity() {
    // 存储待拨号的手机号
    private var pendingCallNumber: String? = null
    private val REQUEST_CALL = 1001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初始化Adapter时传入回调实现
        val adapter = UserAdapter(userList) { phoneNumber ->
            pendingCallNumber = phoneNumber
            checkPermissionAndCall()
        }
        recyclerView.adapter = adapter
    }

    private fun checkPermissionAndCall() {
        if (ContextCompat.checkSelfPermission(
                this,
                android.Manifest.permission.CALL_PHONE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.CALL_PHONE),
                REQUEST_CALL
            )
        } else {
            makeCall()
        }
    }

    private fun makeCall() {
        pendingCallNumber?.let { number ->
            val dial = "tel:$number"
            val intent = Intent(Intent.ACTION_CALL, Uri.parse(dial))
            startActivity(intent)
            // 拨号完成后置空存储的号码
            pendingCallNumber = null
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CALL) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                makeCall()
            } else {
                Toast.makeText(this, "权限被拒绝,无法拨打电话", Toast.LENGTH_SHORT).show()
                pendingCallNumber = null
            }
        }
    }
}

可选优化方案

如果不需要直接触发拨号,只是跳转系统拨号页填充号码,可以使用Intent.ACTION_DIAL,这个动作不需要申请任何权限,直接调用即可,省去权限处理逻辑:

private fun openDialPage(number: String) {
    val dial = "tel:$number"
    val intent = Intent(Intent.ACTION_DIAL, Uri.parse(dial))
    startActivity(intent)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:51:02