Create Better Apps With Android Run-time Permission Request

0
Shares
Create Better Apps With Android Run-time Permission Request
Rate this post

Android devices have become an important part of everyone’s life.

Whether to take photographs, get driving directions, or to make phone calls, each individual use smartphones in their everyday life.

And with all this functionalities, there is a big amount of information protected by set of permissions. Information including calendar appointments, current location, contacts, emails, messages, and more, which an app has to have an Android runtime permission to gain access of data.

With the release of Android 6.0 Marshmallow (API 23), they’ve introduced one of the biggest changes in the permissions model.

They’ve added runtime permissions request, which is a new permission model to replace the existing pre install time permissions.

How Android Runtime Permissions Work?

Basically, it gives your Android app the ability to control with what context you’ll ask for the Android permissions. In simple words, when a user installs your app from Google play store, it will not need to accept permissions before installing your Android app. This makes it easy to get users directly into your app. And you can simply ask for newly permissions later as you need them.

Now that you know everything about Android runtime permission request, it’s time we make a simple demo to learn about it briefly.

Let’s Get Started

Create a new project in Android Studio and add permission.

Android runtime permission request tutorial step 1

In this demo, we’ll gain the access of external storage device using READ_EXTERNAL_STORAGE

Next, we’ll check for permission in the demo.

Android runtime permission request tutorial step 2

private final int APP_PERMISSION = 10;

public boolean isPermissionRequired() {
List mListPermission = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
mListPermission.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (mListPermission.size() == 0) {
return false;
} else {
String[] arrayPermission = new String[mListPermission.size()];
ActivityCompat.requestPermissions(this,
mListPermission.toArray(arrayPermission),
APP_PERMISSION);
}
return true;
}

After that, we’ll handle the result of user action by using onRequestPermissionsResult callback

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case APP_PERMISSION: {

// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) // permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}

Next, we’ll request and handle the result of setting change performed by the user.

PhoneScreen3

 

If permission not granted by user then should explain user the need of permissions for this app and ask to change permission from setting.

A) Request to open application setting.

private final int APP_DETAIL_SETTINGS = 11;
//Intent to change permission of application
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, APP_DETAIL_SETTINGS);

B) handle setting request and check result is it granted or not.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == APP_DETAIL_SETTINGS) {
// check again for permission
isPermissionRequired();
}
}

Start Code Integration

MainActivity.java

public class MainActivity extends AppCompatActivity {
private final int APP_PERMISSION = 10;
private final int APP_DETAIL_SETTINGS = 11;
private final int APP_IMG_RC = 12;
private ImageView ivPhoto;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initControls();
}
private void initControls() {
ivPhoto = (ImageView) findViewById(R.id.ivPhoto);
}
public void onPickImageClicked(View view) {
if (isPermissionRequired())
return;
pickImageFromGallery();
}
public boolean isPermissionRequired() {
List mListPermission = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
mListPermission.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (mListPermission.size() == 0) {
return false;
} else {
String[] arrayPermission = new String[mListPermission.size()];
ActivityCompat.requestPermissions(this,
mListPermission.toArray(arrayPermission),
APP_PERMISSION);
}
return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case APP_PERMISSION: {
String msg = "";
// If request is cancelled, the result arrays are empty.
for (int i = 0, len = permissions.length; i < len; i++) {
String permission = permissions[i];
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permission)) {
msg = getString(R.string.msg_dialog_no_storage_permission);
break;
}
}
}
if (!msg.equals("")) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(false);
builder.setMessage(msg)
.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Intent to change permission of application
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, APP_DETAIL_SETTINGS);
}
});
// Create the AlertDialog object and return it
AlertDialog dialog = builder.create();
dialog.show();
} else if ((ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED))
pickImageFromGallery();
}
}
}
private void pickImageFromGallery() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, APP_IMG_RC);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == APP_DETAIL_SETTINGS) {
isPermissionRequired();
} else if (requestCode == APP_IMG_RC && resultCode == RESULT_OK
&& null != data) {
try {
Uri URI = data.getData();
String[] FILE = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(URI,
FILE, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(FILE[0]);
String mImageDecode = cursor.getString(columnIndex);
cursor.close();
ivPhoto.setImageBitmap(BitmapFactory
.decodeFile(mImageDecode));
} catch (Exception e) {
Toast.makeText(this, "Please try again", Toast.LENGTH_LONG)
.show();
}
}
}
}

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:id="@+id/activity_main"

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="com.runtimepermission.MainActivity">

<ImageView

android:id="@+id/ivPhoto"

android:layout_width="120dp"

android:layout_height="120dp"

android:layout_centerHorizontal="true"

android:layout_marginTop="20dp"

android:adjustViewBounds="true"

android:scaleType="centerCrop"

android:src="@mipmap/ic_launcher" />

<Button

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@+id/ivPhoto"

android:layout_marginTop="20dp"

android:background="@color/colorPrimary"

android:text="Pick Image From Gallery"

android:onClick="onPickImageClicked"

android:textColor="@android:color/white" />

</RelativeLayout>

String.xml

Storage permission allows an application to access your device storage. \nWithout storage permission, we will not able to get gallery images.
Ok
After you run the demo and give permission to access gallery, it will ask you to choose photo shown as below.

Android runtime permission request tutorial step 3

Once you select a photo from gallery, the output will be like below:

PhoneScreen5

Congratulations! You’ve successfully implemented Android runtime permission request in your native app.

Where to Go From Here?

First, if you still have any doubts regarding this tutorial, you can contact our Android developers for technical guidance.

And as mentioned before, that adding runtime permission could get you, new users, to download your app. And in case you’re planning to implement this in your Android app and need help, you can hire Android app developer from us.

We’re a team of 200+ developers who have worked in this industry for more than 7 years. And throughout this journey, we’ve been awarded multiple times and helped 25+ successful startups to convert their idea to reality. For more information, you should check out our Android app portfolio.

Download a free copy of Android runtime demo from Github.

 
0
Shares
 

Have an App Idea?

Get your free consultation now