immersivecognition / unity-experiment-framework

UXF - Framework for creating human behaviour experiments in Unity
https://immersivecognition.github.io/unity-experiment-framework/
MIT License
215 stars 41 forks source link

Android and Standalone HMD Local File Save #85

Closed A-Ivan closed 2 years ago

A-Ivan commented 2 years ago

Hi @jackbrookes ,

I noticed that in UXF 2.0 documentation, it is noted in the compatibility page that file saver does not work for Android or standalone HMD (i.e., Oculus Quest, which also uses Android) and that a HTTP Post option is needed.

But from what I understand, I can't test right now because I don't have a Quest with me, is that it is possible to locally save the csv files. These files would just need to be accessed by connecting the device to a computer and manually copying those files over to the computer.

It seems that as long as the function to save the csv file is using "Application.persistentDataPath", then it should work and save to "/storage/emulated/0/Android/data//files"- https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html

There may be some write permissions to set though (Unity Editor Menu -> Edit -> Project Settings -> Player -> Write Permission) - https://forum.unity.com/threads/writing-files-to-oculus-quest.1076615/

image

You may have to play around with these options (Internal and External write) to see what works, but it looks like in both cases, Android mobile device and standalone HMD, it will work to save these files to the device. This can remove the need to setup and use the HTTP Post option, if you do not want to/can't use the HTTP option (i.e., you are running a study where there is no internet access available).

Have you tried this out before?

jackbrookes commented 2 years ago

I havent tried this, but it would be easy to test if you want to try it out.

You can set the storagePath field to Application.persistentDataPath using a script https://github.com/immersivecognition/unity-experiment-framework/blob/master/Assets/UXF/Scripts/DataHandling/FileSaver.cs#L306

And then remove this line https://github.com/immersivecognition/unity-experiment-framework/blob/master/Assets/UXF/Scripts/DataHandling/FileSaver.cs#L348

thefirstfloor commented 2 years ago

I did actually change that for an APK build that runs on the Quest 2, and it works. Also I had to disable some pieces of UXF code regarding the DynamicDB, as it gave errors on the 'build check'.

A-Ivan commented 2 years ago

Thanks @jackbrookes , unfortunately I do not have an Oculus with me right now to test this but good to know what I would need to change in order to test it.

That's great to hear you were able to get this to work @thefirstfloor . Do you remember what option you chose for the "write permission", if it was "internal" or "external", in which the directory location the CSV files were saved to, or what you had to change in the codes for it to work?

Thank you. Ivan

thefirstfloor commented 2 years ago

Hi @A-Ivan

What I remember I did was making a copy of the windows filesaver script and changed a few things, under which using the persistantDataPath. I checked the project and write permission setting is set to 'external (SDcard)'. The logs are saved at `sdcard>android>data>com.[companyname].[projectname]>files> Also I did remove all scripts and references to the DynamoDB, as this gave conflicts building for Android.

Also, when running the APK for the first time, make sure to choose 'ALLOW' for disk access inside the Quest.

Hope this helps.

jackbrookes commented 2 years ago

I will see if I can get this up and running next week, as it doesn't seem too difficult.

A-Ivan commented 2 years ago

Hi @thefirstfloor ,

This is great and does help, thank you.

@jackbrookes , not sure if you already do something like this, but adding this code to your scripts may help, so that the step of changing the write permission to external is done automatically.

I also added some code to automatically setup Oculus Quest build (minimum Android API level, target Android API level, write permission to external, texture compression).

You just need to add this script, called "AutomaticallyConfigureSettings", to your Assets folder in Unity, I suggest a "Scripts" folder to make it more organized.

In the Unity Editor, a Menu option will appear, called "UXF", with the sub-options called "Android Setup For VFX Use" and "Oculus Setup For VFX Use", clicking on these options will automatically setup the settings for either Android (Android mobile devices) or Oculus Quest, respectively. Note, it takes around 10 seconds for the Unity Editor to update these settings (at least on my computer).

image

using UnityEngine;
using UnityEditor;

public class AutomaticallyConfigureSettings : MonoBehaviour
{
    [MenuItem("UXF/Android Setup For UXF Use")]
    private static void SetSettingsAndroid()
    {
        // Switch to Android build.
        EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);

        // If the current build target is Android, then set the write permission to external
        if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
        {
            // Changes Android write permission to external
            PlayerSettings.Android.forceSDCardPermission = true;

            // Sets the Texture Compression to Default (Don't override)
            EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.Generic;

            Debug.Log("Android settings set");
        }

        // If the build target was not set to Android (it may not be available on the system)
        else
        {
            Debug.Log("Android build was not set, check if it is available. If it isn't, add it to the Unity Editor version via the Unity Hub.");
        }
    }

    [MenuItem("UXF/Oculus Quest Setup For UXF Use")]
    private static void SetSettingsOculus()
    {
        // Switch to Android build.
        EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);        

       // If the current build target is Android, then set the write permission to external, and configure API levels and Texture compression
        if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
        {
            // Changes Android write permission to external
            PlayerSettings.Android.forceSDCardPermission = true;

            // Sets the Android API Level to 26
            PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel26;

            // Sets the Android API Level to Automatic (highest installed)
            PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;

            // Sets the Texture Compression to ASTC
            EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.ASTC;

            Debug.Log("Oculus settings set");
        }

        // If the build target was not set to Android (it may not be available on the system)
        else
        {
            Debug.Log("Android build was not set, check if it is available. If it isn't, add it to the Unity Editor version via the Unity Hub.");
        }
    }
}

I hope this helps.

jackbrookes commented 2 years ago

Nice! I will take a look soon.

jackbrookes commented 2 years ago

New release to address this, thanks for help & suggestions. If you spot anything out of place on the Wiki, or something isn't working, let me know.

https://github.com/immersivecognition/unity-experiment-framework/releases/tag/2.3.4

A-Ivan commented 2 years ago

Hi @jackbrookes ,

You're welcome, happy to help. The new release looks great, thanks for the mention on it.

Regarding Android, mobile devices, do you know the path which files are saved to? I would like to add that information to the wiki to make it clear for users.

On another note, I was looking at the compatibility on the Wiki page and also Unity's Persistent DataPath documentation and it looks like using the persistent DataPath (as was used for Android) would also work for iOS devices and WebGL.

Might be worth testing it on those as well since it would be a small change to the code, as it would then offer the save compatibility with more devices.

jackbrookes commented 2 years ago

Haven't tested on Android, and cant test on iOS

For WebGL local file saving I expect there is 0 people would ever need that option, a native app will be better in every way, so I didn't bother testing. Will keep in mind for the future though if there is a need.

A-Ivan commented 2 years ago

Make sense, I also don't expect anyone using WebGL to use the save feature, but it's good to know that it is possible if anyone is ever interested in it.

Regarding the above script I created for the Oculus Settings function, specifically this line PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel26; there may be an issue if the person doesn't have the Android API Level 26 installed on the computer, there may need to be a try and catch added with a log to let the person know the setup didn't work because of their lack of this specific version, not of Android as a whole.

This shouldn't be an issue for those using Unity 2019.3+ (this is the oldest 2019 version I tested on, I know it doesn't work for 2018.x), as when you install for 2019.3+ it installs multiple SDK and NDK automatically so multiple Android API versions are installed, including version 26.