如何在Fragment中获取Activity的权限申请结果?
解决Fragment中权限申请结果的回调问题
你的问题本质是权限申请结果无法从Activity传递到Fragment,导致用户授权后Fragment没法触发显示地图的逻辑。下面给你三种实用的解决方案,按推荐程度排序:
方案1:让Fragment直接处理权限请求(最推荐)
其实Fragment本身就自带权限申请和结果回调的能力,完全不需要通过Activity中转。这样逻辑更内聚,也避免了跨组件通信的麻烦。
修改你的MapFragment代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 权限已授予,显示地图 permission_button.visibility = View.GONE val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(callback) } else { // 权限未授予,自己申请 requestPermissions( arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), Constants.LOCATION_PREMMISION_CODE ) } } // 重写Fragment的权限结果回调 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == Constants.LOCATION_PREMMISION_CODE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户授予权限,显示地图 permission_button.visibility = View.GONE val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(callback) } else { // 用户拒绝权限,隐藏地图 permission_button.visibility = View.VISIBLE // 可以在这里提示用户需要权限才能使用地图 } } }
这样Fragment完全自主处理权限逻辑,不用依赖Activity的uiCommunicationListener,代码更清晰。
方案2:扩展接口回调,让Activity通知Fragment结果
如果一定要保留Activity的权限检查逻辑,可以扩展你的uiCommunicationListener接口,增加一个权限结果回调方法,让Activity在收到权限结果后通知Fragment。
第一步:修改接口定义
interface UiCommunicationListener { fun isLocationPermissionGranted(): Boolean // 新增权限结果回调方法 fun onLocationPermissionResult(granted: Boolean) }
第二步:修改MainActivity的权限处理
override fun isLocationPermissionGranted(): Boolean { if (ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), Constants.LOCATION_PREMMISION_CODE ) return false } else { return true } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == Constants.LOCATION_PREMMISION_CODE) { val granted = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED // 通知所有实现了接口的Fragment,或者指定你的MapFragment supportFragmentManager.fragments.forEach { fragment -> if (fragment is UiCommunicationListener) { fragment.onLocationPermissionResult(granted) } } } }
第三步:在MapFragment中实现回调
class MapFragment : Fragment(), UiCommunicationListener { // ... 其他代码 ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) checkLocationPermission() } private fun checkLocationPermission() { if (uiCommunicationListener.isLocationPermissionGranted()) { showMap() } else { hideMap() } } private fun showMap() { permission_button.visibility = View.GONE val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(callback) } private fun hideMap() { permission_button.visibility = View.VISIBLE // 隐藏地图的逻辑 } override fun onLocationPermissionResult(granted: Boolean) { if (granted) { showMap() } else { hideMap() } } }
方案3:用ViewModel共享权限状态(适合复杂场景)
如果你的项目用了Jetpack组件,可以用ViewModel来共享权限状态,Activity更新状态,Fragment观察状态变化。
第一步:创建PermissionViewModel
class PermissionViewModel : ViewModel() { val locationPermissionGranted = MutableLiveData<Boolean>() }
第二步:在MainActivity中更新状态
class MainActivity : AppCompatActivity(), UiCommunicationListener { private val permissionViewModel: PermissionViewModel by viewModels() override fun isLocationPermissionGranted(): Boolean { val granted = ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED permissionViewModel.locationPermissionGranted.value = granted if (!granted) { ActivityCompat.requestPermissions( this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), Constants.LOCATION_PREMMISION_CODE ) } return granted } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == Constants.LOCATION_PREMMISION_CODE) { permissionViewModel.locationPermissionGranted.value = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED } } }
第三步:在MapFragment中观察状态
class MapFragment : Fragment() { private val permissionViewModel: PermissionViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 观察权限状态变化 permissionViewModel.locationPermissionGranted.observe(viewLifecycleOwner) { granted -> if (granted) { showMap() } else { hideMap() } } // 初始检查权限 (activity as? UiCommunicationListener)?.isLocationPermissionGranted() } private fun showMap() { permission_button.visibility = View.GONE val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(callback) } private fun hideMap() { permission_button.visibility = View.VISIBLE // 隐藏地图的逻辑 } }
个人最推荐方案1,因为它让Fragment的逻辑更独立,减少了和Activity的耦合。如果你的项目有统一的权限管理需求,方案2或3会更合适。
内容的提问来源于stack exchange,提问作者ScrapeW
相关产品推荐
相关产品推荐

