Skip to content

Commit

Permalink
permission handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
CraZyLegenD committed Jun 17, 2019
1 parent 7dfc4ef commit 4d5a096
Show file tree
Hide file tree
Showing 11 changed files with 525 additions and 7 deletions.
12 changes: 7 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0-alpha05'
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
implementation 'androidx.core:core-ktx:1.2.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
testImplementation 'junit:junit:4.13-beta-3'
androidTestImplementation 'androidx.test:runner:1.2.0-beta01'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-beta01'
implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha05'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha06'
implementation project(path: ':kotlinextensions', transitive: false)

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
implementation 'androidx.biometric:biometric:1.0.0-alpha04'
implementation 'androidx.preference:preference:1.1.0-beta01'

}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
package com.crazylegend.setofusefulkotlinextensions


import android.Manifest
import android.os.Bundle
import com.crazylegend.kotlinextensions.codestyle.BaseAbstractActivity
import com.crazylegend.kotlinextensions.context.shortToast
import com.crazylegend.kotlinextensions.context.showConfirmationDialog
import com.crazylegend.kotlinextensions.coroutines.mainCoroutine
import com.crazylegend.kotlinextensions.exhaustive
import com.crazylegend.kotlinextensions.permissionHandlers.PermissionResult
import com.crazylegend.kotlinextensions.permissionHandlers.coroutines.PermissionCouroutineManager


class MainAbstractActivity : BaseAbstractActivity() {



val REQUEST_ID = 123


override fun getLayoutResourceId(): Int = R.layout.activity_main


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)




}


Expand Down
2 changes: 1 addition & 1 deletion kotlinextensions/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ dependencies {
implementation 'androidx.biometric:biometric:1.0.0-alpha04'
implementation 'androidx.exifinterface:exifinterface:1.1.0-alpha01'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha01'
implementation 'androidx.preference:preference:1.1.0-alpha05'
implementation 'androidx.preference:preference:1.1.0-beta01'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,5 @@ class MainApplication : Application() {
//setting the locale
//LocaleHelper.setLocale(context, "en")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.crazylegend.kotlinextensions.permissionHandlers

import android.content.pm.PackageManager
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment

/**
* Created by hristijan on 6/17/19 to long live and prosper !
*/

abstract class BasePermissionManager : Fragment() {

private val rationalRequest = mutableMapOf<Int, Boolean>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (grantResults.isNotEmpty() &&
grantResults.all { it == PackageManager.PERMISSION_GRANTED }
) {
onPermissionResult(PermissionResult.PermissionGranted(requestCode))
} else if (permissions.any { shouldShowRequestPermissionRationale(it) }) {
onPermissionResult(
PermissionResult.PermissionDenied(requestCode,
permissions.filterIndexed { index, _ ->
grantResults[index] == PackageManager.PERMISSION_DENIED
}
)
)
} else {
onPermissionResult(
PermissionResult.PermissionDeniedPermanently(requestCode,
permissions.filterIndexed { index, _ ->
grantResults[index] == PackageManager.PERMISSION_DENIED
}
))
}
}

protected fun requestPermissions(requestId: Int, vararg permissions: String) {

rationalRequest[requestId]?.let {
requestPermissions(permissions, requestId)
rationalRequest.remove(requestId)
return
}

val notGranted = permissions.filter {
ContextCompat.checkSelfPermission(
requireActivity(),
it
) != PackageManager.PERMISSION_GRANTED
}.toTypedArray()

when {
notGranted.isEmpty() ->
onPermissionResult(PermissionResult.PermissionGranted(requestId))
notGranted.any { shouldShowRequestPermissionRationale(it) } -> {
rationalRequest[requestId] = true
onPermissionResult(PermissionResult.ShowRationale(requestId))
}
else -> {
requestPermissions(notGranted, requestId)
}
}
}

protected abstract fun onPermissionResult(permissionResult: PermissionResult)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.crazylegend.kotlinextensions.permissionHandlers

import android.arch.lifecycle.LiveData
import android.content.Context
import android.support.annotation.MainThread
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment


/**
* Interface definition for a callback to get [LiveData] of [PermissionResult]
*
interface PermissionObserver {
fun setupObserver(permissionResultLiveData: LiveData<PermissionResult>)
}
* Implement this interface to get [LiveData] for observing permission request result.
*/

/**
override fun setupObserver(permissionResultLiveData: LiveData<PermissionResult>) {
permissionResultLiveData.observe(this, Observer<PermissionResult> {
when (it) {
is PermissionResult.PermissionGranted -> {
if (it.requestId == REQUEST_ID) {
//Add your logic here after user grants permission(s)
}
}
is PermissionResult.PermissionDenied -> {
if (it.requestId == REQUEST_ID) {
//Add your logic to handle permission denial
}
}
is PermissionResult.PermissionDeniedPermanently -> {
if (it.requestId == REQUEST_ID) {
//Add your logic here if user denied permission(s) permanently.
//Ideally you should ask user to manually go to settings and enable permission(s)
}
}
is PermissionResult.ShowRational -> {
if (it.requestId == REQUEST_ID) {
//If user denied permission frequently then she/he is not clear about why you are asking this permission.
//This is your chance to explain them why you need permission.
}
}
}
})
}
*
*/



/**
* Created by hristijan on 6/17/19 to long live and prosper !
*/

class PermissionManager : BasePermissionManager() {

private val permissionResultLiveEvent: SingleLiveEvent<PermissionResult> by lazy {
SingleLiveEvent<PermissionResult>()
}

override fun onPermissionResult(permissionResult: PermissionResult) {
permissionResultLiveEvent.postValue(permissionResult)
}

override fun onAttach(context: Context) {
super.onAttach(context)
if (parentFragment != null) {
(parentFragment as PermissionObserver).setupObserver(permissionResultLiveEvent)
} else {
(context as PermissionObserver).setupObserver(permissionResultLiveEvent)
}
}


companion object {

private const val TAG = "PermissionManager"

/**
* A static factory method to request permission from activity.
* Your activity must implement [PermissionObserver]
*
* @param activity an instance of [AppCompatActivity] which is also [PermissionObserver]
* @param requestId Request ID for permission request
* @param permissions Permission(s) to request
*
* @throws [IllegalArgumentException] if your activity doesn't implement [PermissionObserver]
*/
@JvmStatic
@MainThread
fun requestPermissions(
activity: AppCompatActivity,
requestId: Int,
vararg permissions: String
) {
_requestPermissions(
activity,
requestId,
*permissions
)
}

/**
* A static factory method to request permission from fragment.
* Your fragment must implement [PermissionObserver]
*
* @param fragment an instance of [Fragment] which is also [PermissionObserver]
* @param requestId Request ID for permission request
* @param permissions Permission(s) to request
*
* @throws [IllegalArgumentException] if your fragment doesn't implement [PermissionObserver]
*/
@JvmStatic
@MainThread
fun requestPermissions(
fragment: Fragment,
requestId: Int,
vararg permissions: String
) {
_requestPermissions(
fragment,
requestId,
*permissions
)
}

private fun _requestPermissions(
activityOrFragment: Any,
requestId: Int,
vararg permissions: String
) {

val fragmentManager = if (activityOrFragment is AppCompatActivity) {
activityOrFragment.supportFragmentManager
} else {
(activityOrFragment as Fragment).childFragmentManager
}

if (fragmentManager.findFragmentByTag(TAG) != null) {
(fragmentManager.findFragmentByTag(TAG) as PermissionManager).requestPermissions(
requestId,
*permissions
)
} else {
if (activityOrFragment !is PermissionObserver) {
throw IllegalArgumentException(
"Activity/Fragment must implement PermissionObserver"
)
} else {
val permissionManager = PermissionManager()
fragmentManager.beginTransaction().add(
permissionManager,
TAG
).commitNow()
permissionManager.requestPermissions(requestId, *permissions)
}
}
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.crazylegend.kotlinextensions.permissionHandlers

import android.arch.lifecycle.LiveData


/**
* Created by hristijan on 6/17/19 to long live and prosper !
*/

/**
* Interface definition for a callback to get [LiveData] of [PermissionResult]
*
* Implement this interface to get [LiveData] for observing permission request result.
*/
interface PermissionObserver {
fun setupObserver(permissionResultLiveData: LiveData<PermissionResult>)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.crazylegend.kotlinextensions.permissionHandlers


/**
* Created by hristijan on 6/17/19 to long live and prosper !
*/

sealed class PermissionResult {
class PermissionGranted(val requestId: Int) : PermissionResult()
class PermissionDenied(
val requestId: Int,
val deniedPermissions: List<String>
) : PermissionResult()

class ShowRationale(val requestId: Int) : PermissionResult()
class PermissionDeniedPermanently(
val requestId: Int,
val permanentlyDeniedPermissions: List<String>
) : PermissionResult()
}
Loading

0 comments on commit 4d5a096

Please sign in to comment.