Thanks to Anton Rassadin’s help doc, @RealAero and @ericwa I was able to get saves working with Unreal 5.4.3 on the Meta Oculus Quest 3. Saves weren’t working for me after I’d upgraded to 5.4. I could not save save files on my quest. Here’s all the relevant settings I’m aware of, and how i’ve set them, hopefully this is helpful to see it all in one place.
Build: shipping or development
Android
APK Packaging
Minimum SDK Version 32
Target SDK Version 32
useExternalFilesDir: True
Advanced APK Packaging
Extra Permissions
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
Launch Images
Show launch image: True
Android SDK settings:
I was getting this issue from MQDH meta quest developer hub / adb logs.:
java.lang.IllegalArgumentException: Primary directory UnrealGame not allowed for content://media/external_primary/file; allowed directories are [Download, Documents]
Here’s the full log error:
18:17:16.873 2146 19214 E MediaProvider : java.lang.IllegalArgumentException: Primary directory UnrealGame not allowed for content://media/external_primary/file; allowed directories are [Download, Documents]
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.ensureFileColumns(MediaProvider.java:3370)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.ensureUniqueFileColumns(MediaProvider.java:3021)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.insertFile(MediaProvider.java:3780)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:4364)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.insert(MediaProvider.java:4064)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.insertFileForFuse(MediaProvider.java:8375)
18:17:16.873 2146 19214 E MediaProvider : at com.android.providers.media.MediaProvider.insertFileIfNecessaryForFuse(MediaProvider.java:8470)
18:17:16.878 2146 10646 W MediaProvider : Forgot to handle a top level directory in getContentUriForFile?
I added one file, and edited another:
AndroidSanitizePermissions_UPL.xml:
<root xmlns:android="http://schemas.android.com/apk/res/android">
<androidManifestUpdates>
<loopElements tag="meta-data">
<setStringFromAttribute result="NameTagValue" tag="$" name="android:name"/>
<setBoolIsEqual result="UseExternalFilesDirElement" arg1="$S(NameTagValue)" arg2="com.epicgames.unreal.GameActivity.bUseExternalFilesDir"/>
<if condition="UseExternalFilesDirElement">
<true>
<removeElement tag="$"/>
</true>
</if>
</loopElements>
<addElements tag="application">
<meta-data android:name="com.epicgames.unreal.GameActivity.bUseExternalFilesDir" android:value="true" />
</addElements>
</androidManifestUpdates>
</root>
Then create a link to this in your build script: *the project name in this case is NitroGrid
NitroGrid.Build.cs:
using UnrealBuildTool;
public class NitroGrid : ModuleRules
{
public NitroGrid(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" });
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
// Allow saves on android
if (Target.Platform == UnrealTargetPlatform.Android)
{
string manifestFile = System.IO.Path.Combine(ModuleDirectory, "AndroidSanitizePermissions_UPL.xml");
AdditionalPropertiesForReceipt.Add("AndroidPlugin", manifestFile);
}
}
}
After making those changes, saving save objects worked great.
I did not need to request save permissions with this code, possibly because I installed via the .bat file generated with the APK file, which grants permissions. If you’d using a different install method, you may need to request permissions like this: