I’m in the process of implementing Android runtime permissions in the game we’re developing because it targets Android SDK 23.
We’re requesting the WRITE_EXTERNAL_STORAGE permission because we’re taking a screenshot and share that to any app we want. So the user presses the share button, we’re showing the request permissions dialog and the permission is set. This all works fine. However, after setting the permission the Application.persistentDataPath still points to the internal storage, instead of the external storage. After we restart the app, it will point to the external storage, as expected.
Restarting the app is undesirable as you can understand. Is there a solution so restarting the app isn’t necessary? Or in general, how does everyone handle situations where setting a permission requires an app restart?
Ok, so I realise you have probably come up with a solution yourselves by now but I thought I’d post an answer for anyone else searching for a solution to this.
The latest version of Unity still showed the same behaviour: the path you get back from Application.persistentDataPath changes after a restart, following the WRITE_EXTERNAL_STORAGE permission being granted. So, if you have obb file download code, for example, and request that permission runtime (to meet Android M [6.0] requirements) then save a file, the next time the user launches your app persistentDataPath will have changed and you will not find the file you saved previously.
The solution I came up with was to add a function to the plugin I wrote to deal with the permissions flow. The function returns the external directory, appends the rest of the path and creates the directory if it doesn’t already exist, because this is something Unity takes care of for you as part of Application.persistentDataPath. From inside Unity, as soon as I’ve detected that the permission has been granted I use this function to cache the external location for save files, then use this instead of persistentDataPath.
Java:
String result = "";
File file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.exists())
{
if (file.mkdirs())
{
result = file.getPath();
}
}
else
{
result = file.getPath();
}
Path is “/Android/data/[Your Bundle Identifier]/files”, there is probably a way to grab the identifier within Java but I’m just passing it in from C# using Application.bundleIdentifier. As soon as permission is granted, call this and cache the result. If it doesn’t exist and fails to create the directly then result is empty and you have to deal with that.