Skip to content

Commit

Permalink
Merge pull request #197 from AllanWang/enhancement/permissions
Browse files Browse the repository at this point in the history
Enhancement/permissions
  • Loading branch information
AllanWang authored Jun 6, 2019
2 parents f55d101 + efae24a commit b9feba2
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 33 deletions.
1 change: 0 additions & 1 deletion core/src/main/kotlin/ca/allanwang/kau/kotlin/Streams.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ package ca.allanwang.kau.kotlin
* Since we don't have access to the internals of our extended class,
* We will simply iterate and remove when the filter returns {@code false}
*/
@Synchronized
inline fun <T, C : MutableIterable<T>> C.kauRemoveIf(filter: (item: T) -> Boolean): C {
val iter = iterator()
while (iter.hasNext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import ca.allanwang.kau.kotlin.kauRemoveIf
import ca.allanwang.kau.kotlin.lazyContext
import ca.allanwang.kau.logging.KL
import ca.allanwang.kau.utils.KauException
Expand All @@ -30,26 +31,32 @@ import java.lang.ref.WeakReference
/**
* Created by Allan Wang on 2017-07-03.
*
* Permission manager that is decoupled from activities
* Keeps track of pending requests, and warns about invalid requests
* Permission manager that is decoupled from activities.
* Keeps track of pending requests, and warns about invalid requests.
*/
internal object PermissionManager {

private var requestInProgress = false
private val pendingResults: MutableList<WeakReference<PermissionResult>> by lazy { mutableListOf<WeakReference<PermissionResult>>() }
private val pendingResults = mutableListOf<WeakReference<PermissionResult>>()

/**
* Retrieve permissions requested in our manifest
*/
private val manifestPermission = lazyContext<Array<String>> {
private val manifestPermission = lazyContext<Set<String>> {
try {
it.packageManager.getPackageInfo(it.packageName, PackageManager.GET_PERMISSIONS)?.requestedPermissions
?: emptyArray()
it.packageManager.getPackageInfo(
it.packageName,
PackageManager.GET_PERMISSIONS
)?.requestedPermissions?.toSet()
?: emptySet()
} catch (e: Exception) {
emptyArray()
emptySet()
}
}

/**
* Registers a new permission request.
* It is expected that the callback will be called eventually, unless the parent activity is destroyed.
*/
operator fun invoke(
context: Context,
permissions: Array<out String>,
Expand All @@ -60,13 +67,16 @@ internal object PermissionManager {
val missingPermissions = permissions.filter { !context.hasPermission(it) }
if (missingPermissions.isEmpty()) return callback(true, null)
pendingResults.add(WeakReference(PermissionResult(permissions, callback = callback)))
if (!requestInProgress) {
requestInProgress = true
if (pendingResults.size == 1) {
requestPermissions(context, missingPermissions.toTypedArray())
} else KL.d { "Request is postponed since another one is still in progress; did you remember to override onRequestPermissionsResult?" }
} else {
KL.d { "Request is postponed since another one is still in progress; did you remember to override onRequestPermissionsResult?" }
}
}

@Synchronized
/**
* Checks that the listed permissions can be requested, and submits the request to the provided activity
*/
private fun requestPermissions(context: Context, permissions: Array<out String>) {
permissions.forEach {
if (!manifestPermission(context).contains(it)) {
Expand All @@ -82,29 +92,21 @@ internal object PermissionManager {
}

/**
* Handles permission result by allowing accepted permissions for all pending requests
* Also cleans up destroyed or completed pending requests
* Handles permission result by allowing accepted permissions for all pending requests.
* Also cleans up destroyed or completed pending requests.
*/
fun onRequestPermissionsResult(context: Context, permissions: Array<out String>, grantResults: IntArray) {
KL.i { "On permission result: pending ${pendingResults.size}" }
val count = Math.min(permissions.size, grantResults.size)
val iter = pendingResults.iterator()
while (iter.hasNext()) {
val action = iter.next().get()
if ((0 until count).any { action?.onResult(permissions[it], grantResults[it]) != false })
iter.remove()
pendingResults.kauRemoveIf {
val action = it.get()
action == null || (0 until count).any { i -> action.onResult(permissions[i], grantResults[i]) }
}
if (pendingResults.isEmpty())
requestInProgress = false
else {
val action = pendingResults.map { it.get() }.firstOrNull { it != null }
if (action == null) { //actions have been unlinked from their weak references
pendingResults.clear()
requestInProgress = false
return
}
requestPermissions(context, action.permissions.toTypedArray())
val action = pendingResults.asSequence().map { it.get() }.firstOrNull { it != null }
if (action == null) { // actions have been unlinked from their weak references
pendingResults.clear()
return
}
KL.i { "Post on permission result: pending ${pendingResults.size}" }
requestPermissions(context, action.permissions.toTypedArray())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class PermissionResult(permissions: Array<out String>, val callback: (granted: B
return true
}
permissions.remove(permission)
if (permissions.isNotEmpty()) return false
if (permissions.isNotEmpty()) {
return false
}
callback(true, null)
return true
}
Expand Down
1 change: 1 addition & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## v4.1.0
* :core: Deprecate NetworkUtils, as the underlying functions are deprecated
* :core: Permission manager no longer synchronized, as all actions should occur in the main thread
* :kpref-activity: Getter and setter now have action context, with the option to reload self

## v4.0.0
Expand Down
2 changes: 1 addition & 1 deletion sample/src/main/res/xml/kau_changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

<version title="v4.1.0" />
<item text=":core: Deprecate NetworkUtils, as the underlying functions are deprecated" />
<item text=":core: Permission manager no longer synchronized, as all actions should occur in the main thread" />
<item text=":kpref-activity: Getter and setter now have action context, with the option to reload self" />
<item text="" />
<item text="" />

<version title="v4.0.0" />
<item text="Update translations" />
Expand Down

0 comments on commit b9feba2

Please sign in to comment.