Dev: Handling Permissions
Relevant source files
The following files were used as context for generating this wiki page:Introduction
The application's permission handling system is a critical component that governs access to device hardware and storage, essential for its core OCR functionality. The primary permissions required are for camera access to capture images and storage access to manage these images and OCR language data. The project plan specifies a graceful handling approach for permission requests and denials, with the UI components for this flow defined in the presentation layer.
The development roadmap outlines camera permission handling as a key milestone in Phase 2, emphasizing the need to request permissions, show a rationale, and handle denial by navigating the user to app settings. The intended implementation library is Accompanist Permissions.
Sources: ROADMAP.md:126-131, TODO.md:65-68
Declared Permissions and Features
The application declares necessary hardware features and user permissions in its AndroidManifest.xml. This file serves as the single source of truth for the permissions the Android system will prompt the user for.
Hardware Features
The app declares its use of the camera and autofocus capabilities. By setting android:required="false", the app can be installed on devices without a camera, allowing users to process images from the gallery.
| Feature | Required | Purpose |
|---|---|---|
android.hardware.camera | false | Indicates the app uses the camera. |
android.hardware.camera.autofocus | false | Indicates the app uses the camera's autofocus feature. |
Sources: app/src/main/AndroidManifest.xml:6-11
User Permissions
The following table details the permissions requested by the application. The use of maxSdkVersion for storage permissions indicates compatibility with Android's evolving storage access policies (Scoped Storage).
| Permission | maxSdkVersion | Purpose |
|---|---|---|
android.permission.CAMERA | N/A | To access the device camera for capturing images to be processed by the OCR engine. |
android.permission.READ_EXTERNAL_STORAGE | 32 | To read images from the user's gallery on Android versions up to 12L. |
android.permission.WRITE_EXTERNAL_STORAGE | 28 | To save files on Android versions up to 9. This is largely superseded by Scoped Storage on newer APIs. |
android.permission.READ_MEDIA_IMAGES | N/A | The modern equivalent of READ_EXTERNAL_STORAGE for Android 13+ to access images in shared storage. |
This diagram illustrates the declared permissions and the features they enable.
Permission Handling UI Flow
The application defines specific UI components to manage the user interaction during the permission request process. These components are designed to provide clear explanations and guide the user when a permission is denied. The logic is encapsulated within composable functions in PermissionHandler.kt.
UI Components
PermissionRationaleDialog: This dialog is shown when the user has denied a permission previously, but not permanently. It explains why the camera permission is necessary for the app's functionality and gives the user a chance to grant it.PermissionDeniedDialog: This dialog is displayed when the permission has been permanently denied. It informs the user that the feature is unavailable and provides a button to open the app's settings, allowing them to grant the permission manually.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/camera/PermissionHandler.kt:12-67
User Flow Diagram
The following flowchart illustrates the intended sequence of events when the camera permission is requested.
This flow ensures a user-friendly experience by explaining the need for permissions and providing an easy path to enable them if they are denied.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/camera/PermissionHandler.kt, ROADMAP.md:126-131
Code Snippets
The PermissionRationaleDialog provides a clear explanation for why the camera is needed.
// app/src/main/java/com/musagenius/ocrapp/presentation/ui/camera/PermissionHandler.kt:12-34
@Composable
fun PermissionRationaleDialog(
onDismiss: () -> Unit,
onConfirm: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(text = "Camera Permission Required")
},
text = {
Text(
text = "This app needs camera access to scan documents and extract text. " +
"Without camera permission, you can only select images from your gallery."
)
},
confirmButton = {
TextButton(onClick = onConfirm) {
Text("Grant Permission")
}
},
// ...
)
}
If the user permanently denies the permission, the PermissionDeniedDialog guides them to the system settings.
// app/src/main/java/com/musagenius/ocrapp/presentation/ui/camera/PermissionHandler.kt:42-67
@Composable
fun PermissionDeniedDialog(
onDismiss: () -> Unit,
onOpenSettings: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(text = "Camera Permission Denied")
},
text = {
Text(
text = "Camera permission was denied. To use the camera for scanning, " +
"please enable camera permission in app settings."
)
},
confirmButton = {
TextButton(onClick = onOpenSettings) {
Text("Open Settings")
}
},
// ...
)
}
Conclusion
The permission handling system is a well-defined part of the application, with clear declarations in the AndroidManifest.xml and robust UI components for managing user interactions. The architecture accounts for different user responses—grant, denial, and permanent denial—by providing rationales and direct links to system settings. The version-specific storage permissions demonstrate an understanding of modern Android platform requirements, ensuring the app remains functional and compliant across different API levels.