Skip to content

Conversation

@wheregmis
Copy link
Contributor

@wheregmis wheregmis commented Oct 26, 2025

This PR introduces a comprehensive linker-based permission management for automatic update of manifest files and android native plugin building foundation for Dioxus. The implementation is inspired by Manganis's linker-based asset collection approach.

Two main motivation for this PR

  1. To automatically handle the manifest file and info.plist file instead of invoking, ejecting or providing custom file.
  2. Able to pass in the java file path through linker, copy and bundle them (Opening doors for android native apis development)

To break things in chain for android side of things,

Just from top level how it works is

  • We do something like this in plugins
#[cfg(target_os = "android")]
dioxus_platform_bridge::android_plugin!(
    package = "dioxus.mobile.geolocation",
    plugin = "geolocation",
    files = ["src/android/PermissionsHelper.java"]
);
  • The macro embeds metadata into the compiled binary as a linker symbol named JAVA_SOURCE... with a hash.
  • This metadata contains the Java file paths, package name, and plugin name.

From CLI

  • Finds JAVA_SOURCE... symbols in the compiled binary.
  • Deseralize the metadata to get the java files
  • Reads the files from the disk
  • Copies them to gradle project (app/src/main/java)
  • Gradle Compiles and bundle
  • Similarly we register PERMISSION symbols from those plugins which we extract on the CLI and update the manifest.

Example Geolocation crate: https://github.com/wheregmis/mobile-geolocation
Example Demo: https://github.com/wheregmis/geolocation-demo

New crates: (Please suggest the names as i am bad at naming stuff)

  • permissions: Public API that re-exports permissions-core and permissions-macro for easy integration.
  • permissions-core: Types for permission declaration and platform identifiers (Android, IOS, MacOS) (We can extend the identifiers as needed or requested)
  • permissions-macro: Procedural Macros (static_permission!) for declaring permissions via linker symbol (So cli can extract the symbols and update the manifest files automatically)
  • dx-macro-helpers: Common helpers for linker based stuff, shared by manganis and permission
  • platform-bridge: Bareminimal Cross-platform FFI utilities and plugin metadata for Android (JNI) and Darwin (objc2)
  • platform-bridge-macro: android_plugin! macro for embedding Java source file paths in binaries via linker symbols

Extend Geolocation to support other os and build the framwork on platform-bridge and cli. (This portion of the code i will generate from AI as I believe there are other good people who can build full fledge Cross Platform Location Service, and just a note that this AI generated piece of code will leave outside dioxus repo, its just to test the platform-bridge and permissions)

  • MacOS
  • IOS
  • Android
    Below Platform uses runtime based permissions so we dont need to do anything for them on dioxus repo.
    Linux (The permissions are runtime based and can be handled from standard rust crates like rfd, std::fs, so we dont need to do anything on platform bridge side)
    Windows (The permissions are runtime based and can be handled from standard rust crates like windows-rs, winapi, so we dont need to do anything on platform bridge side)
  • Web

@wheregmis
Copy link
Contributor Author

Yey, Android Permission Dialog is working.
Screenshot_1761495440

Improves code formatting in has_location_permission and check_permission functions by splitting long lines and updating function signatures for better readability. No functional changes were made.
The java_plugin macro now accepts full relative paths for Java files instead of assuming a fixed directory structure. Documentation and usage examples have been updated to reflect this change, improving flexibility and clarity for specifying file locations.
Added checks for authorization status before requesting location permissions and retrieving location data. Now only requests permission if not determined, and attempts to retrieve cached location before starting location updates, improving efficiency and user experience.
Introduces the ios_plugin! macro in mobile-core-macro for declarative iOS framework metadata embedding. Updates mobile-core to re-export the macro and refactors mobile-geolocation to use ios_plugin! instead of manual linker attributes.
Expanded documentation for MainThreadCell, clarifying usage and safety. Changed visibility of MainThreadCell to public, improved method docs, and re-exported MainThreadMarker in darwin/mod.rs for easier access.
Changed the framework symbol prefix from '__DARWIN_FRAMEWORK__' to '__DARWIN_FW__' and updated the Mach-O section name from '__darwin_framework' to '__darwin_fw' for compliance with section name length limits and consistency.
Adds comments and corrects the path to Info.plist for iOS and macOS app bundles. For iOS, Info.plist is at the root of the .app bundle, while for macOS it is inside Contents/. Also improves warning message to include the missing path.
Improves permission extraction by returning an empty manifest when no permission symbols are found or when building a web bundle, as permissions are runtime-only in that case. Adds debug logging for missing symbols and ensures robust handling of these scenarios.
@wheregmis
Copy link
Contributor Author

Web:
image

@wheregmis
Copy link
Contributor Author

MacOs:
image

@wheregmis wheregmis changed the title Experimental: Permission, Building Blocks for Native APIs Draft: Permission, Building Blocks for Native APIs Oct 27, 2025
@wheregmis wheregmis changed the title Draft: Permission, Building Blocks for Native APIs Permission, Building Blocks for Native APIs Oct 27, 2025
@wheregmis
Copy link
Contributor Author

@ealmloff Thank you for the feedback. Other than these nits, What do you think about the overall process? Do you think this is something we should proceed with to upstream it? Or maybe try and figure some other build processes, toolings? I want to discuss some top level ideas on the whole process and how should we proceed.

…permission management

- Introduced `CustomPermissionBuilder` for creating custom permissions with platform-specific identifiers.
- Enhanced `PermissionBuilder` to support custom permissions and location permissions with a clear builder pattern.
- Updated documentation and examples in the macro README to reflect new usage patterns for custom and location permissions.
- Improved parsing logic in the macro to handle both builder and direct construction patterns for permissions.
@ealmloff
Copy link
Member

ealmloff commented Nov 5, 2025

@ealmloff Thank you for the feedback. Other than these nits, What do you think about the overall process? Do you think this is something we should proceed with to upstream it? Or maybe try and figure some other build processes, toolings? I want to discuss some top level ideas on the whole process and how should we proceed.

@jkelleyrtp may have more thoughts here as he set up most of the android/ios build support in the CLI

From my perspective, I think this is close to the right approach, but I'm not sure this is the right interface yet. The two approaches for collecting bindings seem to be either build scripts (like robius and tauri) or linker-based collection like this and wasm-bindgen. Between the two linker-based collection is a lot easier to consume which will be important as the number of native bindings grows.

Both tauri or robius require you to manually register permissions which adds extra setup for any system libraries. That approach makes permissions more visible, but automatically registering permissions is much easier to use. We may want to think about adding a prompt to accept or reject the new permissions collected by the linker, but overall I think the linker permissions approach is much nicer.

One concern with the linker approach for bindings is symbols that are optimized away. Looking at the example linked in your description, it looks like you/AI had some issues with symbols being dropped that required adding __ensure_permissions_linked. We will need to either make sure the symbol isn't dropped within the macro by adding #[used] or tie the symbol to the usage of the script that is linked so it is only dropped if the bindings are not used

@wheregmis
Copy link
Contributor Author

wheregmis commented Nov 5, 2025

@ealmloff Thank you for the feedback. Other than these nits, What do you think about the overall process? Do you think this is something we should proceed with to upstream it? Or maybe try and figure some other build processes, toolings? I want to discuss some top level ideas on the whole process and how should we proceed.

@jkelleyrtp may have more thoughts here as he set up most of the android/ios build support in the CLI

From my perspective, I think this is close to the right approach, but I'm not sure this is the right interface yet. The two approaches for collecting bindings seem to be either build scripts (like robius and tauri) or linker-based collection like this and wasm-bindgen. Between the two linker-based collection is a lot easier to consume which will be important as the number of native bindings grows.

Both tauri or robius require you to manually register permissions which adds extra setup for any system libraries. That approach makes permissions more visible, but automatically registering permissions is much easier to use. We may want to think about adding a prompt to accept or reject the new permissions collected by the linker, but overall I think the linker permissions approach is much nicer.

One concern with the linker approach for bindings is symbols that are optimized away. Looking at the example linked in your description, it looks like you/AI had some issues with symbols being dropped that required adding __ensure_permissions_linked. We will need to either make sure the symbol isn't dropped within the macro by adding #[used] or tie the symbol to the usage of the script that is linked so it is only dropped if the bindings are not used

Yes, __ensure_permissions_linked does need some nits, i agree on that part. I started with build script like how robius was working but its a hastle to build dex files copy it and alot of issues when the native plugins will grow. Supporting tauri native plugins would be awesome but i tried and failed as it needs some extra setups that we need to deal with to provide seamless experience. With the growing number of contributors and community i think we can definately provide better abstraction and maybe just sharing android/kotlin files with those plugins should be good. Also, another thing is instead of .java file only, i want to support ,kt file for registering kotlin files and placing it on copying it on correct path for kotlin so we dont have to use java only. (Some plugins are freely available for kotlin and java side of things). Another discussion is on the IOS side of things, building and supporting each native swift package is tricky and challenging like how we are providing seamless for android but i am also not sure if we can do almost everything with objc crates. But the way its growing i think we should be able to do almost majority of things with it so not handling each ios plugin as a native swift package + swift files seems more appealing to me atm.

- Added #[used] attribute to linker sections in both permission and Android plugin macros to prevent the linker from optimizing away symbols, ensuring they are preserved even if unused.
- Created static references to linker sections to enhance defense-in-depth against optimization issues.
@jkelleyrtp
Copy link
Member

jkelleyrtp commented Nov 6, 2025

Going through the linker seems to be the right approach for permissions. Both build scripts and linker will require an end tool to collect the permissions, and I much prefer infrastructure-as-code approaches than the implicit build script. It's nice that not using a permission means not inserting it the Info.plist. Instead of #[used] attributes I would prefer that we make the permission a required argument to the function that requests the permission, and then we perform a volatile read, forcing the symbol to remain. This is similar to how Asset remains because its Display impl forces a volatile read.

We might need to think about Koitlin/Swift source files a bit more since cargo's cache busting system will be more reliable than the linker-based system, at least early on.

However, I'd rather not create a new symbol type for collecting permissions and instead try to reuse the one we use for assets. Though, the asset symbol format is not very flexible (see #4863), so it might require some work on our end to allow different variants as long as they're the same size. Adding a new symbol seems to require duplicating logic in the CLI which we can avoid if we stick with one symbol with different variants.


Also, FWIW, this would be at the top of the list for 0.8 features. If we could get it in 0.7, then it would be at the top of priority behind fixing bugs, that way we can ship native apis while still on 0.7

@wheregmis
Copy link
Contributor Author

@jkelleyrtp Thank you for the inputs. All the recommendation and inputs seems super valid and reasonable. After looking into #4863 I do think if we can somehow provide a appropriate way of creating different variants, and we dont need to create multiple symbols, alot of code on the CLI for extracting symbols can be alot more refined and cleaned. For kotlin/swift sources files, I also dont have super huge usecase to get into alot more depth to learn and define the fundamentals so i would definately leave these big chunks to dioxus core members. For the time being i will try to update my codes to more like an enum of LinkerSymbol which can hold either asset or permission and try to cleanup the CLI code abit so we dont go with multiple symbol type and can slip the permissions under MANGANIS symbol. And when we have a concrete plan for #4863 I can update my code for it. Also maybe we can try to slip in the permissions related stuff if possible into the 0.7 that way in with permissions, followed by build system for kotlin/swift and native apis can be added and shipped while still on 0.7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants