Android Easy Permissions(For Devs)

From Android Marshmallow it is mandatory for devs to request permissions on runtime. Which is great for user security but it adds additional burden on developers.
Every time we create a new Android project we need to go through same hassle of looking for dangerous permission in App’s Manifest & add same repetitive boilerplate code to request permissions.
And it don’t stop here, everytime we add a new permission in app’s Manifest we had to add permission request for that .
This seems all right but when you work on lots of POC this Marshmallow this is painful. This pain could be seen even in my code:
https://stackoverflow.com/a/44021987/2252113
I decide to address this Permission problem once and for all
I created a class which automatically:
- Fetch all the permissions registered in Manifest then
- Filter all registered permissions who came under dangerous permissions
- Automatically Request for dangerous permission
- If permissions are granted setUpViewWithPermissions() will be called
- If all permission will not granted setUpViewWithoutPermissions will be triggered
/**
* class help with permission stuffs
*
* This class reads Registered Permissions in Manifest & detect Dangerous Permissions from them & request them automatically
*
* if permissions are granted setUpViewWithPermissions will be called
*
* If all permission will not granted setUpViewWithoutPermissions will be triggered
*/
abstract class EasyPermissionActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE);
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(getActivityLayout())
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions()
} else {
// Pre-Marshmallow
setUpViewWithPermissions()
}
}
//SetUp views after permission granted
abstract fun setUpViewWithPermissions()
//SetUp views when all permission not granted
abstract fun setUpViewWithoutPermissions()
// activity view
abstract fun getActivityLayout(): Int
private fun requestPermissions() {
val allPermissions =
packageManager
.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
.requestedPermissions
//get all permissions used by app and then filter them if they are Dangerous Permissions
val dangerousPermissions = filterDangerousPermissions(allPermissions)
//list of permissions that are not granted
val listPermissionsNeeded = ArrayList<String>()
dangerousPermissions.forEach { dangerousPermission ->
if (ContextCompat.checkSelfPermission(this, dangerousPermission) != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(dangerousPermission)
}
}
if (listPermissionsNeeded.isNotEmpty()) {
// request if Permissions needed
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toTypedArray(), MULTIPLE_PERMISSIONS)
} else {
// if already granted move on
setUpViewWithPermissions()
}
}
/**
* param: list of registered permissions from App's Manifest
* return :list of dangerous permissions registered in App's manifest
*/
private fun filterDangerousPermissions(registeredPermissionsList: Array<out String>?): ArrayList<String> {
try {
val dangerousPermissionsList = ArrayList<String>()
if (registeredPermissionsList != null) {
for (permission in registeredPermissionsList) {
// if App came under dangerous permission add to dangerousPermissions
if (DANGEROUS_PERMISSIONS.contains(permission)) {
dangerousPermissionsList.add(permission)
}
}
}
return dangerousPermissionsList
} catch (e: PackageManager.NameNotFoundException) {
throw RuntimeException("This should have never happened.", e)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissionsList: Array<String>, grantResults: IntArray) {
when (requestCode) {
MULTIPLE_PERMISSIONS -> {
if (grantResults.isNotEmpty()) {
var permissionsDeniedMessage = ""
for (i in 0 until permissionsList.size) {
// if permission is deniewd add to permissionsDeniedMessage
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
permissionsDeniedMessage += "\n " + permissionsList[i]
}
}
if (permissionsDeniedMessage.isEmpty()) {
// all permissions granted
setUpViewWithPermissions()
Toast.makeText(this, "All permission Granted :) " + permissionsDeniedMessage, Toast.LENGTH_LONG).show()
} else {
// all permissions NOT granted
setUpViewWithoutPermissions()
Toast.makeText(this, "Permission Denied :(" + permissionsDeniedMessage, Toast.LENGTH_LONG).show()
}
}
return
}
}
}
companion object {
const val MULTIPLE_PERMISSIONS = 10 // Permission request code
//
// Permissions defined as dangerous permissions by
// https://developer.android.com/guide/topics/permissions/overview#permission-groups
val DANGEROUS_PERMISSIONS = listOf(
//CALENDER
android.Manifest.permission.READ_CALENDAR,
android.Manifest.permission.WRITE_CALENDAR,
//CALL
android.Manifest.permission.READ_CALL_LOG,
android.Manifest.permission.WRITE_CALL_LOG,
android.Manifest.permission.PROCESS_OUTGOING_CALLS,
//CAMERA
android.Manifest.permission.CAMERA,
//CONTACTS
android.Manifest.permission.READ_CONTACTS,
android.Manifest.permission.WRITE_CONTACTS,
android.Manifest.permission.GET_ACCOUNTS,
//LOCATION
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
//MICROPHONE
android.Manifest.permission.RECORD_AUDIO,
//PHONE
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_PHONE_NUMBERS,
android.Manifest.permission.CALL_PHONE,
android.Manifest.permission.ANSWER_PHONE_CALLS,
android.Manifest.permission.ADD_VOICEMAIL,
android.Manifest.permission.USE_SIP,
//SENSOR
android.Manifest.permission.BODY_SENSORS,
//SMS
android.Manifest.permission.SEND_SMS,
android.Manifest.permission.RECEIVE_SMS,
android.Manifest.permission.READ_SMS,
android.Manifest.permission.RECEIVE_WAP_PUSH,
android.Manifest.permission.RECEIVE_MMS,
// Storage
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}
How to use it?
Add this class in your project. Extend your Main Activity with EasyPermissionActivity.
class HomeActivity : EasyPermissionActivity() {// your activity layout to inflate
override fun getActivityLayout(): Int {
return R.layout.activity_main
}override fun setUpViewWithoutPermissions() {//update UI When All Permissions not granted}override fun setUpViewWithPermissions() {//update UI When All Permissions are granted}
}
Thats it now next time when you add any permission in App’s Manifest you wont need to write a single line of code. 🎉