Android - Configurable directory? - android

One of the steps in building my app is to let the user select a folder in which some files are stored. How can i make this configurable, without hardcoding the directory. Is there any 3rd party library that i can use to do this ?

#Vikram's link provides a dialog that you can use. You can then save the directory the user chose using Shared Preferences.
Here is a simple example on how to use Shared Preferences.
Another tutorial can be found here.
UPDATE: A switch suddenly turned on inside me to do something like this. Credits still go to schwiz in this answer for the base code used. :)
//global variables
private File[] fileList;
private String[] filenameList;
private File[] loadFileList(String directory) {
File path = new File(directory);
if(path.exists()) {
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String filename) {
//add some filters here, for now return true to see all files
//File file = new File(dir, filename);
//return filename.contains(".txt") || file.isDirectory();
return true;
}
};
//if null return an empty array instead
File[] list = path.listFiles(filter);
return list == null ? new File[0] : list;
} else {
return new File[0];
}
}
public void showFileListDialog(final String directory, final Context context) {
Dialog dialog = null;
AlertDialog.Builder builder = new Builder(context);
File[] tempFileList = loadFileList(directory);
//if directory is root, no need to up one directory
if(directory.equals("/")) {
fileList = new File[tempFileList.length];
filenameList = new String[tempFileList.length];
//iterate over tempFileList
for(int i = 0; i < tempFileList.length; i++) {
fileList[i] = tempFileList[i];
filenameList[i] = tempFileList[i].getName();
}
} else {
fileList = new File[tempFileList.length+1];
filenameList = new String[tempFileList.length+1];
//add an "up" option as first item
fileList[0] = new File(upOneDirectory(directory));
filenameList[0] = "..";
//iterate over tempFileList
for(int i = 0; i < tempFileList.length; i++) {
fileList[i+1] = tempFileList[i];
filenameList[i+1] = tempFileList[i].getName();
}
}
builder.setTitle("Choose your file: " + directory);
builder.setItems(filenameList, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
File chosenFile = fileList[which];
if(chosenFile.isDirectory()) {
showFileListDialog(chosenFile.getAbsolutePath(), context);
}
}
});
builder.setNegativeButton("Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog = builder.create();
dialog.show();
}
public String upOneDirectory(String directory) {
String[] dirs = directory.split(File.separator);
StringBuilder stringBuilder = new StringBuilder("");
for(int i = 0; i < dirs.length-1; i++) {
stringBuilder.append(dirs[i]).append(File.separator);
}
return stringBuilder.toString();
}
The code above acts like a mini file explorer that lists the files and folders of the Android File System. You use it like:
showFileListDialog(Environment.getExternalStorageDirectory().toString(),
MainActivity.this);
Answering your question:
Add global key variables
//package name goes here.
public static final String PACKAGE_NAME = "com.example.app";
public static final String KEY_DIRECTORY_SELECTED =
PACKAGE_NAME + ".DIRECTORY_SELECTED";
private SharedPreferences prefs;
initialize your SharedPreferences somewhere on onCreate before you use it:
prefs = getSharedPreferences(PACKAGE_NAME, Context.MODE_PRIVATE);
and then you can add a positive button to the dialog
builder.setPositiveButton("Save Directory", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
prefs.edit().putString(KEY_DIRECTORY_SELECTED, directory).commit();
}
});
In your activity, instead of using the SDCard default directory you can
//if no saved directory yet, use SDCard directory as default
String oldChosenDirectory = prefs.getString(KEY_DIRECTORY_SELECTED,
Environment.getExternalStorageDirectory().toString());
showFileListDialog(oldChosenDirectory, MainActivity.this);
As Vikram pointed out. you also need to do this in your FileNameFilter so that the dialog will display directories ONLY.
Update: As noted in this SO answer, the parameters dir and filename does not refer to the same file. The dir parameter is the directory containing the file, while filename is the filename of the file itself. To determine whether the filte itself is a directory, we need to create a new file from the parameters like so:
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String filename) {
File file = new File(dir.getAbsolutePath() + File.separator + filename);
return file.isDirectory();
}
};

Related

Unable to pick file on Oreo

On Android Nougat and below, I can simply get some file on my storage using this code :
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*.jpg");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, 111);
And get the file path using :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 111 && resultCode == RESULT_OK && data.getData() != null)
String path = data.getData().getPath();
}
But on Android Oreo, this is not working. The file picker is showing up, but I cannot even pick the file using the default file picker. At first, I thought that this is related to permission. But after I add the permission to READ and WRITE external storage on runtime, and granted, this problem still occurred.
Since the default file picker on OREO is troublesome, currently I'm using a custom class to pick file or directory. Another solution is you can use ES File Explorer, etc, but not all of your user has it and the main problem still occurred.
public class FileChooser {
private Activity activity;
private Item[] fileList;
private File path;
private boolean rootDir = true; //check if the current directory is rootDir
private boolean pickFile = true; //flag to get directory or file
private String title = "";
private String upTitle = "Up";
private String positiveTitle = "Choose Path";
private String negativeTitle = "Cancel";
private ListAdapter adapter;
private ArrayList<String> str = new ArrayList<>(); //Stores names of traversed directories, to detect rootDir
private Listener listener;
/**
* #param pickFile true for file picker and false for directory picker
* */
public FileChooser(Activity activity, boolean pickFile, Listener fileChooserListener) {
this.activity = activity;
this.pickFile = pickFile;
this.listener = fileChooserListener;
title = pickFile ? "Choose File" : "Choose Directory";
path = new File(String.valueOf(Environment.getExternalStorageDirectory()));
}
/**
* The view of your file picker
* */
public void openDirectory() {
loadFileList();
AlertDialog.Builder builder = new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_DARK);
if (fileList == null)
builder.create();
builder.setTitle(title + "\n" + path.toString());
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int position) {
String chosenFile = fileList[position].file;
File selectedFile = new File(path + File.separator + chosenFile);
if (selectedFile.isDirectory()) { // user click on folder
rootDir = false;
str.add(chosenFile); // Adds chosen directory to list
path = selectedFile;
openDirectory();
}
else if (chosenFile.equalsIgnoreCase(upTitle) && !selectedFile.exists()) { // 'up' was clicked
String s = str.remove(str.size() - 1); // present directory
path = new File(
path.toString().substring(0, path.toString().lastIndexOf(s))); // exclude present directory
if (str.isEmpty()) // no more directories in the list, rootDir
rootDir = true;
openDirectory();
}
else if (listener != null && pickFile)
listener.onSelectedPath(selectedFile.getAbsolutePath());
}
});
if (!pickFile) {
builder.setPositiveButton(positiveTitle, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (listener != null)
listener.onSelectedPath(path.getPath());
}
});
}
builder.setNegativeButton(negativeTitle, null);
builder.show();
}
/**
* Setup your file picker data
* */
private void loadFileList() {
fileList = null;
if (path.exists()) {
FilenameFilter filter = new FilenameFilter() {
#Override
public boolean accept(File dir, String filename) {
File file = new File(dir, filename);
// Filters based on whether the file is hidden or not
return ((pickFile && file.isFile()) || file.isDirectory()) && !file.isHidden();
}
};
String[] fList = path.list(filter); //set filter
if (fList != null) {
fileList = new Item[fList.length];
for (int i = 0; i < fList.length; i++)
fileList[i] = new Item(fList[i], new File(path, fList[i]).isDirectory() ?
R.drawable.ic_folder : R.drawable.ic_file); //set icon, directory or file
if (!rootDir) {
Item temp[] = new Item[fileList.length + 1];
System.arraycopy(fileList, 0, temp, 1, fileList.length);
temp[0] = new Item(upTitle, R.drawable.ic_undo);
fileList = temp;
}
}
} else
path = new File(String.valueOf(Environment.getExternalStorageDirectory()));
try {
adapter = new ArrayAdapter<Item>(activity,
android.R.layout.select_dialog_item, android.R.id.text1,
fileList) {
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
// creates view
View view = super.getView(position, convertView, parent);
TextView textView = view.findViewById(android.R.id.text1);
textView.setTextColor(Color.WHITE);
// put the image on the text view
textView.setCompoundDrawablesWithIntrinsicBounds(fileList[position].icon, 0, 0, 0);
// add margin between image and text (support various screen densities)
int dp5 = (int) (5 * activity.getResources().getDisplayMetrics().density + 0.5f);
textView.setCompoundDrawablePadding(dp5);
return view;
}
};
} catch (Exception e) {
e.printStackTrace();
}
}
private class Item {
public String file;
public int icon;
private Item(String file, Integer icon) {
this.file = file;
this.icon = icon;
}
#Override
public String toString() {
return file;
}
}
public interface Listener {
void onSelectedPath(String path);
}
}

How to sort file or folder by filename or date at ascending or descending in Android?

The following sample code is from Internet, I hope to sort the List<String> files by filename at ascending or descending.
I hope to the List<String> files by date of file at ascending or descending, how can I do ? Thanks!
The same quetsion with List<String> directories.
List<String> files = Arrays.asList(f.list(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
File f=new File(dir, name);
return f.isFile()&&(f.isHidden()==false);
}
}));
Collections.sort(files);
List<String> directories = Arrays.asList(f.list(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
File f=new File(dir, name);
return f.isDirectory()&& (f.isHidden()==false);
}
}));
Collections.sort(directories);
Just provide your File array and it sort simple.
Arrays.sort(files, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
Demo:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File path = Environment.getExternalStoragePublicDirectory("/DCIM/Camera");
File[] filesList = path.listFiles();
for (int i = 0; i < filesList.length; i++) {
Date lastModDate = new Date(filesList[i].lastModified());
Log.i("Pre sorted", "File last modified # : " + lastModDate.toString());
}
Arrays.sort(filesList, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
Log.i("sorted", "----------------------------------------");
for (int i = 0; i < filesList.length; i++) {
Date lastModDate = new Date(filesList[i].lastModified());
Log.i("Pro sorted", "File last modified # : " + lastModDate.toString());
}
}
You can use like below for sorting based on file name and change that value for date and other comparision. Or simply use ApacheCommons, it will give direct APIs
File[] directoryList = currentFolder.listFiles();
if (directoryList != null) {
List<File> directoryListing = new ArrayList<File>();
directoryListing.addAll(Arrays.asList(directoryList));
Collections.sort(directoryListing, new SortFileName());
Collections.sort(directoryListing, new SortFolder());
}
//sorts based on the files name
public class SortFileName implements Comparator<File> {
#Override
public int compare(File f1, File f2) {
return f1.getName().compareTo(f2.getName());
}
}
//sorts based on a file or folder. folders will be listed first
public class SortFolder implements Comparator<File> {
#Override
public int compare(File f1, File f2) {
if (f1.isDirectory() == f2.isDirectory())
return 0;
else if (f1.isDirectory() && !f2.isDirectory())
return -1;
else
return 1;
}
}
Might be late to answer bt this method sort files by desc order by modified date
File[] listFile = dir.listFiles();
Arrays.sort(listFile, new Comparator<File>() {
#Override
public int compare(File o1, File o2) {
return Long.compare(o2.lastModified(), o1.lastModified());
}
});

How to rename audio file which is in sd card programmatically?

Here is my code to display all music file names in a list view ,here i am taking all files in an array list then displaying in a listview,by using contextmenu performing "rename" on listitems but these changes are not effecting actual file which is in sd card ,suggest me how to do this ,i tried file operations like this.
path = "/sdcard/";
if (getIntent().hasExtra("path")) {
path = getIntent().getStringExtra("path");
}
setTitle(path);
// Read all files sorted into the values-array
values = new ArrayList();
File dir = new File(path);
if (!dir.canRead()) {
setTitle(getTitle() + " (inaccessible)");
}
final String[] list = dir.list();
if (list != null) {
for (String file : list) {
if (file.contains(".3gp")) {
values.add(file);
}
}
}
Collections.sort(values);
// Put the data into the list
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_2,
android.R.id.text1, values);
setListAdapter(adapter);
registerForContextMenu(myList);
}
final int CONTEXT_MENU_DELETE = 1;
final int CONTEXT_MENU_RENAME = 2;
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
menu.add(Menu.NONE, CONTEXT_MENU_DELETE, Menu.NONE, "silmek");
menu.add(Menu.NONE, CONTEXT_MENU_RENAME, Menu.NONE, "adını değiştirmek");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
.getMenuInfo();
Long id = myList.getAdapter().getItemId(info.position);
final int number_of_item_in_listview = Integer.valueOf(id.intValue());
final int context_menu_number = item.getItemId();
switch (item.getItemId()) {
This is how i am renaming file prgrammatically using contextmenu for listview
case CONTEXT_MENU_RENAME:
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("öğeyi yeniden adlandırmak");
alert.setMessage("Seçili öğe için yeni bir isim girin");
final EditText input = new EditText(this);
alert.setView(input);
alert.setPositiveButton("tamam",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
String value = input.getText().toString();
values.set(number_of_item_in_listview, value
+ ".3gp");
adapter.notifyDataSetChanged();
/*
* File sdcard =
* Environment.getExternalStorageDirectory(); File
* from = new File(sdcard,"from.txt"); File to = new
* File(sdcard,"to.txt"); from.renameTo(to);
*/
File f = new File(path + filename);
if (f != null && f.exists()) {
File from = new File(f, f.getName());
File to = new File(f, value);
from.renameTo(to);
}
}
});
alert.setNegativeButton("iptal",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
});
alert.show();
return (true);
}
return (super.onOptionsItemSelected(item));
I would recommend using File.renameTo() rather than running the mv command, since I'm fairly sure the latter isn't supported..
Have you given your application permission to write to the SD Card?
You do this by adding the following to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If it doesn't work once the permission is added check the device log for errors when you try to rename the file (either using the adb command or in the logcat view in Eclipse).
When accessing the SD Card you shouldn't hard-code the path but instead use the Environment.getExternalStorageDirectory() method to get the directory.
The following code works for me:
File sdcard = Environment.getExternalStorageDirectory();
File from = new File(sdcard,"from.txt");
File to = new File(sdcard,"to.txt");
from.renameTo(to);

android find external folders through mnt

Let me get this out of the way; I am a beginner to java, I research the code I need and try to learn it while using it in my app.
I am currently stuck, not really sure how I can continue, ANY help is greatly appreciated.
I am trying to look in the /mnt/ folder for any folder with 'ext' or 'sd' in the file name. This is what I have so far, it gets me a null pointer exception but I don't know what variable is null.
public class MainActivity extends Activity
{
static File[] dirs;
#Override
public void onCreate(Bundle savedInstanceState)
{
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findMnt("/mnt/");
AlertDialog builder = new AlertDialog.Builder(this).setTitle("AppName").setMessage(dirs[0].getPath()).setNeutralButton("Close", null).show();
AlertDialog builder2 = new AlertDialog.Builder(this).setTitle("AppName").setMessage(dirs[1].getPath()).setNeutralButton("Close", null).show();
}
public static void findMnt(String path) {
File file = new File(path);
if(file.exists()){
File[] list = file.listFiles();
for(int i=0; i<list.length; i++) {
if(list[i].isDirectory()) {
if(list[i].getPath().contains("sd") || list[i].getPath().contains("ext")){
for(int b=0; b<list.length; b++){
dirs[b] = new File(list[i].getPath());
}
}
}
}
}
}
Memory Cases: if you take any new device or for ex. micromax funbook, then its having three memory
/data/data/ (phone internal memory) getFilesDirectory()
/mnt/sdcard/ (phone's internal sdcard)
Environment.getExternalStorageDirectory()
/mnt/extsd/ (External sdcard) /mnt/extsd
You first need to be sure whether your External card is of /mnt/sdcard/ or /mnt/extSd for that I have created a function
/**
* #return Number of bytes available on external storage extSD
*/
public long getExternalAvailableSpaceInBytes() {
long availableSpace = -1L;
try {
StatFs stat = new StatFs("mnt/extsd");
System.out.println("ExternalAvailableSpace Path : "+mStringExernalSD);
availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
} catch (Exception e) {
e.printStackTrace();
}
return availableSpace;
}
if getExternalAvailableSpaceInBytes() returns 0 it means you need to consider /mnt/sd
To get all folders
ArrayList<File> mFiles= new ArrayList<File>();
if(getExternalAvailableSpaceInBytes()>0)
findMnt(mFiles, "/mnt/extsd");
else
findMnt(mFiles, "/mnt/sdcard");
public ArrayList<File> findMnt(ArrayList<File> files, File dir)
{
if (!dir.isDirectory())
{
files.add(dir);
return files;
}
for (File file : dir.listFiles())
findMnt(files, file);
return files;
}
This method is crude but will work for what I need it to. Searches for the sdcard folder, then searches for a folder with ext in the name, and if it fails it searches the sdcard folder for an ext folder.
String sd = findSd("/mnt/") + "/";
String ext = findExt("/mnt/") + "/";
if(ext == "ext not found"){
ext = findExt(sd + "/");
}
public static String findSd(String path){
File file = new File(path);
if(file.exists()){
File[] list = file.listFiles();
for(int i=0; i<list.length; i++) {
if(list[i].isDirectory()) {
if(list[i].getPath().contains("sd")){
return list[i].getPath();
}
}
}
}
return "sd not found";
}
public static String findExt(String path){
File file = new File(path);
if(file.exists()){
File[] list = file.listFiles();
for(int i=0; i<list.length; i++) {
if(list[i].isDirectory()) {
if(list[i].getPath().contains("ext") && list[i].getPath() != findSd("/mnt/")){
return list[i].getPath();
}
}
}
}
return "ext not found";
}

How to list all the files in a custom Directory

I'm trying to list all the files in a directory I have made, when I create the directory I warp a file for each contact into the dir. I then want to be able to list all those files inside/within the directory. I have tried everything including
String a = listFiles().tostring();
Yet, nothing happens. To sum it up, I want to list all the files within a custom dir in the SD card.
Here's my updated code
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
FileInputStream iStream = new FileInputStream(path);
String read = path.getbytes().tostring();
You have to see this tutorial how to build an android file browser it will help you a lot!!
This one list all folder and files in sdcard you can adapt it to what you need by changing the value of currentDir in the code
This code is travel entire sdcard and list files. that's may be helpful to you ..!
import java.io.*;
import java.util.*;
public class DirUtils {
public static List recurseDir(String dir) {
String result, _result[];
result = recurseInDirFrom(dir);
_result = result.split("\\|");
return Arrays.asList(_result);
}
private static String recurseInDirFrom(String dirItem) {
File file;
String result,list[];
result = dirItem;
file = new File(dirItem);
if (file.isDirectory()) {
list = file.list();
File[] fileslist = file.listFiles(new MyDocFileFilter());
if (fileslist != null) {
for (File file1: fileslist) {
System.out.println(file1.getAbsolutePath());
}
}
else {
System.out.println("No Subdirectory Found.");
}
for (int i = 0; i < list.length; i++)
result = result + "\n" + recurseInDirFrom(dirItem + File.separatorChar + list[i]);
}
return result;
}
static class MyDocFileFilter implements FileFilter
{
private final String[] myDocumentExtensions
= new String[] {".java", ".png", ".html", "class"};
public boolean accept(File file) {
if (!file.isFile())
return false;
for (String extension : myDocumentExtensions) {
if (file.getName().toLowerCase().endsWith(extension))
return true;
}
return false;
}
}
public static void main(String arg[]) {
DirUtils.recurseDir("your path ");
}
}

Categories

Resources