How can you save both internally and externally

I have looked through the forum and I haven’t found both just one or the other.
SO my question is, is it possible to access both internal and external storage (like on eclipse) or do I need to write a java plugin that passes the external storage path back to me.

I know of Application.persistantDataPath which depending on if you have write_external allowed in manifest or not writes to external storage (enabled) and internal storage(disabled).

So is it possible in unity to download to external and store in internal storage or is that something I have to use plugins for.

You can get your Android apps internal path directly from Unity without a plugin, even with permission WRITE_EXTERNAL_STORAGE. Similar code can be used to get any other path.

I spent 2 days on this :P. First I made my own Java plugin, but as I do not like to extend my current Activity or Application I ran into problems. Finally I pieced together how to do it directly from Unity with the following code:

string path = "";
#if UNITY_ANDROID && !UNITY_EDITOR
try {
         IntPtr obj_context = AndroidJNI.FindClass("android/content/ContextWrapper");
         IntPtr method_getFilesDir = AndroidJNIHelper.GetMethodID(obj_context, "getFilesDir", "()Ljava/io/File;");

         using (AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
            using (AndroidJavaObject obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
               IntPtr file = AndroidJNI.CallObjectMethod(obj_Activity.GetRawObject(), method_getFilesDir, new jvalue[0]);
               IntPtr obj_file = AndroidJNI.FindClass("java/io/File");
               IntPtr method_getAbsolutePath = AndroidJNIHelper.GetMethodID(obj_file, "getAbsolutePath", "()Ljava/lang/String;");   
                                
               path = AndroidJNI.CallStringMethod(file, method_getAbsolutePath, new jvalue[0]);                    

               if(path != null) {
                  Debug.Log("Got internal path: " + path);
               }
               else {
                  Debug.Log("Using fallback path");
                  path = "/data/data/*** YOUR PACKAGE NAME ***/files";
               }
            }
         }
      }
      catch(Exception e) {
         Debug.Log(e.ToString());
      }
#else
      path = Application.persistentDataPath;
#endif

I hope it will help some devs without Java knowledge (like myself :)) to save some time and headache.

You can more easily call the native API to get getFilesDir() with this code:

	string path;

	using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
	{
		using (AndroidJavaObject currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity"))
		{
			path = currentActivity.Call<AndroidJavaObject>("getFilesDir").Call<string>("getCanonicalPath");
		}
	}

If you like, you can fall back on Application.persistentDataPath upon failure, as another poster wrote.

It is possible by using plugins. Return internal storage directory and return external storage directory using the plugin and do all writes either from inside the android plugin or for more flexibly using
System.IO” class.
As noted in my Question Application.persistantDataPath always points to external storage if allowed and internal storage otherwise.

It’s actually possible without plugins (at least for Android). Possible doesn’t mean easy or robust.

The point is depending on your project settings you have either have access to the sdcard or not. You always have access to the internal storage. However Application.persistantDataPath returns the internal path when you don’t have external permissions otherwise the external. That means you can’t determine the internal path with the API Unity provides.

I tried accessing a file in my internal storage while i have enabled external permissions with a hardcoded path and it works fine. The only real problem is that you can’t determine the internal datapath automatically (at least i haven’t found a way).

I had the problem that my app allows me to create “content” and you can save it to the persistant folder. I created something while i only had internal access, so the file is stored in the internal storage. Now i want to compy the file to my PC but i can’t access the internal storage outside my app (i haven’t rooted my tablet).

I just thought, well lets enable external permissions and copy it over, but as mentioned above you can’t determine the internal path anymore.

In my case i knew the path. So i just hardcoded it and rebuilt my app. I’m not sure if you can rely on this scheme:

"/data/data/**com.your.BundleIdentifer**/files"

but on my android it works fine. This of course won’t work on iOS :wink: