Catalog · How the catalog works
MBen.AndroidPermissions
A fluent, production-ready Android permissions management library for Delphi that provides intelligent manifest verification, detailed logging, and granular permission control for modern Android development.
- ★ 1 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
Android Permissions Management Library for Delphi
⚠️ BETA DEMO - This is a proof-of-concept library for educational and demonstration purposes. Not recommended for production use without thorough testing.
A fluent Android permissions management library for Delphi that provides intelligent manifest verification, detailed logging, and granular permission control.
🚀 Features
Ready-to-Use Methods
Configuration
SetLogger()- Inject logging callback
Permission Addition (3 Ways)
- Fluent methods:
.CAMERA.ACCESS_FINE_LOCATION...(type-safe) AddPermission()- Dynamic single add (runtime)AddPermissions()- Batch add from array
Permission Queries
GetGrantedPermissions()- All granted permissionsGetDeniedPermissions()- All denied/missing permissionsGetNotInManifestPermissions()- Permissions not in manifestToArray()- All added permissions
Execution
CheckAndRequest()- Execute complete check/verify/request process ⭐
Core Capabilities
- ✅ Fluent API - Chain methods naturally
- ✅ Manifest Verification - Auto-validates permissions exist in AndroidManifest.xml
- ✅ Smart Sorting - Maintains manifest declaration order
- ✅ 3-Phase Process - Manifest → Analysis → Request
- ✅ Detailed Logging - Visual indicators (✓, ✗, ⏳, ⚠)
- ✅ Denial Detection - Distinguishes manifest missing vs user rejected
- ✅ Dynamic Support - Add new/future permissions at runtime
- ✅ Thread-Safe - Safe UI updates via TThread.Queue
- ✅ Zero Boilerplate - Single call handles everything
🔧 Installation
Step 1: Add Files
Copy to your project:
API.Android.Permissions.Interfaces.pasAPI.Android.Permissions.pas
Step 2: Add Uses Clause
uses
API.Android.Permissions.Interfaces,
API.Android.Permissions;Step 3: Declare in Form
type
TMainView = class(TForm)
MemoLog: TMemo;
private
FPermissions: iAndroidPermissions;
procedure Log(const aMsg: string);
end;Step 4: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="35" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<application>...</application>
</manifest>💡 Quick Start
Basic Usage
procedure TMainView.FormCreate(Sender: TObject);
begin
FPermissions := TAndroidPermissions.New
.SetLogger(Log)
.ACCESS_COARSE_LOCATION
.ACCESS_FINE_LOCATION
.CALL_PHONE
.CAMERA
.INTERNET
.READ_EXTERNAL_STORAGE
.READ_PHONE_STATE
.WRITE_EXTERNAL_STORAGE
.ACCESS_NETWORK_STATE // Not in manifest - will be flagged
.RECORD_AUDIO // Not in manifest - will be flagged
.READ_CONTACTS // Not in manifest - will be flagged
.SEND_SMS // Not in manifest - will be flagged
.CheckAndRequest(procedure(aAllGranted: Boolean; aGranted, aDenied: TArray<string>)
begin
if aAllGranted then
Log('✓ All permissions granted - app is fully operational!');
// // get only aGranted list ..
Log('Granted list:');
Log(GetLogPermissions(aGranted));
// // get only aDenied List ..
Log('Denied list:');
Log(GetLogPermissions(aDenied));
if IsPermGranted(cCAMERA) then
Log('Camera is granted');
end);
end;
procedure TMainView.Log(const aMsg: string);
begin
TThread.Queue(nil,
procedure
begin
MemoLog.Lines.Add(FormatDateTime('hh:nn:ss', Now) + ': ' + aMsg);
// Auto-scroll to bottom
if MemoLog.Lines.Count > 0 then
MemoLog.GoToTextEnd;
end);
end;Check Individual Permissions
// Check after CheckAndRequest completes
if IsPermGranted(cCAMERA) then
UseCameraFeatures()
else
DisableCameraFeatures();Three Ways to Add Permissions
Method 1: Fluent (Type-Safe)
FPermissions
.CAMERA
.ACCESS_FINE_LOCATION
.RECORD_AUDIO;Method 2: Dynamic Single
FPermissions.AddPermission('android.permission.CAMERA');Method 3: Batch
FPermissions.AddPermissions([
'android.permission.CAMERA',
'android.permission.READ_MEDIA_IMAGES'
]);Real-World Example
FPermissions := TAndroidPermissions.New
.SetLogger(Log)
.CAMERA
.ACCESS_FINE_LOCATION
.RECORD_AUDIO
.CheckAndRequest(procedure(aAllGranted: Boolean; aGranted, aDenied: TArray<string>)
begin
// Enable features individually
if IsPermGranted(cCAMERA) then
BtnCamera.Enabled := True;
if IsPermGranted(cACCESS_FINE_LOCATION) then
BtnLocation.Enabled := True;
if IsPermGranted(cRECORD_AUDIO) then
BtnAudio.Enabled := True;
// Log results
Log('Granted: ' + IntToStr(Length(aGranted)));
Log('Denied: ' + IntToStr(Length(aDenied)));
end);🎯 How It Works
Three-Phase Process
Phase 1: Manifest Verification
- Reads AndroidManifest.xml
- Lists all declared permissions
- Validates requested permissions exist
Phase 2: Permission Analysis
- Checks current grant status
- Categorizes as: Granted, Pending, or Not-in-Manifest
- Maintains manifest order
- Prepares request list
Phase 3: System Request
- Requests non-granted permissions
- Shows rationale dialog if needed
- Captures user responses
- Logs results
📊 Example Log Output
02:21:27:
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27: ??? ANDROID PERMISSIONS CHECK AND REQUEST PROCESS ???
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27:
02:21:27: This app uses the enhanced permissions system that:
02:21:27: 1. Verifies permissions exist in AndroidManifest.xml
02:21:27: 2. Checks current grant status
02:21:27: 3. Requests only missing permissions
02:21:27: 4. Logs detailed denial reasons
02:21:27: 5. Shows OS-level denial information
02:21:27:
02:21:27: Expected [Manifest.XML] Permissions At Runtime:
02:21:27:
02:21:27: ??? ACCESS_COARSE_LOCATION
02:21:27: ??? ACCESS_FINE_LOCATION
02:21:27: ??? CALL_PHONE
02:21:27: ??? CAMERA
02:21:27: ??? INTERNET
02:21:27: ??? READ_EXTERNAL_STORAGE
02:21:27: ??? READ_PHONE_STATE
02:21:27: ??? WRITE_EXTERNAL_STORAGE
02:21:27:
02:21:27: Application initialized. Ready to request permissions.
02:21:27:
02:21:27: Checking 12 permissions...
02:21:27:
02:21:27: PHASE 1: MANIFEST VERIFICATION
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27: Total permissions in manifest: 8
02:21:27:
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27:
02:21:27: PHASE 2: PERMISSION STATUS ANALYSIS
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27: Analyzing 12 requested permissions:
02:21:27:
02:21:27: ??? GRANTED: ACCESS_COARSE_LOCATION
02:21:27: ??? GRANTED: ACCESS_FINE_LOCATION
02:21:27: ??? GRANTED: CALL_PHONE
02:21:27: ??? GRANTED: CAMERA
02:21:27: ??? GRANTED: INTERNET
02:21:27: ??? GRANTED: READ_EXTERNAL_STORAGE
02:21:27: ??? GRANTED: READ_PHONE_STATE
02:21:27: ??? GRANTED: WRITE_EXTERNAL_STORAGE
02:21:27: ??? NOT_IN_MANIFEST: ACCESS_NETWORK_STATE
02:21:27: ?????? Action: Add to AndroidManifest.xml
02:21:27: ??? NOT_IN_MANIFEST: RECORD_AUDIO
02:21:27: ?????? Action: Add to AndroidManifest.xml
02:21:27: ??? NOT_IN_MANIFEST: READ_CONTACTS
02:21:27: ?????? Action: Add to AndroidManifest.xml
02:21:27: ??? NOT_IN_MANIFEST: SEND_SMS
02:21:27: ?????? Action: Add to AndroidManifest.xml
02:21:27:
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27: ANALYSIS SUMMARY:
02:21:27: Total Requested: 12
02:21:27: Already Granted: 8
02:21:27: Pending Request: 0
02:21:27: Not in Manifest: 4
02:21:27: ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
02:21:27:
02:21:27: ??? INCOMPLETE: Some permissions missing from manifest.
02:21:27:
02:21:27: Required manifest declarations:
02:21:27: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
02:21:27: <uses-permission android:name="android.permission.RECORD_AUDIO" />
02:21:27: <uses-permission android:name="android.permission.READ_CONTACTS" />
02:21:27: <uses-permission android:name="android.permission.SEND_SMS" />
02:21:27:
02:21:27: ??? All permissions granted - app is fully operational!
02:21:27: Granted list:
02:21:27:
android.permission.ACCESS_COARSE_LOCATION
android.permission.ACCESS_FINE_LOCATION
android.permission.CALL_PHONE
android.permission.CAMERA
android.permission.INTERNET
android.permission.READ_EXTERNAL_STORAGE
android.permission.READ_PHONE_STATE
android.permission.WRITE_EXTERNAL_STORAGE
02:21:27: Denied list:
02:21:27:
android.permission.ACCESS_NETWORK_STATE
android.permission.RECORD_AUDIO
android.permission.READ_CONTACTS
android.permission.SEND_SMS
02:21:27: Camera is granted🛠️ Helper Functions
Global Utilities
// Quick permission check
IsPermGranted(cCAMERA): Boolean
// Format permissions for logging
GetLogPermissions(aPerms: TArray<string>): stringUsage
if IsPermGranted(cCAMERA) then
Log('Camera available');
var Perms := FPermissions.GetGrantedPermissions;
Log('Granted:' + GetLogPermissions(Perms));📚 API Reference
Interface: iAndroidPermissions
interface iAndroidPermissions
function SetLogger(const aLogger: TLoggerProc): iAndroidPermissions;
// 200+ fluent permission methods
function CAMERA: iAndroidPermissions;
function ACCESS_FINE_LOCATION: iAndroidPermissions;
// ... etc
function AddPermission(const aPermission: string): iAndroidPermissions;
function AddPermissions(const aPermissions: TArray<string>): iAndroidPermissions;
function ToArray: TArray<string>;
function GetGrantedPermissions: TArray<string>;
function GetDeniedPermissions: TArray<string>;
function GetNotInManifestPermissions: TArray<string>;
function CheckAndRequest(const aOnResult: TPermissionResultProc = nil): iAndroidPermissions;
end;Callback Type
TPermissionResultProc = TProc<Boolean, TArray<string>, TArray<string>>;
// Parameters:
// - aAllGranted: All permissions granted?
// - aGranted: Granted permissions array
// - aDenied: Denied/missing permissions arrayPermission Constants
cCAMERA = 'android.permission.CAMERA';
cACCESS_FINE_LOCATION = 'android.permission.ACCESS_FINE_LOCATION';
cREAD_CONTACTS = 'android.permission.READ_CONTACTS';
// ... 197+ more constants🗺️ Roadmap
Version 1.0 (Current - Beta)
- ✅ Core permission management
- ✅ Fluent API with 200+ methods
- ✅ Manifest verification
- ✅ 3-phase process
- ✅ Detailed logging
How to Report
Include:
- Android version and device model
- Delphi version
- Permissions requested
- Expected vs actual behavior
- Complete log output
- Reproduction steps
📄 License
MIT License - Free to use, modify, and distribute
- Include license notice
- No liability accepted
🎓 Use Cases
- ✅ Educational demonstration
- ✅ Proof-of-concept projects
- ✅ Development and testing
- ✅ Reference implementation
- ⚠️ Production (test thoroughly first)
🤝 Contributing
- Test on multiple Android versions
- Report issues with full details
- Share improvements
- Suggest enhancements
⭐ Demonstration Library - Testing & Feedback Welcome
Version: 1.0.0-beta
Last Updated: January 2026
Status: BETA - Proof of Concept

