Android runtime permissions powered by RxJava2

Overview

RxPermissions

BuildVersion Build Status

This library allows the usage of RxJava with the new Android M permission model.

Setup

To use this library your minSdkVersion must be >= 14.

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.12'
}

Usage

Create a RxPermissions instance :

final RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity or Fragment instance

NOTE: new RxPermissions(this) the this parameter can be a FragmentActivity or a Fragment. If you are using RxPermissions inside of a fragment you should pass the fragment instance(new RxPermissions(this)) as constructor parameter rather than new RxPermissions(fragment.getActivity()) or you could face a java.lang.IllegalStateException: FragmentManager is already executing transactions.

Example : request the CAMERA permission (with Retrolambda for brevity, but not required)

// Must be done during an initialization phase like onCreate
rxPermissions
    .request(Manifest.permission.CAMERA)
    .subscribe(granted -> {
        if (granted) { // Always true pre-M
           // I can control the camera now
        } else {
           // Oups permission denied
        }
    });

If you need to trigger the permission request from a specific event, you need to setup your event as an observable inside an initialization phase.

You can use JakeWharton/RxBinding to turn your view to an observable (not included in the library).

Example :

// Must be done during an initialization phase like onCreate
RxView.clicks(findViewById(R.id.enableCamera))
    .compose(rxPermissions.ensure(Manifest.permission.CAMERA))
    .subscribe(granted -> {
        // R.id.enableCamera has been clicked
    });

If multiple permissions at the same time, the result is combined :

rxPermissions
    .request(Manifest.permission.CAMERA,
             Manifest.permission.READ_PHONE_STATE)
    .subscribe(granted -> {
        if (granted) {
           // All requested permissions are granted
        } else {
           // At least one permission is denied
        }
    });

You can also observe a detailed result with requestEach or ensureEach :

rxPermissions
    .requestEach(Manifest.permission.CAMERA,
             Manifest.permission.READ_PHONE_STATE)
    .subscribe(permission -> { // will emit 2 Permission objects
        if (permission.granted) {
           // `permission.name` is granted !
        } else if (permission.shouldShowRequestPermissionRationale) {
           // Denied permission without ask never again
        } else {
           // Denied permission with ask never again
           // Need to go to the settings
        }
    });

You can also get combined detailed result with requestEachCombined or ensureEachCombined :

rxPermissions
    .requestEachCombined(Manifest.permission.CAMERA,
             Manifest.permission.READ_PHONE_STATE)
    .subscribe(permission -> { // will emit 1 Permission object
        if (permission.granted) {
           // All permissions are granted !
        } else if (permission.shouldShowRequestPermissionRationale)
           // At least one denied permission without ask never again
        } else {
           // At least one denied permission with ask never again
           // Need to go to the settings
        }
    });

Look at the sample app for more.

Important read

As mentioned above, because your app may be restarted during the permission request, the request must be done during an initialization phase. This may be Activity.onCreate, or View.onFinishInflate, but not pausing methods like onResume, because you'll potentially create an infinite request loop, as your requesting activity is paused by the framework during the permission request.

If not, and if your app is restarted during the permission request (because of a configuration change for instance), the user's answer will never be emitted to the subscriber.

You can find more details about that here.

Status

This library is still beta, so contributions are welcome. I'm currently using it in production since months without issue.

Benefits

  • Avoid worrying about the framework version. If the sdk is pre-M, the observer will automatically receive a granted result.

  • Prevents you to split your code between the permission request and the result handling. Currently without this library you have to request the permission in one place and handle the result in Activity.onRequestPermissionsResult().

  • All what RX provides about transformation, filter, chaining...

License

Copyright (C) 2015 Thomas Bruyelle

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Crash on rotation

    Crash on rotation

    Hey there,

    First of all nice work. Sadly I have to say that your solution currently does not work with rotation changes. Simply press "Enable Camera", rotate your device and press "DENY" on the popup. This will result in the following crash:

     "09-30 23:42:06.090  31948-31948/com.tbruyelle.rxpermissions.sample E/AndroidRuntime﹕ FATAL EXCEPTION: main
        Process: com.tbruyelle.rxpermissions.sample, PID: 31948
        java.lang.RuntimeException: Failure delivering result ResultInfo{[email protected]:requestPermissions:, request=463403621, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.tbruyelle.rxpermissions.sample/com.tbruyelle.rxpermissions.sample.MainActivity}: java.lang.IllegalStateException: RxPermission.onRequestPermissionsResult invoked but didn't find the corresponding permission request.
                at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
                at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
                at android.app.ActivityThread.-wrap16(ActivityThread.java)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:148)
                at android.app.ActivityThread.main(ActivityThread.java:5417)
                at java.lang.reflect.Method.invoke(Native Method)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
         Caused by: java.lang.IllegalStateException: RxPermission.onRequestPermissionsResult invoked but didn't find the corresponding permission request.
                at com.tbruyelle.rxpermissions.RxPermissions.onRequestPermissionsResult(RxPermissions.java:123)
                at com.tbruyelle.rxpermissions.sample.MainActivity.onRequestPermissionsResult(MainActivity.java:36)
                at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
                at android.app.Activity.dispatchActivityResult(Activity.java:6432)
                at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
                at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
                at android.app.ActivityThread.-wrap16(ActivityThread.java)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:148)
                at android.app.ActivityThread.main(ActivityThread.java:5417)
                at java.lang.reflect.Method.invoke(Native Method)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    

    Do you have any ideas how to tackle this problem?

    bug help wanted 
    opened by Gi-lo 47
  • Reason behind the changes from Shadow Activity to Retained Fragment

    Reason behind the changes from Shadow Activity to Retained Fragment

    Hey guys,

    what are the reasons behind changing how the permissions are requested? Why is a retained Fragment now being used instead of a Shadow Activity?

    opened by vanniktech 22
  • Ask permission again

    Ask permission again

    Once the user denies permission, re-asking it doesn't show up the dialog to allow or deny. I need to restart the application to make it appear again.

    Is it by design? Or I'm missing something ?

    RxPermissions.getInstance(context)
        .request(Manifest.permission.ACCESS_FINE_LOCATION)
        .subscribe(..)
    
    bug 
    opened by jaydp17 22
  • java.lang.IllegalStateException: RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.

    java.lang.IllegalStateException: RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.

    One of my activities asks for camera permission on trigger (button click) After following steps, exception is thrown:

    1. user presses button and shadow activity with dialog that asks for permission is shown
    2. user goes to settings and revoke some other permission
    3. user reopens app - shadow activity with dialog is still there
    4. user allows/denies permission and app crashes with exception

    from what I saw in code: RxPermissions.request_() where mSubjects is filled is called before permission is revoked by user

    After user revoked permission app is recreated in new process and mSubjects is empty - therefore exception is thrown in RxPermissions.onRequestPermissionsResult()

    Can you please fix this or suggest a workaround?

    bug 
    opened by tarasantoshchuk 21
  • https://github.com/tbruyelle/RxPermissions/issues/46 crash fixed

    https://github.com/tbruyelle/RxPermissions/issues/46 crash fixed

    Fixed crash that happens in situation described here.

    These changes do not affect other situations when activity is recreated (display rotation, other config changes).

    I was unable to find solution, that would pass permission request results to the caller in this case. This part of issue still needs to be fixed.

    opened by tarasantoshchuk 18
  • Why not using headless fragment for catching the result?

    Why not using headless fragment for catching the result?

    Hey there,

    nice idea with this library, but why adding a new (shadow)activity to the stack all the time? You could use a headless fragment instead. This has multiple advantages:

    • No additional activities on stack
    • No additional activity in the manifest
    opened by andretietz 16
  • Question about

    Question about "Must be done during an initialization phase like onCreate"

    Why do I need to get the instance of RxPermission in a phase like onCreate? Since internally it uses the ApplicationContext isn't the activity lifecycle irrelevant?

    question 
    opened by vanniktech 15
  • java.lang.IllegalStateException: Fragment host has been destroyed

    java.lang.IllegalStateException: Fragment host has been destroyed

    monkey Crash log,how to solve it, thx!

      java.lang.IllegalStateException: Fragment host has been destroyed
            at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2211)
            at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2239)
            at android.support.v4.app.BackStackRecord.commitNow(BackStackRecord.java:648)
            at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(RxPermissions.java:71)
            at com.tbruyelle.rxpermissions2.RxPermissions.access$000(RxPermissions.java:34)
            at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:54)
            at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:47)
            at com.tbruyelle.rxpermissions2.RxPermissions.pending(RxPermissions.java:205)
            at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:194)
            at com.tbruyelle.rxpermissions2.RxPermissions.access$100(RxPermissions.java:34)
            at com.tbruyelle.rxpermissions2.RxPermissions$2.apply(RxPermissions.java:96)
            at io.reactivex.Observable.compose(Observable.java:6418)
            at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:170)
            at com.tct.toolscard.ToolsCardView.toggleFlashLight(ToolsCardView.java:152)
            at com.tct.toolscard.ToolsCardView.onClick(ToolsCardView.java:254)
            at android.view.View.performClick(View.java:6615)
            at android.view.View.performClickInternal(View.java:6592)
            at android.view.View.access$3100(View.java:786)
            at android.view.View$PerformClick.run(View.java:25951)
            at android.os.Handler.handleCallback(Handler.java:873)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:201)
            at android.app.ActivityThread.main(ActivityThread.java:6806)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
    
    opened by trycatchx 14
  • FragmentManager is already executing transactions

    FragmentManager is already executing transactions

    Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions
                                                                                         at android.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:1981)
                                                                                         at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2037)
                                                                                         at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:799)
                                                                                         at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(RxPermissions.java:54)
                                                                                         at com.tbruyelle.rxpermissions2.RxPermissions.<init>(RxPermissions.java:41)
                                                                                         at com......MessagesActivity.initViews(MessagesActivity.java:113)
    

    in this code :

    rxPermissions = new RxPermissions(this);

    I don't know exactly the reason behind this as it was working before without any issue.

    opened by alouanemed 14
  • Upload to bintray

    Upload to bintray

    Scripts and configuration to upload to bintray with a valid pom (and be able to link it with jcenter())

    it needs 2 properties, bintray.user and bintray.apikey in local.properties.

    I had to change the local name of the lib folder when importing in gradle because the script kept exporting 'lib' but I don't think it's an extreme change (it should* exist another way to do it).

    opened by javiergamarra 14
  • Return a detailed permission report rather than just a boolean

    Return a detailed permission report rather than just a boolean

    Would not it be better if the Subscriber would get a Map<String, Boolean> and from there we could see which permission was / is denied and which was / is accepted.

    enhancement 
    opened by vanniktech 12
  • Crash with new navigation library

    Crash with new navigation library

    E/FragmentManager: saveBackStack("b63fc48d-e48e-4242-bb65-16692a4ca714") must not contain retained fragments. Found retained child fragment RxPermissionsFragment{32c8fe0} (143f3c92-efcb-4ba1-ba40-11c7545ca2a9 tag=RxPermissions)

    androidx.navigation:navigation-fragment-ktx:2.4.2

    opened by SergeyMilevskiy 3
  • FragmentTransition Bug

    FragmentTransition Bug

    Fatal Exception: java.lang.IllegalStateException FragmentManager is already executing transactions androidx.fragment.app.FragmentManager.ensureExecReady (FragmentManager.java:1931)

    androidx.fragment.app.BackStackRecord.commitNow (BackStackRecord.java:305) com.tbruyelle.rxpermissions3.RxPermissions.getRxPermissionsFragment (RxPermissions.java:78) com.tbruyelle.rxpermissions3.RxPermissions.access$000 (RxPermissions.java:37) com.tbruyelle.rxpermissions3.RxPermissions$1.get (RxPermissions.java:62) com.tbruyelle.rxpermissions3.RxPermissions$1.get (RxPermissions.java:55) com.tbruyelle.rxpermissions3.RxPermissions.pending (RxPermissions.java:212) com.tbruyelle.rxpermissions3.RxPermissions.request (RxPermissions.java:201) com.tbruyelle.rxpermissions3.RxPermissions.access$100 (RxPermissions.java:37) com.tbruyelle.rxpermissions3.RxPermissions$4.apply (RxPermissions.java:156) io.reactivex.rxjava3.core.Observable.compose (Observable.java:6759) com.tbruyelle.rxpermissions3.RxPermissions.requestEachCombined (RxPermissions.java:194)

    Activity contains a viewpager with 3 fragment. During initialiazion, we call RxPermissions.request, FragmentManager may conflict transactions.

    Old version(e.g. 0.9.5) call commitAllowingStateLoss in getRxPermissionFragment method will not produce this crash.

    opened by axel8888 0
  • Memory Leak

    Memory Leak

    Screenshot_2022-04-07-16-44-23-694_tech nani www

    code: val rxPermissions = RxPermissions(this) rxPermissions.request( Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WAKE_LOCK ).subscribe(Consumer {

        })
    
    opened by leviluo 0
  • Bug: requestEach callback  do not contain each permission result

    Bug: requestEach callback do not contain each permission result

    Prerequisites

    1.with appcompat 1.3.0 and above 2.with permission list paramters in a special order like below

    READ_PHONE_STATE CAMERA ACCESS_FINE_LOCATION

    must in this order

    Issue description

    requestEach callback do not contain each permission result. because above appcompat 1.3.0 system do not callback permission result in the order that we provide by parameters, so some publishSubject may send before subscribe.

    Actual behavior

    only contain CAMERA and READ_PHONE_STATE permission

    Expected behavior

    contain ACCESS_FINE_LOCATION and CAMERA and READ_PHONE_STATE permission

    Steps To Reproduce

    config gralde
    implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.github.tbruyelle:rxpermissions:0.12'

    config androidManifest.xml with permission

    use rxpermission

    RxPermission usage code

            RxPermissions(this).requestEach(
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.CAMERA,
                Manifest.permission.ACCESS_FINE_LOCATION
            ).subscribe {
                Log.e("=====", it.toString()) 
            }
    

    Lib Version

    implementation 'com.github.tbruyelle:rxpermissions:0.12'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    

    Screenshots above appcompat 1.3.0 1

    2

    3

    with appcompat 1.1.0

    4

    5

    opened by wangkai4556 3
  • Need to Migrate JCenter to mavenCentral

    Need to Migrate JCenter to mavenCentral

    Hi Team,

    As JCenter is shutting down and we need to migrate to mavenCentral. Is there any plan to migrate RxPermission to mavenCentral. If yes, when we can expect the change so we can use RxPermission.

    Thanks.

    opened by abhi301285 5
Releases(v0.12)
Owner
Thomas Bruyelle
Thomas Bruyelle
Android library for permissions request (updated 27.11.2017)

NoPermission Simple Android library for permissions request. Consists of only one class. Why NoPermission: Not a framework. It's just one class Dialog

Alexey Bykov 105 Nov 15, 2022
Simplifying Android Permissions

Gota Libary With Android 6.0 Marshmallow, Google introduced a new permission model that allows users to better understand why an application may be re

Abdullah Alhazmy 73 Jul 24, 2022
Simplify Android M system permissions

EasyPermissions EasyPermissions is a wrapper library to simplify basic system permissions logic when targeting Android M or higher. Note: If your app

Google Samples 9.6k Nov 16, 2022
Ask Permission - Simple RunTime permission manager

Ask Permission https://kishanjvaghela.github.io/Ask-Permission/ Simple RunTime permission manager How to use Add url to your gradle file compile 'com.

Kishan Vaghela 77 Nov 18, 2022
A declarative API to handle Android runtime permissions.

PermissionsDispatcher Fully Kotlin/Java support Special permissions support 100% reflection-free PermissionsDispatcher provides a simple annotation-ba

PermissionsDispatcher 11.1k Nov 19, 2022
Android Library to help you with your runtime Permissions.

PermissionHelper Android Library to help you with your runtime Permissions. Demo Android M Watch it in action. Pre M Watch it in action. Nexus 6 (M) N

Kosh Sergani 1.2k Nov 10, 2022
Runtime Mobile Security (RMS) 📱🔥 - is a powerful web interface that helps you to manipulate Android and iOS Apps at Runtime

Runtime Mobile Security (RMS) ?? ?? by @mobilesecurity_ Runtime Mobile Security (RMS), powered by FRIDA, is a powerful web interface that helps you to

Mobile Security 2k Nov 29, 2022
A runtime mobile application analysis toolkit with a Web GUI, powered by Frida, written in Python.

___ ___ / | \ ____ __ __ ______ ____ / ~ \/ _ \| | \/ ___// __ \ \ Y ( <_> )

NCC Group Plc 1.2k Nov 23, 2022
Demo of Downloading Songs/Images through Android Download Manager using RxJava2

Downloader Demo using RxJava Overview This project is for downloading items(songs, images etc) in Android using RxJava2. There are, however 2 conditio

Anshul Jain 168 Nov 25, 2022
Android gallery & photo/video functionality simplified with RxJava2

RxGallery Android gallery & photo/video functionality simplified with RxJava2 Setup To use this library your minSdkVersion must be >= 9. Add it in you

Brian Rojas 38 Oct 11, 2022
An Android Library that provides social login for 15 platforms within by RxJava2, Kotlin and Firebase Authentication.

RxSocialLogin The license information for logo is located at the bottom of the document. These instructions are available in their respective language

WindSekirun (wind.seo) 124 Nov 21, 2022
Easier RxJava2 debugging with better stacktraces

Traceur Traceur enables easier debugging of RxJava2 exceptions, by appending the source of any asynchronous calls to the original exception. An exampl

Oisin O'Neill 493 Sep 26, 2022
Android library for permissions request (updated 27.11.2017)

NoPermission Simple Android library for permissions request. Consists of only one class. Why NoPermission: Not a framework. It's just one class Dialog

Alexey Bykov 105 Nov 15, 2022
Simplifying Android Permissions

Gota Libary With Android 6.0 Marshmallow, Google introduced a new permission model that allows users to better understand why an application may be re

Abdullah Alhazmy 73 Jul 24, 2022
Simplify Android M system permissions

EasyPermissions EasyPermissions is a wrapper library to simplify basic system permissions logic when targeting Android M or higher. Note: If your app

Google Samples 9.6k Nov 16, 2022
🔓 Kotlin version of the popular google/easypermissions wrapper library to simplify basic system permissions logic on Android M or higher.

EasyPermissions-ktx Kotlin version of the popular googlesample/easypermissions wrapper library to simplify basic system permissions logic on Android M

Madalin Valceleanu 323 Nov 23, 2022
Simplifying Android Permissions

Gota Libary With Android 6.0 Marshmallow, Google introduced a new permission model that allows users to better understand why an application may be re

Abdullah Alhazmy 73 Jul 24, 2022
Android Library for requesting Permissions with Kotlin Coroutines or AndroidX LiveData

PEKO PErmissions with KOtlin Android Permissions with Kotlin Coroutines or LiveData No more callbacks, builders, listeners or verbose code for request

Marko Devcic 130 Nov 15, 2022
Get a unique ID for Android devices without any permissions.

Java and Kotlin Android library. Uniquely identify an Android device without any permissions and API restrictions. The recommended approach using DRM API.

Eyosiyas Bereketab 9 Aug 25, 2022