Skip to content

Create "manifest_override" feature - #23

Open
NathanaelA wants to merge 1 commit into
mzdk100:mainfrom
NathanaelA:escape_hatch
Open

Create "manifest_override" feature #23
NathanaelA wants to merge 1 commit into
mzdk100:mainfrom
NathanaelA:escape_hatch

Conversation

@NathanaelA

Copy link
Copy Markdown

This allows an escape hatch to declare a custom AndroidManifest.xml file to be copied rather than have it be generated.

In my specific case their are several items that the current generator doesn't support , and this now makes this tool (at least in the Android Manifest) easily forward compatible immediately as if the generator doesn't work you can override it with your own.

…e a custom AndroidManifest.xml file to be copied rather than generated.
@mzdk100

mzdk100 commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Can you give an example? It's best to use generators to support those use cases, which is consistent with Rust's best practices of using unified manifest files.

@NathanaelA

Copy link
Copy Markdown
Author

Yep, I specifically ran into a few issues that I can remember (and several more that I can't)

  1. the android:requestLegacyExternalStorage="true" in the tool manifest generator is creating a child-node inside of <application> like <requestLegacyExternalStorage>true</...> rather than putting that as a key:value pair in the `' -- I don't know if that works for other people but it is NOT working for me on the Meta Quest -- I spent way to many HOURS wasting time trying to figure out why the prior version using cargo-ndk and own manifest was working yet moving to the cargo-apk2 was totally failing.
Manifests

Created by Cargo-APK2

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mgcarpet.vr"
          android:versionCode="16777472" android:versionName="0.1.0">
    <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="29"/>
    <uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1"/>
    <uses-feature android:name="com.oculus.feature.PASSTHROUGH" android:required="false"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application android:debuggable="false" android:label="Magic Carpet VR" android:extractNativeLibs="true">
        <android:allowNativeHeapPointerTagging/>
        <android:requestLegacyExternalStorage>true</android:requestLegacyExternalStorage>
        <meta-data android:name="com.oculus.supportedDevices" android:value="quest2|questpro|quest3|quest3s"/>
        <activity
                android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
                android:name="android.app.NativeActivity"
                android:screenOrientation="landscape" android:exported="true" android:resizeableActivity="false">
            <meta-data android:name="android.app.lib_name" android:value="mgc_app"/>
            <meta-data android:name="com.oculus.intent.category.VR" android:value="vr_only"/>
            <meta-data android:name="com.oculus.supportedDevices" android:value="quest2|questpro|quest3|quest3s"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
                <category android:name="com.oculus.intent.category.VR"/>
            </intent-filter>
        </activity>
        <activity
                android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
                android:name="rust.jniminhelper.PermActivity"
                android:screenOrientation="landscape" android:resizeableActivity="false"/>
    </application>
</manifest>

Created by me:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.mgcarpet.vr"
          android:versionCode="1"
          android:versionName="0.1.0">

    <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="29"/>

    <!-- VR headtracking required; Quest 3 always provides it -->
    <uses-feature
        android:name="android.hardware.vr.headtracking"
        android:required="true"
        android:version="1"/>

    <!-- Boundaryless application -->
    <uses-feature
            android:name="com.oculus.feature.BOUNDARYLESS_APP"
            android:required="true"/>

    <!-- Passthrough is optional — useful for future mixed-reality overlays -->
    <uses-feature
        android:name="com.oculus.feature.PASSTHROUGH"
        android:required="false"/>

    <!-- /sdcard/mgcarpet/baked/ game data — legacy full access under targetSdkVersion 29 (see above) -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:label="Magic Carpet VR"
        android:requestLegacyExternalStorage="true"
        android:hasCode="true">

        <!--
          NativeActivity: the OS calls into the .so produced by mgc-app.
          lib_name must match the Cargo package name (hyphens → underscores).
        -->
        <activity
            android:name="android.app.NativeActivity"
            android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
            android:exported="true"
            android:resizeableActivity="false"
            android:screenOrientation="landscape">

            <meta-data
                android:name="android.app.lib_name"
                android:value="mgc_app"/>

            <!-- Main launcher + VR category: Quest OS launches this as a VR app -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
                <category android:name="com.oculus.intent.category.VR"/>
            </intent-filter>

            <!-- Tell the Meta runtime this is a VR-only application -->
            <meta-data
                android:name="com.oculus.intent.category.VR"
                android:value="vr_only"/>

        </activity>

        <activity
                android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
                android:name="rust.jniminhelper.PermActivity" android:screenOrientation="landscape"
                android:resizeableActivity="false"/>
    </application>
</manifest>
  1. During my tests trying to figure things out, for one test I wanted to do; I needed access to "tools:support" on a uses-permissions which requires not only that extra support on the uses-permission, but also requires a change on the top level to add the tools xmlns. I might still need to do this in the future, if I find some reason I need to move to API 31, but currently keeping it at api 29 & using my own manifest fixes the permissions issue... FYI; tools:xxxx are valid attributes on many different nodes; the generator has zero support for the tools namespace.

  2. Theme on "Activity" is missing. (Minor, but ran into it while trying to fix a different issue. 😆 )

  3. Top level nodes: Queries, path-permissions, properties, and uses-library are all items I've used in past app's, none of these are supported in the generator.

In addition, if you look at:
https://developer.android.com/guide/topics/manifest/manifest-intro#reference
&
https://developer.android.com/guide/topics/manifest/application-element
&
https://developer.android.com/guide/topics/manifest/activity-element

There are a massive number of both top level nodes and key:values that aren't currently supported...

So having an escape hatch, seems like a reasonable feature request...

@mzdk100

mzdk100 commented Aug 12, 2026

Copy link
Copy Markdown
Owner

I can merge this PR to temporarily solve this scenario problem, but I need you to add instructions for adding this feature in the README.

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.

2 participants