Working efficiently with permissions in Android M

On IO 2015, Android dev team has introduced us with the new permission system in Android Marshmallow, and how to work with then using the new support libraries.

Until Android 5.1 Lollipop, app permission are handle by the AndroidManifest through the use of the tag <uses-permission />, and on the moment of download, Google Play ask users to authorize the requested permissions. Now on Android M, you need to ask for permissions at runtime. To see more about what changes and how to work properly with permission, see this talk from IO 2015.

Particularly, i did not like how the new api handles permissions, so i decide to build a class that will manage and guide all the process behind requesting an specific set of permissions, using the Builder pattern (Similar to how fragments transactions works). In this post, i’ll show how use this class to solve the problem.


Basically, through the fluent language inside PermissionManager class, we should configure all necessary handlers and infos for the permission request:

PermissionManager.create()
.addPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.addPermission(Manifest.permission.READ_CONTACTS)
.withCancelCallback(cancelCallback)
.withPermissionCallback(successCallback)
.requestPermissions(MainActivity.this, false);

Or, if you’re a RetroLambda guy.

PermissionManager.create()
.addPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.addPermission(Manifest.permission.READ_CONTACTS)
.withCancelCallback(() -> {
// handle cancel
}))
.withPermissionCallback(return (permission, granted) -> {
// handle callback
})
.requestPermissions(MainActivity.this, false);

The last step is to call the method PermissionManager.bindPermissionResult, that will send the permission result for the appropriate callback:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionManager.bindPermissionResult(this, permissions, grantResults);
}

Full activity code looks like:

import android.Manifest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

findViewById(R.id.request_permission).setOnClickListener(clickListener);
}


View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
PermissionManager.create()
.addPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.addPermission(Manifest.permission.READ_CONTACTS)
.withCancelCallback(cancelCallback)
.withPermissionCallback(successCallback)
.requestPermissions(MainActivity.this, false);
}
};

PermissionManager.Callback successCallback = new PermissionManager.Callback() {

@Override
public void onPermissionResult(String permission, boolean granted) {
if (granted) {
Toast.makeText(MainActivity.this, String.format("Permission %s granted!", permission), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, String.format("Permission %s denied!", permission), Toast.LENGTH_SHORT).show();
}
}
};

PermissionManager.CancelCallback cancelCallback = new PermissionManager.CancelCallback() {
@Override
public void onCancel() {
Toast.makeText(MainActivity.this, "User cancel operation", Toast.LENGTH_SHORT).show();
}
};

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionManager.bindPermissionResult(this, permissions, grantResults);
}
}

Full code can be downloaded/forked on my github.

Like what you read? Give Pedro Souza a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.