My friend and I are attempting to create an app that saves files to a device. We used this code to write to an external SD card, and it works great on his Droid X and Samsung Galaxy Tab.
Get the path to the SD card:
private static final File ROOT = Environment.getExternalStorageDirectory();
Create the folder path and files:
FileWriter fw = new FileWriter(ROOT + "/test/" + "time_frames.txt");
we are using document factory to create the documents
so you can see that we create the path then try to save to that path that was just created
File file = new File(ROOT + "/test/" + "time_frames.txt");
When I run it on my Nexus S (which does NOT have a SD card) is having trouble with the exact same code.
private static final File ROOTtest = Environment.getExternalStorageDirectory();
this returns /data
private static final File ROOT = Environment.getRootDirectory();
this returns /mnt/sdcard
private static final File intData = Environment.getDataDirectory();
this returns /system
my question is which one of these will work for devices that have SD cards and no SD cards? I have tried a lot, but trying all this stuff has really confused me. Thanks in advance
Environment.getExternalStorageDirectory() returns the path to external storage, it should work on all devices. Whether they have an actual SD card doesn't matter, and your code shouldn't care either. You need to make sure that external storage is available before you try to use it though, because it could be unmounted at any time.
Related
Can I somehow find out which storages are currently available WITHOUT starting the document picker and let the user select a directory?
I want to display all storage roots like following:
File mainRoot = Environment.getExternalStorageDirectory();
// any root path that is available => I don't need access rights here, I just want to know which storages are available and "mounted"
DocumentFile sdCardRoot = ???;
DocumentFile usbCardRoot = ???;
DocumentFile gDriveRoot = ???;
Why?
Actually I want to know if an sd card is available before telling the user that he needs to select the sd cards root directory via the document picker...
So I want following:
check if an sd card is available
if not, do nothing
if an sd card is available, tell the user that my app needs permissions to read the sd card and ask the user to select the sd cards root directory via the storage access framework
The same I want to do for the usb stick, but there I know how to do it (there broadcast receivers exist to get notified when an usb stick is added and I can check if on is already connected as well)
You can do the following:
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
//Ask for the permission
File externalRoot = Environment.getExternalStorageDirectory(); //gives the root directory of External storage
}
Edit:
Go to your .android\avd\"avd_name".avd folder , and open config.ini ; Make sure you have ,
hw.sdCard=yes
sdcard.size=100M
sdcard.path=[Path to ".android" directory]/.android/avd/Nexus_5X_API_23.avd/sdcard.img
Here's the thing I came up until now:
File root = Environment.getExternalStorageDirectory();
DocumentFile sdCardRoot = null;
File[] fs = context.getExternalFilesDirs(null);
// at index 0 you have the internal storage and at index 1 the real external...
if (fs != null && fs.length >= 2)
{
String mainPath = fs[0].getAbsolutePath();
String subPath = mainPath.replace(root.getFolder().getAbsolutePath(), "");
String pathSDCard = fs[1].getAbsolutePath().replace(subPath, "");
String relTreePath = pathSDCard.substring(1).replace("storage", "tree") + "%3A";
// this string is defined com.android.externalstorage.ExternalStorageProvider... but seems to not be accessable in code...
Uri treeUri = Uri.withAppendedPath(Uri.parse("content://com.android.externalstorage.documents"), relTreePath);
sdCardRoot = DocumentFile.fromTreeUri(context, treeUri);
}
// now you have the internal storage root in "root" - this path is directly readable via the `File` class
// and the sd card's root is in sdCardRoot and can be managed via the `DocumentFile` class...
I'd like to read all files located in internal storage and filter them to find those *.mp3 ones. With external storage I could just use:
final String MEDIA_PATH = Environment.getExternalStorageDirectory().getPath();
to get the path, but I cannot find the way to do it for internal memory (for instance to get to Music folder of the phone). Is there a way to do it?
Are you aware of getFilesDir() method?
http://developer.android.com/training/basics/data-storage/files.html
You can use Context.getFilesDir() method to get the path to the internal storage.
Like : File file = new File(getFilesDir() + "/" + name);
I'm trying to write a file to my phone.
I used Environment.getDataDirectory() to know the internal storage's path and Environment.getExternamStorageDirectory() to know the external storage's path.
But when I use Environment.getExternalStorageDirectory() as path, the file is created in internal storage. And when I use Environment.GetDataStorage() as the path, the file is not created. (I am not sure, but I can't find it in the explorer app, at least.)
I think my phone's internal storage is perceived as external storage.(In my case, it has 32 GB amount of storage)
I want to know removable storage(e.g. micro SD card) path. What should I do?
From the official documentation for getExternalStorageDirectory()
Don't be confused by the word "external" here. This directory
can better be thought as media/shared storage. It is a filesystem that
can hold a relatively large amount of data and that is shared across
all applications (does not enforce permissions). Traditionally this is
an SD card, but it may also be implemented as built-in storage in a
device that is distinct from the protected internal storage and can be
mounted as a filesystem on a computer.
So, it can be different from built-in storage in a device.
For your case, you could use getExternalStoragePublicDirectory(java.lang.String)
This is where the user will typically place and manage their own
files
The path here should be one of DIRECTORY_MUSIC, DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS,
DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, or
DIRECTORY_DCIM. May not be null.
Or if you want your data to be deleted whenever the user uninstalls your app, you could use getExternalFilesDir().
As these files are internal to the applications, and not typically visible to the user as media.
Also there are some differences between getFilesDir() and getExternalFilesDir()
External files are not always available: they will disappear if the user mounts the external storage on a computer or removes it. See the APIs on environment for information in the storage state.
There is no security enforced with these files. For example, any application holding WRITE_EXTERNAL_STORAGE can write to these files.
Try this...
static String storagestate = Environment.getExternalStorageState();
private static FileOutputStream outStream;
private static File imageFilepath;
public static String saveImage(Bitmap bitmap) {
File folder = null;
// Check for SD card
if (storagestate.equals(Environment.MEDIA_MOUNTED)) {
folder = new File(Environment.getExternalStorageDirectory(),
"*YourStorageNameInDevice");
if (!folder.exists()) {
folder.mkdir();
}
outStream = null;
String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date());
// Getting filepath
imageFilepath = new File(folder.getPath() + File.separator
+ timestamp + ".PNG");
try {
outStream = new FileOutputStream(imageFilepath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return imageFilepath.getAbsolutePath();
}
}
I have phone (B15 CAT) with a sd card slot. When i insert a sdcard in this phone and asking for the external storage directory with :
Environment.getExternalStorageDirectory()
it always return an space on sdcard0 which is the internal memory. This memory is too small for my need.
By listing /mnt i found a mount point named /sdcard2 which is the "real" scard.
Unfortunately sdcard2 doesn't seems to be a standard and some other brand will use some other name...
Knowing that getExternalStorageDirectory() seems working as expected on phone with no sdcard slot , like nexus 4, how should i handle external storage to be sure to write on the sdcard (big space available) and not on internal memory ?
I have tried something like this :
File mnt = new File("/mnt");
File[] liste = mnt.listFiles();
boolean hassd2 = false;
for(File mount : liste) {
if(folder.getName().equals("sdcard2") {
hassd2 = true;
break;
}
}
String path = "";
if(hassd2) {
path = "/sdcard2/my/folder/"
} else {
File p = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/folder/");
path = p.toString();
}
It's working but only with this specific phone and others one with no sdcard slot ...
I also had the problem with the build in functions of Android in case of multiple 'external' storages mounted. I parsed the mounted directories directly from the f_stab file.
This link should give you the code you needed.
After having the mount points you could try to calculate the available space in order to decide if it is enough for your operation.
I am writing an Android mediaPlayer app, so I want to scan through all files on the entire phone (i.e. sdcard and phone memory). I can read from the sdcard, but not the root of it. That is, I can just read from the path /sdcard/[folder]/ and it works fine, but if I go to /sdcard/ the app crashes. How can I access all the files on the sdcard, as well as the files on the phone itself?
Never use the /sdcard/ path. it is not guaranteed to work all the time.
Use below code to get the path to sdcard directory.
File root = Environment.getExternalStorageDirectory();
String rootPath= root.getPath();
From rootPath location, you can build the path to any file on the SD Card. For example if there is an image at /DCIM/Camera/a.jpg, then absolute path would be rootPath + "/DCIM/Camera/a.jpg".
However to list all files in the SDCard, you can use the below code
String listOfFileNames[] = root.list(YOUR_FILTER);
listOfFileNames will have names of all the files that are present in the SD Card and pass the criteria set by filter.
Suppose you want to list mp3 files only, then pass the below filter class name to list() function.
FilenameFilter mp3Filter = new FilenameFilter() {
File f;
public boolean accept(File dir, String name) {
if(name.endsWith(".mp3")){
return true;
}
f = new File(dir.getAbsolutePath()+"/"+name);
return f.isDirectory();
}
};
Shash