I'm currently using the below code to create subfolder in MicroSD on Lollipop using SAF
String[] folders = fullFolderName.replaceFirst(UriFolder + "/", "").split("/");
//fullFolderName is a String which represents full path folder to be created
//Here fullFolderName = /storage/MicroSD/MyPictures/Wallpapers
///storage/MicroSD/MyPictures/ already exists
//Wallpapers is the folder to be created
//UriFolder is String and contains /storage/MicroSD
//folders[] will have folders[0]="MyPictures" folders[1]="Wallpapers"
DocumentFile Directory = DocumentFile.fromTreeUri(context, Uri.parse(treeUri));
//treeUri is the uri pointing to /storage/MicroSD
//treeUri is a Uri converted to String and Stored so it needs to parsed back to Uri
DocumentFile tempDirectory = Directory;
//below loop will iterate and find the MyPictures or the parent
//directory under which new folder needs to be created
for(int i=0; i < folders.length-1; i++)
{
for(DocumentFile dir : Directory.listFiles())
{
if(dir.getName() != null && dir.isDirectory())
{
if (dir.getName().equals(folders[i]))
{
tempDirectory = dir;
break;
}
}
}
Directory = tempDirectory;
}
Directory.createDirectory(folders[folders.length-1]);
The above code works fine and creates subdirectory but it takes ~5 Secs to create the folder. I'm new to SAF so is this the only way to locate subdirectories or is there any other efficient way to create subdirectories?
On internal storage I will use
new File(fullFolderName).mkdir();
Which will create folder in a fraction of second.
Here is a bit efficient way to create
public static boolean createFolderUsingUri(String fullFolderName,String treeUri,
String UriFolder,Context ctx)
{
String[] folders = fullFolderName.replaceFirst(UriFolder + "/", "").split("/");
//fullFolderName is a String which represents full path folder to be created
//Example: fullFolderName = /storage/MicroSD/MyPictures/Wallpapers
//The path /storage/MicroSD/MyPictures/ already exists
//Wallpapers is the folder to be created
//UriFolder is String and contains string like /storage/MicroSD
//folders[] will have folders[0]="MyPictures" folders[1]="Wallpapers"
//treeUri string representation of Uri /storage/MicroSD
//Ex: treeUri content://uritotheMicroSdorSomepath.A33%0A
DocumentFile Directory = DocumentFile.fromTreeUri(ctx, Uri.parse(treeUri));
for(int i=0; i < folders.length-1; i++)
{
Directory=Directory.findFile(folders[i]);
}
Directory.createDirectory(folders[folders.length-1]);
return true;
}
The method described in question took ~5 Secs, whereas this method takes ~ 3 Secs. On CM file manage the folder creation on same path took ~4 Secs so this is comparatively faster method. Yet searching more faster way which will take < 1 Sec
Related
In android I am able to get my phone's removable external storage by use of:
for (File f : context.getExternalFilesDirs("/"))
if (Environment.isExternalStorageRemovable(f))
Log.println(Log.DEBUG, "#", f.getAbsolutePath());
However, this returns /storage/8E6A-06FF/Android/data/test.application/files which isn't what I want as I simply want the removable's root path /storage/8E6A-06FF/. How can I can get the root path of my phone's removable storage?
You can try this one it is works perfectly for me.It works like a charm with all Os's version.I didn't found any issue so far with this function.
public static String getSDPath() {
String filepath = "";
String[] strPath = {"/storage/sdcard1", "/storage/extsdcard",
"/storage/sdcard0/external_sdcard", "/mnt/extsdcard",
"/mnt/sdcard/external_sd", "/mnt/external_sd",
"/mnt/media_rw/sdcard1", "/removable/microsd", "/mnt/emmc",
"/storage/external_SD", "/storage/ext_sd",
"/storage/removable/sdcard1", "/data/sdext", "/data/sdext2",
"/data/sdext3", "/data/sdext4", "/emmc", "/sdcard/sd",
"/mnt/sdcard/bpemmctest", "/mnt/sdcard/_ExternalSD",
"/mnt/sdcard-ext", "/mnt/Removable/MicroSD",
"/Removable/MicroSD", "/mnt/external1", "/mnt/extSdCard",
"/mnt/extsd", "/mnt/usb_storage", "/mnt/extSdCard",
"/mnt/UsbDriveA", "/mnt/UsbDriveB"};
for (String value : strPath) {
File f = null;
f = new File(value);
if (f.exists() && f.isDirectory()) {
filepath = value;
break;
}
}
return filepath;
}
Try this:
for (File f : context.getExternalFilesDirs("/"))
if (Environment.isExternalStorageRemovable(f))
Log.println(Log.DEBUG, "#", f.getParentFile().getParentFile().getParentFile().getParent());
context.getExternalFilesDirs() will always returns application-specific directory. But the good thing is that application-specific directories are always 4 level deep from the root folder of the storage device. So calling getParentFile() four times on the File f instead of f.getAbsolutePath() will get you the root path of your phone's removable storage.
Maybe just split it at Android?
I tested it, and it works after I request for permission - WRITE_EXTERNAL_STORAGE.
fun getBaseDir(dir: File): String {
val absPath = dir.absolutePath
return if (absPath.contains("/Android")) {
absPath.split("/Android")[0]
} else {
absPath
}
}
This will loop through files on sdcard root directory. If you want primary storage, just change [1] to [0].
getExternalFilesDirs returns paths to your app directory on primary and secondary storage. After splitting the second path by "Android", the first string will contain path to your secondary storage root. for example in my case it was "/storage/B242-37B2/". Working with minSdkVersion 19+.
String sdCardRoot = ContextCompat.getExternalFilesDirs(getApplicationContext(), null)[1].getAbsolutePath().split("Android")[0];
File f = new File(sdCardRoot);
File[] files = f.listFiles();
for (File inFile : files){
Log.d("Files", inFile.getName());
}
Try this one if it helps you. For more information refer this link.
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
Here is another approach for the same. Source from here.
Environment.getExternalStorageState() returns path to internal SD
mount point like "/mnt/sdcard"
But the question is about external SD. How to get a path like "/mnt/sdcard/external_sd" (it may differ from device to device)?
Android has no concept of "external SD", aside from external storage, as described above.
If a device manufacturer has elected to have external storage be on-board flash and also has an SD card, you will need to contact that manufacturer to determine whether or not you can use the SD card (not guaranteed) and what the rules are for using it, such as what path to use for it.
I am trying get all the list of particular folder name from SD-Card to list-view in android. I am giving two option to user they can create folder as well as they can rename folder from application it self.
With the list-view i have given check-box so user can check any single list value at a time and then can perform operation as they want of editing or creating folder in SD-Card.
Everything is working fine till creating folder, but my problem start's here, when user tries to rename folder name, then first time user can successfully changes the folder name but while doing same task second time, user is not able to rename same folder again.
What mistake i am doing, following is my code please help, Thanks in advance.
private static List<String> myList = new ArrayList<String>();
public static void folder_create() {
if (Code.pm == 1) {
String updateFolder = Environment.getExternalStorageDirectory()
.getPath() + "/AudioRecorder/";
File filecall = null;
filecall = new File(updateFolder);
File list[] = filecall.listFiles();
for (int i = 0; i < list.length; i++) {
myList.add(list[i].getName());
}
int len = mListView.getCount();
SparseBooleanArray checked = mListView.getCheckedItemPositions();
for (int i = 0; i < len; i++)
if (checked.get(i)) {
String mUpdateName = myList.get(i);
File file = new File(updateFolder + "/" + mUpdateName);
System.out.println("=======File======" + file);
File file2 = new File(updateFolder + "/" + Code.className);
System.out.println("=======File2======" + file2);
file.renameTo(file2);
}
} else {
String filepath = Environment.getExternalStorageDirectory()
.getPath();
File file = new File(filepath, "/AudioRecorder/" + Code.className);
if (!file.exists()) {
file.mkdirs();
}
}
}
Here Code is static class and pm is integer variable. So when user click button based on pm variable value it will perform task weather to rename folder or create folder.
If I understand your issue, you're trying to rename a directory after having made 'some tasks'. Are those tasks made into this folder? If yes, be sure that you have closed your streams (creating / modifying content) like so:
stream.close();
Please also check the LogCat to see if some warnings are shown.
I have ArrayList of object like
ArrayList<DataCCHeading>CC1=new ArrayList<DataCCHeading>();
ArrayList<DataCCHeading>hd=new ArrayList<DataCCHeading>(result);
for (DataCCHeading dataCCHeading : hd)
{
if(dataCCHeading.Ownername==TAG_CC1HeadingData)
{
CC1.add(dataCCHeading);
}
}
What I want to do to store external storage SDCard so that I can later get that data other wise I have to request it again from server. My question is how to store Arraylist of object to store and retrieve from SDCard?
You have a few options:
Java Serialization: Just make your class implements Serializable, and write the appropriate serialize and deserialize logic, and you can write them to a file and read it back. See this tutorial: http://www.tutorialspoint.com/java/java_serialization.htm
JSON serialization: Use a library list GSON, you can serialize your objects to a JSON array as a text file, save it to a file. Then read it back as a JSON string and use the GSON library again to convert it back to an arraylist of your object.
Use built-in SQLiteDatabase: Store your objects as rows of data in a sqlite database. Class members will be stored as columns in a table. To convert them back to an array, just retrieve all rows from the table, build the object one by one and add them to an arraylist.
You'd probably want to serialise it into something first (e.g.: using JYaml).
Then you can easily de/serialise, and it's quite space efficient.
You do it like this:
//use getExternalStorageState to determine if there is an sd card
if (Environment.getExternalStorageState() == null) {
directory = new File(Environment.getDataDirectory()
+ "/RobotiumTestLog/");
photoDirectory = new File(Environment.getDataDirectory()
+ "/Robotium-Screenshots/");
/*
* this checks to see if there are any previous test photo files
* if there are any photos, they are deleted for the sake of
* memory
*/
//if the directory exists, delete files in directory
if (photoDirectory.exists()) {
File[] dirFiles = photoDirectory.listFiles();
if (dirFiles.length != 0) {
for (int ii = 0; ii <= dirFiles.length; ii++) {
dirFiles[ii].delete();
}
}
}
// if no directory exists, create new directory
if (!directory.exists()) {
directory.mkdir();
}
// if phone DOES have sd card
} else if (Environment.getExternalStorageState() != null) {
// search for directory on SD card
directory = new File(Environment.getExternalStorageDirectory()
+ "/RobotiumTestLog/");
photoDirectory = new File(
Environment.getExternalStorageDirectory()
+ "/Robotium-Screenshots/");
if (photoDirectory.exists()) {
File[] dirFiles = photoDirectory.listFiles();
if (dirFiles.length > 0) {
for (int ii = 0; ii < dirFiles.length; ii++) {
dirFiles[ii].delete();
}
dirFiles = null;
}
}
// if no directory exists, create new directory to store test
// results
if (!directory.exists()) {
directory.mkdir();
}
}
It is a pretty easy process. What I did here was check to see if there is an SD card, if there is, I search for a directory, if no directory, I create one. If there is a directory and it has content I erase it. You don't have to do all that. If you like, you can use the the Environment.getExternalStorageDirectory(). This will get the SD card. From there you create a bufferedWriter and write. You also need to add <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in your manifest. If you have any questions, let me know.
I hope this helps!
I need to calculate the number of images stored in SD card and so i would like to name the images unique like Sample0,Sample1,Sample2,Sample3,etc.
Is it Possible?
It gives the number of images present in the images folder of your SD card:
File dir = new File(Environment.getExternalStorageDirectory()
+ "/images");
File[] files = dir.listFiles();
int numberOfImages=files.length;
I now it's been a long time, but, the method above would give you the number of any kind of files and directories within images folder, not only the images number, and doesn't look for images in subfolders inside the images directory.
Let's say we have this structure:
Images/
- img1.jpg
- img2.jpg
- data.dat
- whatever.pdf
- Folder/
- img3.png
The method above will give you 5 and you should obtain 3 isn't it?
I've been working on something similar and I'm pretty sure there is a more efficient way, but with this method I get the number of all images within the SDCard, or any given directory and its subfolders...
Here we go:
public int countImgs(File file, int number) {
File[] dirs = file.listFiles();
String name = "";
if (dirs != null) { // Sanity check
for (File dir : dirs) {
if (dir.isFile()) { // Check file or directory
name = dir.getName().toLowerCase();
// Add or delete extensions as needed
if (name.endsWith(".png") || name.endsWith(".jpg")
|| name.endsWith(".jpeg")) {
number++;
}
} else number = countImgs(dir, number);
}
}
return number;
}
Where the param file is the root directory and the number would be 0 at start. So to use it:
int imgNumber = countImgs(Environment.getExternalStorageDirectory(), 0);
it will be an error when files = null when get the count of images stored in SD card
File dir = new File(Environment.getExternalStorageDirectory() + "/images");
File[] files = dir.listFiles();
String strnumberOfImages=files.length;
int intnumberOfImages= 0;
try{
intnumberOfImages = Integer.parseInt( strnumberOfImages);
}catch ( Exception e ){
intnumberOfImages = 0;
}
if just check empty or not
File dir = new File(Environment.getExternalStorageDirectory()+ "/images");
File[] files = dir.listFiles();
if(files != null){
// there are picz
}else{
// sd card empty
}
I know that my question is a duplicate of this question and this one. But still I have some problems, so don't try to close or downvote my question friends. Please go through the question fully.
In my app I want to store Images into the same folder as where the device native Camera stores them. As per my research, I have found out that each device stores the Images into a different name and in different folder.
That is:
Nexus-One stores its camera files into a folder named Camera (/sdcard/DCIM/Camera).
All HTC devices store their camera files into a folder named 100MEDIA (/sdcard/DCIM/100MEDIA).
Sony Xperia x10 stores its camera files into a folder named 100ANDRO (/sdcard/DCIM/100ANDRO).
Motorola MilesStone stores its camera files into a folder named Camera (/sdcard/DCIM/Camera).
So I wanted to know if it's programmatically possible to get this path so that I can store the images taken from my app to the same location?
When I was googling I found out that it's better to create an external folder of my own so that I can store the images in that path with the name I am specifying. After that also in HTC device of API version 3 (Android 1.5) I found out that only the folder is getting created but the image gets saved in its default place with a name of its own.
How to solve this issue? Is it not possible to find the specific path and name of the image that gets saved for each device? Please help me friends.
Use getExternalStorageDirectory() if API level is below 7 and then append /Pictures to get the path of Photos storage.
for API level > 7 use getExternalStoragePublicDirectory (DIRECTORY_PICTURES).
I use the following code
String pictures_path = Utils.getRealPathFromURI(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
File path = new File(pictures_path);
if (path.isFile())
path = path.getParentFile();
Where Utils:
public static String getRealPathFromURI(Uri content_uri, int media_type) {
String column = MediaType.MEDIA_TYPE_PICTURE;
ContentResolver content_resolver = getContext().getContentResolver();
String [] proj = { column };
Cursor cursor = content_resolver.query(content_uri,
proj, // Which columns to return
null, // WHERE clause; which rows to return (all rows)
null, // WHERE clause selection arguments (none)
null); // Order-by clause (ascending by name)
int column_index = cursor.getColumnIndexOrThrow(column);
if (!cursor.moveToFirst())
return null;
return cursor.getString(column_index);
}
EDIT: Unfortunatelly, the approach above may not always work :( ...
Eventually I did manual checkings:
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
if (path.exists()) {
File test1 = new File(path, "100MEDIA/");
if (test1.exists()) {
path = test1;
} else {
File test2 = new File(path, "100ANDRO/");
if (test2.exists()) {
path = test2;
} else {
File test3 = new File(path, "Camera/");
if (!test3.exists()) {
test3.mkdirs();
}
path = test3;
}
}
} else {
path = new File(path, "Camera/");
path.mkdirs();
}
This is the function that I am using. It doesnt specifically name 100Media or Camera directories. It simply starts in the /DCIM folder and looks at its children. If the child is not a .thumbnails directory (or is, depending on what youre doing), then look at its children and get them. It also gets pictures in the /DCIM directory itself.
File dcim = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File thumbnails = new File(dcim, "/.thumbnails");
File[] listOfImg = dcim.listFiles();
if (dcim.isDirectory()){
//for each child in DCIM directory
for (int i = 0; i < listOfImg.length; ++i){
//no thumbnails
if( !listOfImg[i].getAbsolutePath().equals(thumbnails.getAbsolutePath()) ){
//only get the directory (100MEDIA, Camera, 100ANDRO, and others)
if(listOfImg[i].isDirectory()) {
//is a parent directory, get children
File[] temp = listOfImg[i].listFiles();
for(int j = 0; j < temp.length; ++j) {
f.add(temp[j].getAbsolutePath());
}
}else if(listOfImg[i].isFile()){
//is not a parent directory, get files
f.add(listOfImg[i].getAbsolutePath());
}
}
}
}
I have been looking for a solution to this problem myself. Since different manufacturers have differnet naming conventions for camera folders, this seems to cover all ground best. It works for me pretty well.