Wednesday, 18 November 2015

Runtime User Permission For Contacts

Runtime permissions
Here I am showing only for read contact permission.
Android 6.0 M, application will not be accepted any permission at installation time.
Apps may request permission to access information or use device capabilities at any time after installation. When a user needs to perform an action in an app, such as using the device camera, the app may request permission at that moment.

Users may also allow or deny the permissions of any app from Android Settings anytime after installation.
Android's permission system is one of the biggest security concern all along since those permissions are asked for at install time.

How to make your application support new Runtime Permission.
Set you android application compileSdkVersion and targetSdkVersion to 23. For that use below line
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
    }
Add a permission into AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />

Read Contact Permission:

If permission has already been granted, showContactDetails will be suddenly called. Otherwise launch a permission request dialog like below.

In order to check permission before going to read contacts -

@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.readContactBtn:
                requestContactsPermission();
                break;
        }
    }

Once user click on button readContact will be called then it will check permission granted or not.

public void requestContactsPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            before = ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.READ_CONTACTS);
            if (before) {
                showMessageOKCancel("You need to allow access to Contacts",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(RuntimePermission.this, PERMISSIONS_READ_CONTACT, REQUEST_CONTACTS);
                            }
                        });
                return;
            } else {
                Log.d("this is else block", "Block Number");
                ActivityCompat.requestPermissions(this, PERMISSIONS_READ_CONTACT, REQUEST_CONTACTS);
                return;
            }
        }
        showContactDetails();
    }

// show message dialog when user deny permission 
    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(RuntimePermission.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

Once user select ALLOW or DENY onRequestPermissionsResult will always be called to inform a result which we can check from the 3rd parameter, grantResults:

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CONTACTS:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission Granted
                    showContactDetails();
                } else {
                    // Permission Denied
                    Toast.makeText(RuntimePermission.this, "READ_CONTACTS Denied", Toast.LENGTH_SHORT).show();
                    after = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS);
                    boolean goToSettings = !(after || before);
                    if (goToSettings)
                        openApplicationInfoSetting();
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

//open application setting screen for enabling permission
    private void openApplicationInfoSetting() {
        new AlertDialog.Builder(RuntimePermission.this)
                .setMessage("Allow App access to your contact. \n\nTo enable this, click App settings Below and activate Contact under the permission menu.")
                .setPositiveButton("APP SETTINGS", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        Intent intent = new Intent();
                        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        Uri uri = Uri.parse("package:" + getPackageName());
                        intent.setData(uri);
                        startActivity(intent);
                    }
                })
                .setNegativeButton("NOT NOW", null)
                .create()
                .show();
    }

let's explain about shouldShowRequestPermissionRationale() method return value.

Step 1-When it will return true
  • If the app has requested this permission previously and the user denied the request.
Step 2-When it will return false
  • The app didn't request for this permission yet.
  • If the app has requested this permission previously and the user denied the request with Don't ask again.
  • If a device policy prohibits the app from having that permission
In the same way you can check permission for writing contacts(insert contact).

MainActivity.java

package com.demo.test.readcontactruntimepermission;

import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class RuntimePermission extends AppCompatActivity implements View.OnClickListener {
    private static String[] PERMISSIONS_READ_CONTACT = {Manifest.permission.READ_CONTACTS};
    private static final int REQUEST_CONTACTS = 11;
    boolean before, after;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_runtime_permission);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.readContactBtn:
                requestContactsPermission();
                break;
        }
    }

    public void requestContactsPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            //
            before = ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.READ_CONTACTS);
            if (before) {
                showMessageOKCancel("You need to allow access to Contacts",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(RuntimePermission.this, PERMISSIONS_READ_CONTACT, REQUEST_CONTACTS);
                            }
                        });
                return;
            } else {
                Log.d("this is else block", "Block Number");
                ActivityCompat.requestPermissions(this, PERMISSIONS_READ_CONTACT, REQUEST_CONTACTS);
                return;
            }
        }
        showContactDetails();
    }

    //open application setting screen for enabling permission
    private void openApplicationInfoSetting() {
        new AlertDialog.Builder(RuntimePermission.this)
                .setMessage("Allow App access to your contact. \n\nTo enable this, click App settings Below and activate Contact under the permission menu.")
                .setPositiveButton("APP SETTINGS", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        Intent intent = new Intent();
                        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        Uri uri = Uri.parse("package:" + getPackageName());
                        intent.setData(uri);
                        startActivity(intent);
                    }
                })
                .setNegativeButton("NOT NOW", null)
                .create()
                .show();
    }

    // show message dialog when user deny permission
    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(RuntimePermission.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

    private void showContactDetails() {
        Log.i("CONTACT",
                "Going to read contact");
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CONTACTS:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission Granted
                    showContactDetails();
                } else {
                    // Permission Denied
                    Toast.makeText(RuntimePermission.this, "READ_CONTACTS Denied", Toast.LENGTH_SHORT).show();
                    after = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS);
                    boolean goToSettings = !(after || before);
                    if (goToSettings)
                        openApplicationInfoSetting();
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

No comments:

Post a Comment