Android

Understanding Runtime permission and RxPermission of RxJava in Android part -3

As We have the basic understanding of RxJava features and function from the last post of basic of RxJava and RxJava2 Part-1 and basic of RxJava and RxBinding part-2. Rx is getting popular in Android application development because it gives the best result of reactive nature. In this series, we will learn some of new Rx feature is called RxPermission.

Earlier we have practiced that the user can be seen the permission detail at while installing the app. But in marshmallow device version 6.0 it has changed. Now application will not be granted the permission while installing the application. It will ask users at runtime. Why is this required?

In the previous below the marshmallow versions like the lollipop and other lower version devices, User was felt like obvious to see the permission details while installing that, They might be thinking that why can I shared my confidential information without asking that permission. The application should be asked me, hey if you want to access those then please grant me permission to access. For example, if any other app wants to get access the phone contacts then user feel obvious to give access those. That why it comes runtime permission. If the other application wants to access phone contacts of users then its all depend on the user if they granted the permission or not. If the user has not granted then other application will not be allowed to access that information.

One common question of every developer that how Android take care our old application launch on marshmallow device. So I would say do not panic be relaxed android take care that issue very smartly. If your application has built on targeted SDK version is less than 23 then it should not be crashed on Android M. It will work fine without any issue. Runtime permission will only ask users if you build the app on target SDK version 23 or higher.

This really sounds good for the users to feel confident that my phone is secure if I used to install any other application without any issue. Android take care security point of view at the top priority. Awesome:)

Okay, Let’s see what are those permissions are granted while installing the application. These permissions called protection-level permission. It will not ask the user at runtime.

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT

Great. This permission is required to add in Android manifest file then it works fine without any crash. Now let’s check what is required to check the permission of my target SDK version and compile SDK version is 23 or higher.

A developer needs to follow three basic methods.
1. checkSelfPermission(Permission) – to check the permission is already granted or not.
2. requestPermissions(String [] permissions, int requestCode) – if not then request for permission
3. onRequestPermissionsResult(int premsRequestCode, String [] permissions, int [] grantResults) – to check the result whether permission is granted or not.

Let’s see one example I am building an app which targets SDK version is 23 or higher. I want location access in one of my application. First of all, you need to know what are permission is required for access the Location. Okay, How do I make sure? Let’s check in framework level what Gooogle has defined for location access?
When I look this file DefaultPermissionGrantPolicy.java in framework module.
I found this permission is required to access the location.

 private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>();
    static {
       LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
       LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }

So basically these two permission is required to access Location. Ok, Let’s check while clicking on a button I want to access the location.

   @OnClick(R.id.RuntimeButton)
    public void RunTimeClick(){

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                //Location Permission already granted or not
                tryToGetLocationValue();
            } else {
                //Request Location Permission
                askLocationPermission();
            }
        }
        else {
           // not required any runtime permission for below M
            tryToGetLocationValue();
        }
    }

Here we are checking the build SDK version is marshmallow then request for permission else not required permission.

public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    private void askLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission. This info convince to users to allow
                // Show alert message to users to need location access allpw location permission
                    showAlert();
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION );
            }
        }
    }
   private void showAlert(){
        new AlertDialog.Builder(this)
                .setTitle("Location Permission Needed")
                .setMessage("This app needs the Location permission, please accept to use location functionality")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //Prompt the user once explanation has been shown to ask for permission again
                        ActivityCompat.requestPermissions(RunTimePermissionTestActivity.this,
                                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                MY_PERMISSIONS_REQUEST_LOCATION );
                    }
                })
                .create()
                .show();

    }

To access the runtime permission it is mandatory that permission also registered in AndroidManifest.xml file.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">

Once the user will be allowed to granting this permission it will trigger the result in onRequestPermissionResult ().

  @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission is granted
                    // location-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                         Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                         tryToGetLocationValue();
                    }
                } else {
                    // permission denied
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }
        }
    }

So this is the basic Runtime permission in Android application development. But now the time is the Reactive, So we should be thinking about the reactive that removed all the boilerplate code. RxPermissions is the library allows the usage of RxJava with the new Android M permission model.

To access the reactive permission very first thing we need to add the relevant dependency in android gradle file.

 compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'

for RxJava2 it has modified

compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'

It has removed all the boilerplate code and make our life pretty easy and simple. It is not required to check the permission result that particular permission is granted or not. Every thing is handling at single place.

@OnClick(R.id.RuntimeButton)
    public void RunTimeClick() {
        RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance
        // Must be done during an initialization phase like onCreate
        rxPermissions
                .requestEach(Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION)
                .subscribe(permission -> { // will emit 2 Permission objects
                    if (permission.granted) {
                        // `permission.name` is granted !
                        tryToGetLocationValue();

                    } else if (permission.shouldShowRequestPermissionRationale) {
                        // Denied permission without ask never again
                        Toast.makeText(RunTimePermissionTestActivity.this, "Denied permission without ask never again",
                                Toast.LENGTH_SHORT).show();
                    } else {
                        // Denied permission with ask never again
                        // Need to go to the settings
                        Toast.makeText(RunTimePermissionTestActivity.this, "Permission denied, can't enable the Location",
                                Toast.LENGTH_SHORT).show();
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        Log.e("TAG", "onError,"+throwable.getMessage());
                    }
                });
    }

RxPermission is awesome for runtime permission prompt. In my next tutorial of this Rx series, we will learn new reactive feature and functions. If you wondering Kotlin for android then I would be recommended to check all this post of Kotlin Category.

Please do subscribe your email to get every newsletter from this blog and if you feel that this post helps you then do not forget to share and comment below.

I used my old reference to this post which is written here.

Happy coding 🙂

0 0 votes
Article Rating

Recent Posts

Hide your production API key or any sensitive data in Android

Hi everyone, In this article, we are going to learn how to hide the production… Read More

2 years ago

How to handle the localisation or multi language support in android with examples?

Hello everyone, Today in this article, we are going to learn about localisation to support… Read More

2 years ago

How to convert any callback to Coroutines and use them in Kotlin Android?

Hello everyone, In this article, we are going to learn something to handle the callback… Read More

2 years ago

Request Permission Launcher with Kotlin in Android

In this article, we are learning about the run time permissions for request permission launchers.… Read More

2 years ago

Implement the SMS User Consent API and SMS Retriever API in Android

Hello everyone. In my last tutorial, we learned about the Jetpack Compose introduction and about applying the… Read More

3 years ago

Jetpack Compose Coroutine flow with LiveData/ViewModel in Android

Hello everyone, In this article, we are going to learn about the Jetpack Compose with… Read More

3 years ago