如何从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
相关产品推荐
相关产品推荐

