1、默认权限申请
- 申请:
requestPermissions(arrayOf(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE), 45)
- 回调:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {}
2、 之前用的优秀三方 RxPermissions
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// I can control the camera now
} else {
// Oups permission denied
}
});
由于上面库用的rxJava, 而项目目前使用的协程那一套,没接入rxJava, 所以参照上面自己封装了一下
3、flow 实现的 FlowPermissions
- FlowPermissions
class FlowPermissions {
val TAG: String = FlowPermissions::class.java.simpleName
@VisibleForTesting
var mFlowPermissionsFragment: Lazy<FlowPermissionsFragment>? = null
constructor(activity: FragmentActivity) {
mFlowPermissionsFragment = getLazySingleton(activity.supportFragmentManager)
}
constructor(fragment: Fragment) {
mFlowPermissionsFragment = getLazySingleton(fragment.childFragmentManager)
}
private fun getLazySingleton(fragmentManager: FragmentManager): Lazy<FlowPermissionsFragment> {
return object : Lazy<FlowPermissionsFragment> {
private var flowPermissionsFragment: FlowPermissionsFragment? = null
override val value: FlowPermissionsFragment
get() = getRxPermissionsFragment(fragmentManager)
override fun isInitialized(): Boolean {
return flowPermissionsFragment != null
}
}
}
private fun getRxPermissionsFragment(fragmentManager: FragmentManager): FlowPermissionsFragment {
var rxPermissionsFragment = flowPermissionsFragment(fragmentManager)
val isNewInstance = rxPermissionsFragment == null
if (isNewInstance) {
rxPermissionsFragment = FlowPermissionsFragment()
fragmentManager
.beginTransaction()
.add(rxPermissionsFragment, TAG)
.commitNow()
}
return rxPermissionsFragment!!
}
private fun flowPermissionsFragment(fragmentManager: FragmentManager): FlowPermissionsFragment? {
return if (fragmentManager.findFragmentByTag(TAG) != null) {
fragmentManager.findFragmentByTag(TAG) as FlowPermissionsFragment
} else {
null
}
}
fun request(vararg permissions: String): FlowPermissions {
mFlowPermissionsFragment?.value?.requestPermissions2(*permissions)
return this
}
fun getFlows(): Flow<Boolean> {
return mFlowPermissionsFragment?.value?.onRequestPermissionsResults!!
}
}
- FlowPermissionsFragment
class FlowPermissionsFragment : Fragment() {
private val _effect: Channel<Boolean> = Channel()
var onRequestPermissionsResults: Flow<Boolean> = _effect.receiveAsFlow()
@TargetApi(Build.VERSION_CODES.M)
fun requestPermissions2(vararg permissions: String) {
val permissionList = ArrayList<String>()
permissions.forEach {
val b = ContextCompat.checkSelfPermission(this@FlowPermissionsFragment.requireContext(), it) != PackageManager.PERMISSION_GRANTED
if (b) {
permissionList.add(it)
}
}
if (permissionList.isNotEmpty()) {
this@FlowPermissionsFragment.requestPermissions(permissionList.toTypedArray(), PERMISSIONS_REQUEST_CODE)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode != PERMISSIONS_REQUEST_CODE) return
val shouldShowRequestPermissionRationale = BooleanArray(permissions.size)
for (i in permissions.indices) {
shouldShowRequestPermissionRationale[i] = shouldShowRequestPermissionRationale(
permissions[i]
)
}
onRequestPermissions(
permissions,
grantResults,
shouldShowRequestPermissionRationale
)
}
private fun onRequestPermissions(
permissions: Array<String>,
grantResults: IntArray,
shouldShowRequestPermissionRationale: BooleanArray
) {
var granted = true
grantResults.forEach {
if (it != PackageManager.PERMISSION_GRANTED) {
granted = false
}
}
lifecycleScope.launch {
_effect.send(granted)
}
}
@TargetApi(Build.VERSION_CODES.M)
fun isGranted(permission: String?): Boolean {
val fragmentActivity = activity
?: throw IllegalStateException("This fragment must be attached to an activity.")
return fragmentActivity.checkSelfPermission(permission!!) == PackageManager.PERMISSION_GRANTED
}
@TargetApi(Build.VERSION_CODES.M)
fun isRevoked(permission: String?): Boolean {
val fragmentActivity = activity
?: throw IllegalStateException("This fragment must be attached to an activity.")
return fragmentActivity.packageManager.isPermissionRevokedByPolicy(
permission!!,
requireActivity().packageName
)
}
companion object {
private const val PERMISSIONS_REQUEST_CODE = 42
}
}
- 使用
lifecycleScope.launch {
FlowPermissions(this@MainActivity)
.request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION)
.getFlows()
.collectLatest { granted ->
Log.d("granted", "$granted")
}
}
这边只是做了简单的判断, 就是申请的权限,全部都允许了,才会granted==true。如果想要做定制修改。只需要 修改 FlowPermissionsFragment类下的 onRequestPermissions方法中的 _effect.send(granted),自己定义实体类。就可以在 collectLatest中获取。
4、 官方给了新的权限申请方式,也是特别好用的
- 声明回调
private val activityResultLauncher =
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
// Handle Permission granted/rejected
permissions.entries.forEach {
val permissionName = it.key
val isGranted = it.value
if (isGranted) {
// Permission is granted
} else {
// Permission is denied
}
}
}
- 申请权限
activityResultLauncher.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE
)
)
4.1、虽然不是链式,但是也是相当的简单明了。 简单封装一下:
- 封装
class PermissionTool private constructor() {
companion object {
private lateinit var requestMultiplePermissions: ActivityResultLauncher<Array<String>>
private var tool: PermissionTool? = null
get() {
if (field == null) field = PermissionTool()
return field
}
@Synchronized
fun getInstance(activity: ComponentActivity): PermissionTool {
requestMultiplePermissions = activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { map ->
mCallback.invoke(!map.containsValue(false))
}
return tool!!
}
var mCallback: (success: Boolean) -> Unit = {}
}
fun requestMultiplePermissions(activity: ComponentActivity, permission: Array<String>, callback: (success: Boolean) -> Unit) {
mCallback = callback
if (permission.all { ActivityCompat.checkSelfPermission(activity.baseContext, it) == PackageManager.PERMISSION_GRANTED }) {
callback.invoke(true)
} else {
requestMultiplePermissions.launch(permission)
}
}
}
- 使用,一定要在start方法之前调用getInstance(),
//声明
private lateinit var permissionTool: PermissionTool
//oncreate方法中调用:
permissionTool = PermissionTool.getInstance(this@MainActivity)
// 调用
permissionTool.requestMultiplePermissions(
this@MainActivity,
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) { isGranted ->
}
4.2、扩展式封装,不像上面那样麻烦
- 新建扩展类
fun FragmentActivity.requestPermission(permissions: Array<String>, callBack: (granted: Boolean) -> Unit) {
lateinit var requestMultiplePermissions: ActivityResultLauncher<Array<String>>
requestMultiplePermissions = this.activityResultRegistry.register("registry", ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
callBack(!permissions.containsValue(false))
requestMultiplePermissions.unregister()//unregister()是关键,由于不是在onCreate方法中注册的,不加上它,在使用时会发生重复监听的情况。
}
requestMultiplePermissions.launch(permissions)
}
- 使用
requestPermission(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) { isGranted ->
}