I see a bunch of other people asking this same question, but none of the solutions posted helped me.
I'm trying to write a (binary) file to external storage from my Android app.
I put <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> into my manifest, but I still can't manage to create any files. The code I'm using to create files is
File folder = new File(Environment.getExternalStorageDirectory(), SAVE_DIRECTORY);
File toWrite = new File(folder, "save.bin");
if(!toWrite.exists()){
try {
if(!folder.mkdirs())
Log.e("Save", "Failed to create directories for save file!");
toWrite.createNewFile();
} catch (IOException e) {
Log.e("Save", "Failed to create save file! " + e.getMessage());
}
}
The call to mkdirs() fails, and the createNewFile() throws the IOException (ENOENT, because the directory doesn't exist)
Anybody know what's up? I've even tried rebooting my device. I'm on API level 8 on a Nexus 7, if it makes any difference.
first you should check the ExternalStorageState
public static boolean isSDCARDAvailable(){
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
if this method isSDCARDAvailable return true, then use your code
add the permissions:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
The documentation says that starting in API level 19, WRITE_EXTERNAL_STORAGE is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir(). However if you don't want to write files there and instead want to write files to getExternalStorageDirectory(), under API 23 or higher you have to request permission at run time using requestPermissions(). Once I did that I was able to create a directory in getExternalStorageDirectory().
I was suffering this issue as well and everything was properly configured in my app, i.e., I had the read and write permissions for external storage.
My problem was in the way I was creating the path to store my files:
private val LOG_BASE_PATH = Environment.getExternalStorageDirectory().path + "myFolder"
Note that it is necessary to include the "/" as follows:
private val LOG_BASE_PATH = Environment.getExternalStorageDirectory().path + "/myFolder/"
Without this, you won't be able to create the folder. Android won't fail, so you might think that there are issues with your phone configuration or app permissions.
Ideally, this helps somebody to save some precious time.
Related
I have a question.
How can I save a file from network to the external storage of the android device, with
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
being depricated?
My Code:
private void download(Context mContext) throws IOException {
String requestUrl = "http://someresource/..."
URL url = new URL(requestUrl);
InputStream in = url.openStream();
mContext.getFilesDir();
URI uri = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC).toURI();
Files.copy(in, Paths.get(uri.getPath() + "/_test.mp3"), StandardCopyOption.REPLACE_EXISTING);
in.close();
System.out.println("finished!");
}
I get the error W/System.err: java.nio.file.AccessDeniedException: /storage/emulated/0/Music/_test.mp3
I also read the article https://developer.android.com/training/data-storage/shared/media#java
but I suppose this is meant to be more of a guideline to tamper with existing media files, like searching or editing file tags etc. and not simply saving a file in the media directory.
Update:
My app needs to fulfill two tasks. I want to save an mp3 file to the above mentioned directory and also read files from this directory.
Below Q: Working with Environment.getExternalStorageDirectory().getPath()+"/Music"; returns the Music-Folder on the built-in flash memory of the Android device.
In that manner I want to know how to get the Music-Folder on the SD-Card of the Android device (when its plugged in).
Since Q: the above Method returns a directory, which is no longer directly accessible to apps. The tasks I want to fulfil are the same as the ones mentioned above.
As #blackapps supposed, using the MediaStore Class is in Q preferable. But how exactly do I do that?
For android 10 and 11 add this line to your <application> element in the android manifest file.
hope it will work:
<application
android:requestLegacyExternalStorage="true"
Now I'm making some version of File Manager in Andoid.
My permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
When I write new file to /mnt/sdcard (External Stroage) everything is allright.
But When i write new file to /mnt/sdcard2 (internal storage) I get IOException like
open failed: EACCES (Permission denied)
My full code:
try {
File existingFile = new File(path);
File newFile = new File(newPath);
if (!newFile.exists()) {
if (!isFolder)
{
newFile.createNewFile();
}
}
if (isFolder) {
FileUtils.copyDirectory(existingFile, newFile);
}
else
{
FileUtils.copyFile(existingFile, newFile);
}
} catch (IOException e) {
result = 1;
}
When i test my application I use real device.
My Path is like '/mnt/sdcard/Music/blabla' and so on
My Path is like '/mnt/sdcard/Music/blabla'
Do not use hardcoded paths as these may (and will) differ depending on device model or can even OS version. You got methods in Environment class to get you root folder of external storage and you should use it like getExternalStorageDirectory()
EDIT
. I need to get folder that contents folder like Music, DCIM, Download, but in Inner Storage of Smartphone
You cannot have "private" DCIM, Downloads really if you want to use system features like DownloadManager or external Camera app, because these apps will simply not be able to write to your private storage. So you either download/take photo yourself - then you can save the file whenever you want, or you use what is it now available, with all the pros and cons.
Name "external"/"internal" is a bit misleading nowadays, so do not take it too literally.
I'm trying to rename a file to add it extension. I'm detecting the type of the file, and want to append the extension to the file. It all works well, but I have a Sony Xperia Z2 for testing, and something weird happens. In other devices and emulators, works like a charm, but in this one... it's impossible.
It always return false, despite it has write permission in the parent folder, it's the same folder, and it only appends a ".jpg" or ".png" or something like that. As the File.renameTo function doesn't gives any error, just throw false, I can't know for sure if it's only me... but I start to believe it's something about how it manage the internal/external storage. The internal storage is actually sdcard0, and the external is sdcard1. Some apps, like ES File Manager, ask about where the root of my sdcard is, so it can rename, move, or copy files in my sdcard. Airdroid ask me to do the same thing. Why is that happening? How can I fix this?
Oh, and I have the pertinent permissions in the manifest, I've been searching a lot for a fix for this thing... and doesn't works in internal storage, as well. I'm totally lost. Here's the function I use to rename the file, if it helps someone... but I think it's a problem of the "internal sdcard" devices, or something.
private void setFixed(File f, String ext){
File parent = f.getParentFile();
try {
String name = f.getName();
String toName = (name+"."+ext).replace(" ", "");
//Lines that I added just to test. I saw before I call this function that the parent has write permission.
//Log.i("Pre", parent.getCanonicalPath()+name);
//Log.i("Post", parent.getCanonicalPath()+toName);
//File of = new File(parent.getCanonicalPath()+name);
//File nf = new File(parent.getCanonicalPath()+toName);
//Log.i("Converted", String.valueOf(of.renameTo(nf)));
File f1 = new File(parent.getAbsolutePath()+toName);
boolean success = f.renameTo(f1);
Log.i("File renamed?", String.valueOf(success));
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks a lot!
Please read the documentation for renameTo(File) (click on the method and press ctrl + Q).
Renames this file to newPath. This operation is supported for both
files and directories. 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 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. Note that this method does not throw IOException on
failure. Callers must check the return value.
As you can see, the search permission is required. Ensure that you add this to the manifest.
You also need to change
File f1 = new File(parent.getAbsolutePath()+toName);
to
File f1 = new File(parent.getAbsolutePath().toString()+ "/" +toName);
I am trying to output numeric values one at a time from an Android application I'm writing, but I'm having a lot of trouble figuring out what's going on. Tried looking for answers, but only confused further. This strikes me as something that should be relatively straightforward, so I feel pretty dumb for being so confused by it.
String directory = Environment.getExternalStorageDirectory().getAbsolutePath();
When I log the directory I get a path "/storage/emulated/0" Where is that? Is that different from what I would get if I wasn't debugging?
Then I have:
String fileName = directory + "/Android/data/com.sample.app/files/test.txt"
File myFile = new File(fileName);
FileOutputStream fos;
try {
fos = new FileOutputStream(myFile);
String text = "Test text\n";
fos.write(text.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
I tried using the Windows Explorer to figure out where stuff is saving and/or is supposed to be saved but I don't see it. This is code based on the information in this link: http://developer.android.com/guide/topics/data/data-storage.html, but I really don't understand where the "/storage/emulated/0" comes from and how I either access that location or get rid of it.
EDIT: Right now I just want to save all the numbers so I can check what is coming out. The numbers are recorded from the audio input.
EDIT: Using the ASTRO File app on my phone revealed the files
Didn't need the "/Android/data/com.sample.app/files/" part, don't know how to use that.
Path wrong?
/storage/emulated/0 is a path at your filesystem which represents the external storage. At earlier versions of Android we often had /mnt/sdcard/ or something similiar, but many devices today don't have a sdcard but emulate an external storage anyway.
To view the files at your Android filesystem I'd recommend to use an App like Astro File Manager. Just take a look if your file has been written.
One possible mistake could be, that you you are missing a File.separator between your directory and the local path.
String fileName = directory + File.seperator + "Android/data/com.sample.app/file/test.txt"
Directory created?
You should also make sure, that the directory exists by calling myDir.mkDirs();, where myDir is the complete path without the filename.
To create the directory you can use the following code
directory = directory + "/Android/data/com.sample.app/file/test.txt"
new File(directory).mkDirs();
Uses-Permission in Manifest?
Last error source could be, that you might miss the external storage permission, you need a
You also need to make sure, that you require the permission for writing to the external storage. Take a look for <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in your Android Manifest file.
I have eclipse plugin jface application.
A thread writes file via BufferedWriter.
After writing is done I close the buffer after that I try to rename the file.
But sometimes file is not renamed!
I tried to add some Thread.Sleep(BIG_NUMBER) between couple of retries this didn't help.
It looks like the file getting some kind of lock. (when I kill the jvm I can rename the file).
Is there something I can do?
OS: Windows XP, windows 7
JAVA version: 1.5
File.RenameTo() is platform dependent and relies on a few conditions to be met in order to succesfully rename a file, a better alternative is using
Path source = currentFile.toPath();
try {
Files.move(source, source.resolveSibling(formattedName));
} catch (IOException e) {
e.printStackTrace();
}
Read more here.
From the javadocs:
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
Note that the Files class defines the move method to move or rename a file in a platform independent manner.
For the File.renameTo() to work,The file will need to be somehow writable by external applications.
You can also do something like below:
File o=new File("oldFile.txt");
File n=new File("newFile.txt");
n.delete();
o.renameTo(n);
n.delete() : We need to delete the file(new.txt) if exists.
o.rename(n) : so that the file(old.txt) is renamed as new.txt
How to find out why renameTo() failed?
Reliable File.renameTo() alternative on Windows?
http://www.bigsoft.co.uk/blog/index.php/2010/02/02/file-renameto-always-fails-on-windows
We have had issues under Windows 7 with UAC and unexpected file permissions. File#canWrite will return true even though any attempts to perform file I/O will fail.
Make sure the file you are trying to rename actually exists
Make sure that the location you are attempting to write the file (or rename the file) to is accessible. We write a simple text file to the location, check to see if it exists and that it's contents is correct (we're paranoid) before we attempt any further I/O.
This is working fine for me. Rename is done using two steps but don't forget to set permissions in manifest.xml with:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
public boolean RenameFile(String from, String to) {
to.replace(" ", ""); // clear all spaces within file name
File oldfile = new File(from);
File newfile = new File(to);
File tempfile = new File(to + ".tmp"); // add extension .tmp
oldfile.renameTo(tempfile);
return (tempfile.renameTo(newfile));
}