- Home /
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.
Answer by Raigex · Jul 18, 2012 at 04:17 PM
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.
Answer by Clas · Jan 17, 2016 at 05:28 PM
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.
Answer by piojo9 · Mar 18, 2016 at 12:51 PM
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.
This question is almost 4 years old, please stop grave digging.
Answer by Bunny83 · Dec 21, 2012 at 03:12 PM
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 ;)
Thanks for the info but I do not like hard-coding paths because I never know if what they point to exists on the targeted platform. EG: If i were to use external path for Samsung it would be: [code]/mnt/sdcard/[/code]
but I know of some other companies (cant remember their names atm) that use [code]/external/sdcard/ [/code]
or something similar. So there is stuff i will hard-code but most things no I prefer to get from the system or have the user select it. Although I probably don't have to worry about this in android system I would rather be safe than sorry.
I totally agree. I hate hardcoded stuff as well ;) It's actually a lack of Unity not providing this path to you. Since you can access both, external and internal it should be possible to get the path to the internal storage as well.
The sdcard is usually mounted with several alias names. On my asus Nexus7 the sdcard is mounted as:
/sdcard
/mnt/sdcard
/storage/sdcard0
/storage/emulated/0
/storage/emulated/legacy
At least these are the only ones i've found (as i said i haven't rooted my device)
I've read somewhere that google requires the sdcard at /mnt/sdcard
Anyway what we actually need is a seperate property in the Application class for each path. The internal and external. Properties are nice, but i hate when they change their behaviour when you change a setting elsewhere. Another negative example of global state ;)
As final note: I would never use such a hardcoded path in a game / app when i publish it to the playstore / appstore.
Although I think you can get the local storage path and the external storage path using JNI calls without any plugins. Just using the standard
[CODE] JavaClassObject tmpObject = new JavaClassObject("unityplayeractivity") [/CODE]
Then call regular api's from android (eg getExternalDirectory()) I just remembered the above as technically that is not a plugin because Unity3d does give you access to the Activity that it uses.
@Raigex: Thanks for this info. I have to play with that when I'm back at work. However a built in solution which works for all platforms would be the preferred way.
Your answer
Follow this Question
Related Questions
Using AndroidJavaClass in a java Unity3d plugin 0 Answers
AndroidJavaClass. Call returns null ptr. 1 Answer
Unity Plugin or Unity in Android SDK. 0 Answers
Uncomiled Java code Android 0 Answers
Android Java Plugin For Unity Object with null ptr! 0 Answers