Giter Club home page Giter Club logo

assent's Introduction

Assent

Assent is designed to make Android's runtime permissions easier and take less code in your app to use.

Android CI Codacy Badge License

Table of Contents

  1. Gradle Dependency
  2. The Basics
  3. Using Results
  4. Permanently Denied
  5. Request Debouncing
  6. Rationales
  7. Coroutines

Core

Core

Add this to your module's build.gradle file:

dependencies {
  
  implementation 'com.afollestad.assent:core:3.0.2'
}

The Basics

Runtime permissions on Android are completely reliant on the UI the user is in. Permission requests go in and out of Activities and Fragments. This library provides its functionality as Kotlin extensions to Fragment Activities (e.g. AppCompatActivity) and AndroidX Fragments.

Note: you need to have permissions declared in your AndroidManifest.xml too, otherwise Android will always deny them.

class YourActivity : AppCompatActivity() {

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

    // Set to true if one or more permissions are all granted
    val permissionsGranted: Boolean = isAllGranted(WRITE_EXTERNAL_STORAGE, CAMERA)
    
    // Requests one or more permissions, sending the result to a callback
    askForPermissions(WRITE_EXTERNAL_STORAGE, CAMERA) { result ->
      // Check the result, see the Using Results section
    }
    
    // Requests one or multiple permissions and performs an action if all are granted
    runWithPermissions(WRITE_EXTERNAL_STORAGE, CAMERA) { 
      // Do something
    }
  }
}

All of the request methods above have an optional requestCode named parameter which you can use to customize the request code used when dispatching the permission request.

These methods can all be called from within an Activity or a Fragment. It works the same way in both.


Using Results

AssentResult is provided in request callbacks. It has a few useful fields and methods:

val result: AssentResult = // ...

val permissions: List<Permission> = result.permissions
val grantResults: List<GrantResult> = result.grantResults

// Takes a single permission and returns if this result contains it in its set
val containsPermission: Boolean = result.containsPermission(WRITE_EXTERNAL_STORAGE)

// You can pass multiple permissions as varargs
val permissionGranted: Boolean = result.isAllGranted(WRITE_EXTERNAL_STORAGE)

// You can pass multiple permissions as varargs
val permissionDenied: Boolean = result.isAllDenied(WRITE_EXTERNAL_STORAGE)

// Returns GRANTED, DENIED, or PERMANENTLY_DENIED
val writeStorageGrantResult: GrantResult = result[WRITE_EXTERNAL_STORAGE]

val granted: Set<Permission> = result.granted()

val denied: Set<Permission> = result.denied()

val permanentlyDenied: Set<Permission> = result.permanentlyDenied()

Permanently Denied

Assent detects when the user of your app has permanently denied a permission. Once a permission is permanently denied, the Android system will no longer show the permission dialog for that permission. At this point, the only way to get them to grant the permission is to explain why you really need the permission and then launch system app details page for your app.

val result: AssentResult = // ...

if (result[WRITE_EXTERNAL_STORAGE] == PERMANENTLY_DENIED) {
  // NOTE: You should show a dialog of some sort before doing this!
  showSystemAppDetailsPage()
}

Request Debouncing

If you were to do this...

askForPermissions(WRITE_EXTERNAL_STORAGE) { _ -> }

askForPermissions(WRITE_EXTERNAL_STORAGE) { _ -> }

...the permission would only be requested once, and both callbacks would be called at the same time.

If you were to do this...

askForPermissions(WRITE_EXTERNAL_STORAGE) { _ -> }

askForPermissions(CALL_PHONE) { _ -> }

...Assent would wait until the first permission request is done before executing the second request.


Rationales

Rationales

Add this to your module's build.gradle file:

dependencies {

      implementation 'com.afollestad.assent:rationales:3.0.2'
}

Google recommends showing rationales for permissions when it may not be obvious to the user why you need them.

Assent supports extensible rationale handlers, it comes with two out-of-the-box:

  • SnackBarRationaleHandler
  • AlertDialogRationaleHandler
// Could also use createDialogRationale(...) here, 
// or provide your own implementation of RationaleHandler. 
val rationaleHandler = createSnackBarRationale(rootView) {
  onPermission(READ_CONTACTS, "Test rationale #1, please accept!")
  onPermission(WRITE_EXTERNAL_STORAGE, "Test rationale #1, please accept!")
  onPermission(READ_SMS, "Test rationale #3, please accept!")
}

askForPermissions(
    READ_CONTACTS, WRITE_EXTERNAL_STORAGE, READ_SMS,
    rationaleHandler = rationaleHandler
) { result ->
  // Use result
}

Coroutines

Coroutines

Add this to your module's build.gradle file:

dependencies {

  implementation 'com.afollestad.assent:coroutines:3.0.2'
}

Kotlin coroutines enable Assent to work without callbacks. If you do not know the basics of coroutines, you should research them first.

First, awaitPermissionsResult(...) is the coroutines equivalent to askForPermissions(...):

// The coroutine extensions work from within any `suspend` function/lambda.
coroutineScope {
   val result: AssentResult = awaitPermissionsResult(
       READ_CONTACTS, WRITE_EXTERNAL_STORAGE, READ_SMS,
       rationaleHandler = rationaleHandler
   )
   // Use the result...
}

And second, awaitPermissionsGranted(...) is the coroutines equivalent to runWithPermissions(...):

// The coroutine extensions work from within any `suspend` function/lambda.
coroutineScope {
   awaitPermissionsGranted(
       READ_CONTACTS, WRITE_EXTERNAL_STORAGE, READ_SMS,
       rationaleHandler = rationaleHandler
   )
   // All three permissions were granted...
}

assent's People

Contributors

afollestad avatar stephanepechard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

assent's Issues

Crash when saving state with Jetpack Navigation components

Library Version:

2.2.3

Affected Device(s):

XIAOMI note 3 android 7.1.2

Describe the Bug:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.foooo.baaar, PID: 29733
    java.lang.IllegalStateException: Failure saving state: active PermissionFragment{b24a4fa} has cleared index: -1
        at androidx.fragment.app.FragmentManagerImpl.saveAllState(FragmentManager.java:2960)
        at androidx.fragment.app.Fragment.performSaveInstanceState(Fragment.java:2628)
        at androidx.fragment.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:2910)
        at androidx.fragment.app.FragmentManagerImpl.saveAllState(FragmentManager.java:2971)
        at androidx.fragment.app.FragmentController.saveAllState(FragmentController.java:134)
        at androidx.fragment.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:591)
        at androidx.appcompat.app.AppCompatActivity.onSaveInstanceState(AppCompatActivity.java:510)
        at android.app.Activity.performSaveInstanceState(Activity.java:1415)
        at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1301)
        at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:4597)
        at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3908)
        at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3971)
        at android.app.ActivityThread.-wrap25(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1541)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:6244)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)

To Reproduce:

  1. using jetpack navigation launch fragment
  2. run runWithPermissions(Permission.WRITE_EXTERNAL_STORAGE) { doSomeStuff()}
  3. press home and save state with override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // Save recycler view state outState.putParcelable("LIST_STATE_KEY", mLayoutManager?.onSaveInstanceState()) }
  4. crash

Expected Behavior:
when i press home without doing runWithPermissions(Permission.WRITE_EXTERNAL_STORAGE) { doSomeStuff()} it works fine otherwise it crashes

Error build Material Dialogs and Assent

Execution failed for task ':app:mergeDebugJavaResource'.

A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
2 files found with path 'META-INF/core.kotlin_module' from inputs:
- C:\Users\Admin.gradle\caches\transforms-2\files-2.1\124b13c45286de7ac064c6f7acf0b9a2\core-3.3.0\jars\classes.jar
- C:\Users\Admin.gradle\caches\transforms-2\files-2.1\96ae0a161a120939d19171b3ee04d738\core-3.0.0-RC4\jars\classes.jar
Adding a packagingOptions block may help, please refer to
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
for more information

Crash when running from child fragment

Library Version:

2.2.3

Affected Device(s):

Google Pixel 2 with Android Q

To Reproduce:

  1. If I call runWithPermissions from fragment which is attached to childFragmentManager an exception is thrown:
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=65616, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {XXX/XXXui.activity.main.MainActivity}: java.lang.IllegalStateException: Cannot detach Fragment attached to a different FragmentManager. Fragment PermissionFragment{9bdf753 (79540633-3812-4049-a38b-e4b0f34675f7) [assent_permission_fragment/fragment]} is already attached to a FragmentManager.
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4618)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4660)
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1929)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:209)
        at android.app.ActivityThread.main(ActivityThread.java:7021)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:486)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:872)
     Caused by: java.lang.IllegalStateException: Cannot detach Fragment attached to a different FragmentManager. Fragment PermissionFragment{9bdf753 (79540633-3812-4049-a38b-e4b0f34675f7) [assent_permission_fragment/fragment]} is already attached to a FragmentManager.
        at androidx.fragment.app.BackStackRecord.detach(BackStackRecord.java:355)
        at com.afollestad.assent.internal.PermissionFragment$detach$1.invoke(PermissionFragment.kt:38)
        at com.afollestad.assent.internal.PermissionFragment$detach$1.invoke(PermissionFragment.kt:27)
        at com.afollestad.assent.internal.ExtensionsKt.transact(Extensions.kt:85)
        at com.afollestad.assent.internal.PermissionFragment.detach$library_release(PermissionFragment.kt:37)
        at com.afollestad.assent.internal.Data$Companion.forgetFragment(Data.kt:77)
        at com.afollestad.assent.internal.PermissionFragmentKt.onPermissionsResponse(PermissionFragment.kt:101)
        at com.afollestad.assent.internal.PermissionFragment.onRequestPermissionsResult(PermissionFragment.kt:57)
        at androidx.fragment.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:750)
        at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:8110)
        at android.app.Activity.dispatchActivityResult(Activity.java:7960)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4611)

Expected Behavior:

no crash

Issue with runWithPermissions / permanently denied in 3.0 RC3

I think you have an issue with the permanently denied permissions check, I am using the runWithPermissions helper with my camera, if one denies it the first time, then clicks the camera button again, they get asked to accept. When they do, the camera never launches. Putting the debugger on the isAllGranted call of the runWithPermissions, it says camera is Permanently Denied, even though if you go and look at the app under app settings its set to allow.

Can't seem to ask for user location permission

I have followed the how to guide and I just can't get it to work. All I want is for the location permission to popup.

 val rationaleHandler = createSnackBarRationale(rootView) {
            onPermission(Permission.ACCESS_COARSE_LOCATION, "Test rationale #1, please accept!")
            onPermission(Permission.ACCESS_FINE_LOCATION, "Test rationale #2, please accept!")

        }


                val result = awaitPermissionsResult(Permission.ACCESS_FINE_LOCATION,Permission.ACCESS_FINE_LOCATION
                    rationaleHandler = rationaleHandler
                )
                statusText.text = result.toString()
            }
            .launchIn(lifecycleScope)

That code has errors and does not work in the latest version of kotlin.

Crash when requesting permission and rotating device

java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=196688, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {....application.MainActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4588)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4630)
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:6990)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
     Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at androidx.fragment.app.FragmentManagerImpl.checkStateLoss(FragmentManagerImpl.java:1536)
        at androidx.fragment.app.FragmentManagerImpl.enqueueAction(FragmentManagerImpl.java:1558)
        at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:317)
        at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:282)
        at com.afollestad.assent.internal.ExtensionsKt.transact(Extensions.kt:85)
        at com.afollestad.assent.internal.PermissionFragment.detach$com_afollestad_assent(PermissionFragment.kt:49)
        at com.afollestad.assent.internal.Assent$Companion.forgetFragment(Assent.kt:84)
        at com.afollestad.assent.internal.PermissionFragmentKt.onPermissionsResponse(PermissionFragment.kt:116)
        at com.afollestad.assent.internal.PermissionFragment.onRequestPermissionsResult(PermissionFragment.kt:68)
        at androidx.fragment.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:769)
        at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7940)
        at android.app.Activity.dispatchActivityResult(Activity.java:7762)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4581)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4630) 
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:6990) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445

Library Version:

2.3.1

Affected Device(s):

Note 9 with API 28

Describe the Bug:
Permission dialog crashes after rotation

To Reproduce:

  1. Open a fragment that requires a permission with runWithPermissions
  2. Wait for the permissions alert
  3. Rotate the device
  4. Press Allow or deny
    RESULT: Crash

Expected Behavior:

No Crash

Activity instance will become null when switching between Activities

Hi, it looks like there's a bug in the setup:

@Override
protected void onStop() {
        // Cleans up references of the Activity to avoid memory leaks
        Assent.setActivity(null);
        super.onStop();
}

For example, I am in Activity A, and when I start Activity B, the last onStop() call in A will clear the Activity instance held in Assent

A: onCreate()
A: onStart()
B: onCreate()
B: onStart()
A: onStop()

Permission Enum doesn't contain all permissions.

Please consider making a Pull Request if you are capable of doing so.

May I pull a request to add more permission to Permission enum?

What module does this apply to?

Core

Description what you'd like to happen:

I need to use MODIFY_AUDIO_SETTINGS permission, but I wonder why it's not in the permission enum. So, would it be okay if I pull a request to add that along with a bunch of other permission?

Describe alternatives you've considered:

I couldn't find a workaround on this besides adding more permissions to the permission enum.

Support Android 10 permissions

What module does this apply to?
Core

Description what you'd like to happen:
Since permissions are implemented as a custom enum which maps to the Android string permissions, the enum must be updated when Android API changes add new permission strings. Android 10 adds new permissions, for example ACCESS_BACKGROUND_LOCATION.

Fatal Exception: java.lang.IllegalStateException FragmentManager is already executing transactions

Fatal Exception: java.lang.IllegalStateException
FragmentManager is already executing transactions
androidx.fragment.app.FragmentManager.ensureExecReady (FragmentManager.java:1686)
androidx.fragment.app.FragmentManager.execPendingActions (FragmentManager.java:1745)
androidx.fragment.app.FragmentManager.executePendingTransactions (FragmentManager.java:614)
com.afollestad.assent.internal.TransactKt.transact (Transact.kt:30)
com.afollestad.assent.internal.PermissionFragment.detach$core (PermissionFragment.java:68)
com.afollestad.assent.internal.Assent$Companion.forgetFragment (Assent.java:79)
com.afollestad.assent.internal.PermissionFragmentKt.handleResult (PermissionFragment.kt:107)
com.afollestad.assent.internal.PermissionFragment.onPermissionsResponse (PermissionFragment.kt:83)
com.afollestad.assent.internal.PermissionFragment.onCreate$lambda$0 (PermissionFragment.java:36)
androidx.activity.result.ActivityResultRegistry$1.onStateChanged (ActivityResultRegistry.java:149)
androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.java:360)
androidx.lifecycle.LifecycleRegistry.forwardPass (LifecycleRegistry.java:271)
androidx.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.java:313)
androidx.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.java:151)
androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.java:134)
androidx.fragment.app.Fragment.performStart (Fragment.java:3167)
androidx.fragment.app.FragmentStateManager.start (FragmentStateManager.java:588)
androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:279)
androidx.fragment.app.FragmentStore.moveToExpectedState (FragmentStore.java:113)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1424)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:2968)
androidx.fragment.app.FragmentManager.dispatchStart (FragmentManager.java:2893)
androidx.fragment.app.FragmentController.dispatchStart (FragmentController.java:274)
androidx.fragment.app.FragmentActivity.onStart (FragmentActivity.java:359)
androidx.appcompat.app.AppCompatActivity.onStart (AppCompatActivity.java:248)
android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1435)
android.app.Activity.performStart (Activity.java:8097)
android.app.ActivityThread.handleStartActivity (ActivityThread.java:3535)
android.app.servertransaction.TransactionExecutor.performLifecycleSequence (TransactionExecutor.java:221)
android.app.servertransaction.TransactionExecutor.cycleToPath (TransactionExecutor.java:201)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:173)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2108)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:223)
android.app.ActivityThread.main (ActivityThread.java:7945)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:603)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:947)

Library Version:

3.0.2

Affected Device(s):

Model: HiPad-Air
Android: 11

Describe the Bug:

Crash during usage

Crash when requesting permissions in fragment onViewCreated

Library Version:

2.2.3

Affected Device(s):

Samsung note 9

Description
When i call this in onViewCreated:

askForPermissions(Permission.CAMERA, requestCode = REQUEST_CODE_PERMISSIONS) { assentResult ->
           // ...
        }

I get this crash:

java.lang.IllegalStateException: FragmentManager is already executing transactions
        at androidx.fragment.app.FragmentManagerImpl.ensureExecReady(FragmentManagerImpl.java:1643)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1703)
        at androidx.fragment.app.FragmentManagerImpl.executePendingTransactions(FragmentManagerImpl.java:229)
        at com.afollestad.assent.internal.ExtensionsKt.transact(Extensions.kt:88)
        at com.afollestad.assent.internal.Data$Companion.ensureFragment(Data.kt:66)
        at com.afollestad.assent.AssentInFragmentKt.askForPermissions(AssentInFragment.kt:60)
        at co.redeye.dms.presentation.search.qrcode.QrCodeReaderFragment.createCameraSource(QrCodeReaderFragment.kt:62)
        at co.redeye.dms.presentation.search.qrcode.QrCodeReaderFragment.onViewCreated(QrCodeReaderFragment.kt:41)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:896)
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2078)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1852)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1808)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1709)
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManagerImpl.java:147)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:6981)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

Result callback not getting triggered

Timber.d("onCreate: Asking for permission")
askForPermissions(
    Permission.READ_EXTERNAL_STORAGE,
    Permission.READ_CONTACTS
) {
    Timber.d("onCreate: Result is $it") // THIS IS NOT GETTING TRIGGERED
}

Library Version:

implementation 'com.afollestad.assent:core:3.0.0-RC4'

Affected Device(s):

  • OnePlus6

Describe the Bug:

A clear description of what is the bug is.

To Reproduce:

  1. Create a new android project
  2. Simply askForPermissions with READ_EXTERNAL_STORAGE and READ_CONTACTS

Expected Behavior:

  • Result callback should be triggered

Actual Behavior

  • Result callback not getting triggered

`askForPermissions` isn't triggering the `AssentResult` callback on Android 11?

With 3.0.0-RC4

askForPermissions(
  listOf(
    Permission.WRITE_EXTERNAL_STORAGE ,
    Permission.READ_EXTERNAL_STORAGE ,
    Permission.READ_PHONE_STATE,//
    Permission.CAMERA,//
  )
)

When all permissions are agreed (only running in use), calling askForPermissions again does not trigger the callback with an AssentResult.

After testing Android10 or below, calling again can be called back
当所有权限都同意(仅在使用中运行)后 再次调用askForPermissions没有触发回调AssentResult
经测试Android10以下再次调用可以回调

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.