How to Request Runtime Permissions in Android Using EasyPermissions Library
Runtime permissions became mandatory in Android starting from Android Marshmallow (API level 23).
Instead of automatically granting permissions during installation, Android now asks users to approve dangerous permissions while the app is running.
Managing permissions manually can become repetitive and difficult, especially when handling multiple permissions and permanently denied states.
In this tutorial, we will learn how to use the EasyPermissions library in Android to request runtime permissions more efficiently.
What Is EasyPermissions?
EasyPermissions is a lightweight Android library developed to simplify runtime permission handling.
It helps developers:
- Request multiple permissions
- Handle permission callbacks
- Show rationale dialogs
- Handle permanently denied permissions
- Redirect users to app settings
Why Runtime Permissions Are Important
Dangerous permissions allow access to sensitive device features such as:
- Camera
- Storage
- Location
- Microphone
- Contacts
Android requires developers to request these permissions during runtime for better user privacy and security.
Step 1 — Add Dependency
Open your build.gradle file and add the following dependency:
implementation 'pub.devrel:easypermissions:3.0.0'
After adding the dependency, sync your Gradle project.
Step 2 — Add Permissions in AndroidManifest.xml
Open AndroidManifest.xml and add the required permissions.
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
These permissions are required for camera access and reading device storage.
Step 3 — Create Layout File
Create the UI inside activity_main.xml.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_open_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Camera"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4 — Implement Permission Handling
Open MainActivity.java and add the following code:
package com.example.easypermissionexample;
import android.Manifest;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import java.util.List;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;
public class MainActivity extends AppCompatActivity
implements EasyPermissions.PermissionCallbacks {
private static final int REQUEST_CODE = 123;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonOpenCamera =
findViewById(R.id.button_open_camera);
buttonOpenCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera();
}
});
}
@AfterPermissionGranted(REQUEST_CODE)
private void openCamera() {
String[] perms = {
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE
};
if (EasyPermissions.hasPermissions(this, perms)) {
Toast.makeText(
this,
"Permissions Granted",
Toast.LENGTH_SHORT
).show();
} else {
EasyPermissions.requestPermissions(
this,
"Camera and Storage permissions are required",
REQUEST_CODE,
perms
);
}
}
@Override
public void onPermissionsGranted(
int requestCode,
@NonNull List<String> perms
) {
}
@Override
public void onPermissionsDenied(
int requestCode,
@NonNull List<String> perms
) {
if (EasyPermissions.somePermissionPermanentlyDenied(
this,
perms
)) {
new AppSettingsDialog.Builder(this)
.build()
.show();
}
}
@Override
public void onRequestPermissionsResult(
int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults
) {
super.onRequestPermissionsResult(
requestCode,
permissions,
grantResults
);
EasyPermissions.onRequestPermissionsResult(
requestCode,
permissions,
grantResults,
this
);
}
}
How This Implementation Works
The permission workflow is:
- User clicks the button
- Application checks permissions
- If permissions are granted, camera logic runs
- If permissions are denied, Android permission dialog appears
- If user permanently denies permissions, app settings dialog opens
Handling Permanently Denied Permissions
When users check:
Don't ask again
Android will stop showing the permission dialog.
EasyPermissions helps redirect users to:
- App Settings
- Permission Management Screen
This improves user experience significantly.
Common Mistakes Developers Make
1. Forgetting Manifest Permissions
Runtime requests will fail if permissions are missing inside the manifest file.
2. Not Handling Denied Permissions
Applications should gracefully handle denied states instead of crashing.
3. Requesting Too Many Permissions
Request only the permissions required for the feature currently being used.
Modern Android Permission Recommendations
For production Android applications:
- Request permissions only when needed
- Explain clearly why permissions are required
- Handle denied states properly
- Support Android 13+ permission changes
- Use Activity Result APIs when possible
EasyPermissions vs Manual Permission Handling
| EasyPermissions | Manual Handling |
|---|---|
| Cleaner code | More boilerplate |
| Built-in rationale support | Manual dialog management |
| Settings redirection support | Manual intent handling |
FAQ
Is EasyPermissions still useful in 2026?
Yes. It remains useful for simplifying Android runtime permission handling.
Can I request multiple permissions together?
Yes. EasyPermissions supports requesting multiple permissions in a single dialog.
What happens if the user permanently denies permission?
The application should redirect users to App Settings so they can manually grant permissions.
Conclusion
Runtime permission handling is an important part of modern Android development.
The EasyPermissions library simplifies permission requests, improves readability, and helps developers manage permission states efficiently.
Using proper permission handling improves application security, user trust, and overall user experience.
About the Author
Salil Jha is a Full Stack and Mobile Developer with experience in Android, React Native, scalable SaaS products, fintech applications, and developer tooling platforms.
CodeChain Dev — Build Modern Products. Solve Real Problems.
Deep Structural Diagnostics.
Mastering JSON is only the first step. Use our industrial-grade workbench to format, validate, and synthesize models for your production APIs.