Runtime Permission in Android Marshmallow Example

Android has introduced Runtime Permission system (API level 23) for better privacy protection of its users. Android Marshmallow will not grant any permission to application at installation time. Instead, Application need to request user for a permission one by one at runtime.

This sample application shows runtime permission available in Android Marshmallow. It shows how to check and request permissions at runtime, handle backwards compatibility using the support library and how to declare optional permissions for Marshmallow-devices only.

In this sample application we are going to access Camera and External Storage to capture and store Image.

Runtime permission in Android Marshmallow
Runtime Permission in Android M


Source Code

Defining Permissions

To use access Camera and External Storage we need to add following permissions:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="sushil.sonevalley.runtimepermission.MainActivity">

    <ImageView
        android:id="@+id/ivCameraPic"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:src="@mipmap/ic_launcher"
        android:layout_centerHorizontal="true"/>

    <Button
        android:id="@+id/btnCamera"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Launch Camera"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>


MainActivity.java
package sushil.sonevalley.runtimepermission;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private File myDir;
    private File filePath;
    private Button btnCamera;
    private static final int REQUEST_IMAGE_CAPTURE = 1;
    private static final int REQUEST_EXTERNAL_STORAGE_RESULT = 2;
    private static final int REQUEST_CAMERA_RESULT = 3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createAppDirectory();
        btnCamera = (Button) findViewById(R.id.btnCamera);
        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPhoto();
            }
        });
    }

    private void getPhoto() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if((ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
                if((ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
                    callCameraIntent();
                } else {
                    if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                        Toast.makeText(this, "External Storage Permission required to save image", Toast.LENGTH_LONG).show();
                    }
                    requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_EXTERNAL_STORAGE_RESULT);
                }
            } else {
                if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
                    Toast.makeText(this, "External Storage Permission required to save image", Toast.LENGTH_LONG).show();
                }
                requestPermissions(new String[]{Manifest.permission.CAMERA},REQUEST_CAMERA_RESULT);
            }
        } else {
            callCameraIntent();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_EXTERNAL_STORAGE_RESULT) {
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getPhoto();
            } else {
                Toast.makeText(this, "Permission has not been granted, can't save image", Toast.LENGTH_LONG).show();
            }
        } else if (requestCode == REQUEST_CAMERA_RESULT) {
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getPhoto();
            } else {
                Toast.makeText(this, "Permission has not been granted, can't open camera", Toast.LENGTH_LONG).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    private void createAppDirectory() {
        String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
        myDir = new File(root + "/SoneValley");
        if (!myDir.exists()) {
            myDir.mkdirs();
        }
    }

    private void callCameraIntent() {

        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault());
        Date date = new Date();
        String sDate = formatter.format(date);
        String imageName = "SONEVALLEY" + sDate + ".jpg";

        try {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            filePath = new File(myDir, imageName);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(filePath));
            startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
        } catch (ActivityNotFoundException e) {
            String errorMessage = "Whoops - your device doesn't support capturing images!";
            Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        Bitmap bitmap = null;
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            try {
                String imagePath = filePath.getAbsolutePath();
                bitmap = BitmapFactory.decodeFile(imagePath);
                ImageView mImageView = (ImageView) findViewById(R.id.ivCameraPic);
                mImageView.setImageBitmap(bitmap);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}



Screen Preview


Runtime Permission in Android Marshmallow, Home Screen
Home Screen
Runtime Permission in Android Marshmallow, Requesting Permission for Camera
Requesting Permission for Camera



Runtime Permission in Android Marshmallow, Requesting Permission for External Storage
Requesting Permission for External Storage
Runtime Permission in Android Marshmallow, Requesting Permission Denied
Resources can't be Accessed on Permission Denied



Runtime Permission in Android Marshmallow, Resourses Accessed on Permission Granted
Resources Accessed on Permission Granted

SHARE

0 comments:

Post a Comment