Mobile Permissions Support
Feature Request
Currently, there is no way to request or manage permissions on mobile platforms in Dioxus applications. This affects critical functionality such as camera access, location services, file system access, and other platform capabilities that require user permission.
Background
Mobile applications require permissions to access sensitive device features and user data. Both Android and iOS have their own permission systems that differ significantly in implementation but serve the same purpose of protecting user privacy.
Platform Requirements
Android Permission System
Android uses a dual-layer permission system:
-
Manifest Declaration: All permissions must be declared in
AndroidManifest.xml -
Runtime Requests: Permissions are categorized by protection level:
-
Normal Permissions (automatically granted at install, no runtime request needed):
android.permission.INTERNETandroid.permission.ACCESS_NETWORK_STATEandroid.permission.VIBRATEandroid.permission.SET_ALARM
-
Dangerous Permissions (require runtime request):
android.permission.CAMERAandroid.permission.READ_CONTACTSandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.RECORD_AUDIO
-
Special Permissions (require specific handling):
android.permission.SYSTEM_ALERT_WINDOWandroid.permission.WRITE_SETTINGS
-
Android provides a unified permission request API that works consistently across different permission types.
iOS Permission System
iOS has a different approach:
-
Info.plist Declarations: All privacy-sensitive permissions must be declared in
Info.plistwith appropriate usage description strings (explaining why the app needs the permission) -
Per-Permission APIs: Unlike Android, iOS uses separate APIs for each permission type:
- Camera access uses
AVCaptureDevice.requestAccess(for:) - Location uses
CLLocationManager.requestWhenInUseAuthorization() - Photo library uses
PHPhotoLibrary.requestAuthorization() - Each with their own callback patterns
- Camera access uses
-
Usage Descriptions: Every permission requires a corresponding entry in Info.plist:
NSCameraUsageDescriptionNSPhotoLibraryUsageDescriptionNSLocationWhenInUseUsageDescription- And many others
-
Special Entitlements: Some iOS capabilities require additional entitlements beyond Info.plist entries:
- Push Notifications
- Apple Pay
- iCloud
- App Groups
- Background Modes
Platform-Specific Permissions
Each platform has unique permissions that don't exist on the other:
Android-only Permissions:
android.permission.SYSTEM_ALERT_WINDOWandroid.permission.READ_SMS/android.permission.RECEIVE_SMSandroid.permission.READ_PHONE_STATEandroid.permission.WRITE_SETTINGSandroid.permission.REQUEST_INSTALL_PACKAGES
iOS-only Permissions:
- Tracking Authorization (
NSUserTrackingUsageDescription) - Local Network (
NSLocalNetworkUsageDescription) - Critical Alerts (
UNAuthorizationOptionCriticalAlert) - Face ID/Touch ID (
NSFaceIDUsageDescription) - Photo Library Additions (
NSPhotoLibraryAddUsageDescription)
Proposed Implementation
Due to the specific platform needs and evolving technologies, it may be best to expose AndroidManifest.xml and Info.plist to be used in the compiled platform projects. There should be a unified native experience for permissions. Maybe something like
let result = dioxus::mobile::android::require_permission(AndroidPermission::SystemAlertWindow); // platform specific
...
let result = dioxus::mobile::ios::require_permission(IosPermission::TrackingAuthorization); // platform specifc, corresponds to NSUserTrackingUsageDescription in Info.plist
...
let result = dioxus::mobile::require_permission(Permission::CAMERA); // cross platform
Which is can be used as guards that prompt the user for permission if not already granted.
Documentation Strategy
We should provide:
- Comprehensive API documentation for all permission-related functions
- Feature-based guides (e.g., "Using the Camera in Dioxus Mobile")
- Platform-specific permission best practices
- Examples demonstrating proper permission flow handling
Alternative Implementation
A fully unified permission API in Cargo.toml or dioxus.toml would be simpler for developers but wouldn't adequately address platform-specific requirements. Even with a unified configuration approach for common permissions, exposing direct access to platform configuration files is necessary for advanced use cases. Also the merging of generated platform files with user-provided configurations introduces complexity and potential conflicts.
Unanswered Questions
How should libraries that require permissions interact with downstream applications? Maybe simply recommending including a section in the README for configuring AndroidManifest.xml and Info.plist is enough.
Prior Art
- https://crates.io/crates/crossbow
- https://v2.tauri.app/security/permissions/
- https://github.com/DioxusLabs/dioxus/pull/3535
We've thought about this lately and my own thoughts are that we need to expose the files themselves (AndroidManifest.xml & Info.plist), but I would also like a way to merge and propagate permission requirements automatically from dependencies (such as SDK). The latter would likely require Manganis.
It is good to know that Info.plist requires permission usage descriptors.
Some considerations -
On android, uses-permission/permission is a direct descendant of manifest and on IOS permissions are also a direct descendant of dict so merging would not be too complex. For both android and IOS, I believe when duplicates are encountered, the last one takes Precedence. Beyond duplicates it would probably be best if the entries themselves could be merged, though the correct behavior of merging may be complicated. E.g. Assume two libraries with the following
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
These can't really be merged since the later may use bluetooth for location. Another consideration is Info.plist descriptors on IOS are also shown to the user.
Thus for merging solution, the most correct and maintainable solution might be to fail building on such conflicts with a conflict reason and have the user manually specify them in their config file. This would also mean that resolution needs to be done in reverse breadth first order. A downside to this is that permission files start to become spaghetti with some permissions needed by the application, some needed for conflict resolution from libraries, and others not specified but will be applied when merging.
That said, maybe the easiest and most correct solution is not to do merging and propagation. Another reason for this: E.g. A library may have have bluetooth functionality, but a downstream application never uses that, so it actually does not need <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />. Also considering libraries will likely have feature flags where some permissions may be needed and others not, this is probable.
Is there any plans for implementing this? If this is not a priority, then what is the suggested workaround? I want to use USB accessories on Android and camera on all native platforms.
Agree - this is already implemented for macOS via dioxus.toml using the info_plist_path option... am i missing the way to specify an info.plist for ios, or AndroidManifest for android?
Indeed, @czarop, this feature has been partially added but not properly documented.
Indeed, @czarop, this feature has been partially added but not properly documented.
Ah really @Sitin ? Are you able to provide any info for this, specifically specifying an info.plist in an iOS build - it would save me a ton of time building manually!
Sorry if my words have confused you, @czarop. I meant to say that MacOS options are there, but they are not well documented yet. There is just a link to a struct containing bundle settings (0.6 docs).
The ability to specify Info.plist for iOS (similar to what exists for MacOS) would be greatly appreciated and unblock many capabilities.
In case you haven't seen it, since the v0.7.0-alpha0 it is possible to define in Dioxus.toml
[application]
android_manifest = "./AndroidManifest.xml"
with a custom AndroidManifest.xml in your directory.
For example (based on AndroidManifest.xml.hbs present in this repo, I don't recommend modifying anything but the permissions):
<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:hasCode="true"
android:supportsRtl="true"
android:icon="@mipmap/ic_launcher"
android:extractNativeLibs="true"
android:allowNativeHeapPointerTagging="false"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config"
>
<activity
android:configChanges="orientation|screenLayout|screenSize|keyboardHidden"
android:exported="true"
android:label="@string/app_name"
android:name="dev.dioxus.main.MainActivity"
>
<meta-data
android:name="android.app.lib_name"
android:value="dioxusmain"
/>
<meta-data
android:name="android.app.func_name"
android:value="ANativeActivity_onCreate"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And if you need to access https based apis on javascript (geolocation for examples), I fixed this issue in my PR #4428.