in my application i create a temporary file this way
File tmp = File.createTempFile("TEST_", null, getFilesDir());
this resolves in a file that toURI()zed corrisponds to something like
/data/data/it.lorenzoff.test/files/TEST_XXX.tmp
In certain circumstances, i'd like to move this file permanently on sdcard but this code
dest = new File("/sdcard/permanentFile");
tmp.renameTo(dest);
never works.
I'm already using these permissions
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
but renameTo continue returning false.
What i'm doing wrong?
Thanks in advance
L.
The explanation can be found in documentation for File:
Many failures are possible. Some of the more likely failures include:
Write permission is required on the directories containing both the source and destination paths.
Search permission is required for all parents of both paths.
Both paths [must] be on the same mount point. On Android, applications are most likely to hit this restriction when attempting to copy between internal storage and an SD card.
In this case source and target file paths point to different mount points (these two mount points even have different file system). You only option is to manually copy the file to sdcard and then delete the file from internal storage.
Related
I have an issue with writing to sd card on my android 4.4 device. I'm writing an application that gets path to its directory on sd card using the getExternalFilesDirs() method. But when I try to store data in the directory I get an error:
EACCES (Permisson denied)
The applications directories in Android/data/ in both internal memory and on the sd card are owned by different linux users. Any other application on my device works fine. The application works on another device with that sd card.
You need to add this permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
i think you have missplaced this line.
Double check this line
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
where you have put this line?
this line should be outside of <application/> scope
like this
<manifest>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
...
<application>
...
<activity>
...
</activity>
</application>
</manifest>
For getExternalFilesDirs to return the path of the sdcard, the OEM must have set the SECONDARY_STORAGE environment variable in the device specific init.rc file as mentioned here: https://source.android.com/devices/storage/config-example.html
Look at the source of getExternalFilesDirs here: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/ContextImpl.java#1039
The value is obtained from Environment.buildExternalStorageAppFilesDirs. Look at that source here: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/Environment.java#206
The value is dependent on mExternalDirsForApp, which in turn is populated by reading the contents of SECONDARY_STORAGE variable: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/Environment.java#136
As you can see, if the SECONDARY_STORAGE variable is not set, the sdcard path will not be returned. You can cross-check this by going to adb shell and looking at the output of echo $SECONDARY_STORAGE
use getExternalFilesDir()
It returns the path to files folder inside Android/data/data/your_package/ on your secondary storage SD card. It is used to store any required files for your app (e.g. images downloaded from web or cache files). Once the app is uninstalled, any data stored in this folder is gone too.
This is where you can write file in secondary storage ie(your micro sdcard)
if you want to write outside or the root of the secondary storage you have to use Storage access framework .
Our application has a large amount of C++ code that creates its own log file as a simple .txt file. It's a circular buffer so it's limited to the size we specify. It's also placed in whatever directory we specify.
The problem is where to place the file so it can be accessed with ADB or a similar tool (without rooting). If we didn't care about the publicly-accessible part, it seems this would be the logical place to locate the file:
packageManager.getApplicationInfo(applicationContext.getPackageName().dataDir
But since we want to be able to pull the file from a customer's phone for post-mortem debugging, I've tried placing it here:
"/mnt/sdcard/Android/data"
This is problematic for several reasons, but I'm not sure if they're all true. (1) It's hard-coded; (2) Not all Android devices have external storage, although I thought they still mapped it to internal storage? (3) The location isn't app-specific so it won't get uninstalled along with the app. And (4) Runtime permission for EXTERNAL_STORAGE is required.
I believe 1-3 can be solved with something like:
android.content.Context.getExternalFilesDir()
Or is there a better choice?
But I don't believe this will get around #4, which is unfortunate as I'd prefer not to "scare" users with more permission requests.
What's the best way to handle this?
Make sure that you have the permissions to read and write the External SD using this code in the Manifest File:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
And then this string will give you the wanted path:
String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + getContext().getPackageName();
/storage/emulated/0/Android/data/com.exemple.yourapp/
Because of apk maximum size 50MB, i decided to make apk expansion file. I know that I can get any file (inputstream) from this package but I am working in LibGDX, and this doesn't have option to load textures/music from inputstream.
So, I must extract files, load texture/music and then I can delete file.
I think that i need max 50MB space and i have two options:
UNZIP TO:
ContextWrapper.getFilesDir() - it returns internal file, but I can't know how many files can I unzip there, because this storage is shared with all apps.
getExternalStorageDirectory() - it returns external file, but according to website (developer.android.com) "This directory may not currently be accessible"
Which directory will be best to unpack and always avaliable?
If, as you tell us, here there are big quantities of data, so in order to improve user experience (not all phones have huge memory and using internal storage may cause your app is uninstalled) you should use external storage.
You have to care about couple of things:
Add permissions to read / write
Check file availability starting app
Adding permissions:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
Checking file availability
And starting the app, be careful and check if external storage is available, and show message otherwise in order to avoid exceptions:
Caution: External storage can become unavailable if the user mounts the external storage on a computer or removes the media, and there's no security enforced upon files you save to the external storage. All applications can read and write files placed on the external storage and the user can remove them.
Use Context.getCacheDir() to get access to a private directory where you can extract files. This should be considered as a cache directory, so you should check for the file on startup and extract it again if it is missing.
This method doesn't require any additional permissions and is more secure. Also, the directory is guaranteed to exist by the Android APIs.
Is it possible to programmatically copy a file into, or create a symbolic link in the /data/data/application_package/lib directory?
When trying to write to the lib directory, I always get permission denied error.
I have defined
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You cannot write to lib/, however you do not need to.
You can write to any non-reserved location within your your application's private storage area, and you can load a native library from any file on the device for which you have read and execute permission, using System.load() with the full pathname, rather than System.loadLibrary() with the short library name.
The external storage (sdcard) is mounted with a non-executable flag, but a file in your private storage directory would be a workable solution. Just be sure to make it only writable by your application, so that something else can't change it behind your back (it is because you cannot protect external storage files from such modification that the external storage is non-executable)
if you want load so file ,you can use system.load(); you can copy so to data/package name/libs
and use system.load() to load so
I am new to android. I am trying to download a file from server and save the file in a particular path. The application is working fine. However I am not able to find the path of the downloaded file. In the code I have given as
File output = new File("/data/data/com.test.firstApp/", fileName);
Where can i find the file on my system?
Don't use hard coded file paths. The framework will give you the base path of the area you want to save files to.
For the SD card, use Environment.getExternalStorageDirectory()
For local files, use Context.getFilesDir() (or Context.openFileOutput(String name, int mode), etc)
For local cache, use Context.getCacheDir()
Adding to Rich's answer, in the likely event you will end up writing to external storage make sure to include this permission in the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Check this page http://developer.android.com/guide/topics/data/data-storage.html
You can find there many methods how to save file. What is more you can also read something about good practices.
Cheers