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
Related
In my application i used to show to the user all the files with a specific extension available in his "Downloads" directory :
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
return dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".ext");
}
});
It seems that this is not working anymore on android 11 and 10 (maybe below ?).
After investigation i found that listFiles() or list() now only return image file and not all the files as it used to be.
Almost like if a "default filter" was applied. Therefore my ".ext" files doesn't show anymore
What can i do to be able to see my ".ext" file and not only image file ?
Note that using the standard Filepicker to choose a file is not really an option , i have to stay in the app workflow.
I am trying to use Android's internal helpers to get a path from the system for my file first and then put my files where the system wants. Because tomorrow they might change their minds.
I made a simple program to explore this subject. Here is my code;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String path = letsMakeAfile(this, "myFile.txt");
}
private static String letsMakeAfile(Context context, String nameOfFile) {
String strOfFinalPath ="";
//ask the system what path to use...
String strOfContextPath = context.getFilesDir() + "/";
//line above doesnt work without ' + "/" ' or something on the end
//line above records this path: /data/user/0/com.example.filesexperimenting/files/
//this appears to be an invalid path unless "user" is a hidden directory
Log.d("IDIOT", "strOfContextPath: "+ strOfContextPath);
try
{
File file = new File(strOfContextPath, nameOfFile);
if (file.exists() == false) {
file.mkdirs();
//after this line "makes dirs" is file automatically still made and dropped in?
letsMakeAfile(context, nameOfFile);
//I assume not so Ive made a recursive call
}
else
;
//escape recursion....
strOfFinalPath = file.getAbsolutePath();
//Here I record the path where I hope the file is located
Log.d("IDIOT", "strOfFinalPath: "+ strOfFinalPath);
}
catch (Exception e) {
e.printStackTrace();
Log.d("IDIOT", "CATCH ERROR: "+ e.getLocalizedMessage());
}
//runs without a catch
return strOfFinalPath;
}
}
Logcat:
2019-04-09 09:59:22.901 16819-16819/? D/IDIOT: strOfContextPath: /data/user/0/com.example.filesexperimenting/files/
2019-04-09 09:59:22.901 16819-16819/? D/IDIOT: strOfFinalPath: /data/user/0/com.example.filesexperimenting/files
Ultimately I am getting a path of /data/user/0/com.example.filesexperimenting/files/ from context.getFilesDir() which appears to be an invalid path unless "user" is a hidden directory (then why can I see root?). In Device File Explorer under data the only other directories are app, data and local
What am I missing? I'll assume its something with file.makedirs()
Full disclosure, I am a student and there is not a lot out there on this so your replies, while obvious to you at your experience level, should help others. I have some experience with Java and more with C++ but Android is new to me. Thanks in advance!
So, in talking outside of StackExchange it appears that using java.io like I am trying to in the example can cause some problems because of the preset file directories that may be locked or restricted that Java io might not know about.
Android has it's own method openFileOutput(String name, int mode) that has the ability to create the app resource file and directory it belongs in.
Description copied from class: android.content.Context
Actions:
~Open a private file associated with this Context's application package for writing.
~Creates the file if it doesn't already exist.
~No additional permissions are required for the calling app to read or write the returned file.
Params:
~name – The name of the file to open; can not contain path separators.
~mode – Operating mode.
Returns: The resulting FileOutputStream.
Throws: java.io.FileNotFoundException
If you want to be able to navigate to the location of your saved files through the file explorer (either in Android Studio or the Files app on the phone) you should use Context.getExternalFilesDir().
Context.getFilesDir() returns a directory not accessible by anyone BUT the creating application. So if you would like to see what is in this file you would need to open it with the same application that wrote it. IE: Print the contents to the screen after you save it in your app.
Context.getExternalFilesDir() returns a directory completely accessible by anyone and any application. So files created and saved in this external directory can be seen by Android Studio's file explorer as the OP has screenshot or by any application installed on the phone.
What is nice about both of these methods is that as long as you are only accessing files you have created you never need to ask the user for storage permissions Read or Write. If you would like to write to someone else's external files dir then you do.
Source
Check if sdcard is mounted or not.
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
///mounted
}
Get the path of sd card
File dir= new File(android.os.Environment.getExternalStorageDirectory());
walkdir(dir);
ArrayList<String> filepath= new ArrayList<String>();
//list for storing all file paths
public void walkdir(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
// if its a directory need to get the files under that directory
walkdir(listFile[i]);
} else {
// add path of files to your arraylist for later use
//Do what ever u want
filepath.add( listFile[i].getAbsolutePath());
}
}
}
}
Try using this:
context.getFilesDir().getParentFile().getPath()
I am working on a chat application where I am sending/receiving Images/ Media. I am writing those files in a directory both sent and received.
Now the problem is if I send an image from gallery in chat I am copying it into Sdcardpath + AppName/Images/Sent/.
I this case the images in sent folder are duplicate.
And gallery app is Showing Sent folder with images. I need a way so that gallery cannot read the SentFolder. Below is my code for creating directory.
public static File getImageSentDirectory() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
File dir = new File(Environment.getExternalStorageDirectory() + DOCUMENT_FILE_SENT_PATH);
if (!dir.exists())
dir.mkdirs();
return dir;
} else {
File dir = new File(getAppContext().getFilesDir() + DOCUMENT_FILE_SENT_PATH);
if (!dir.exists())
dir.mkdirs();
return dir;
}
}
I also tried .
dir.setWritable(true,true);
dir.setReadable(true,true);
But on restart device gallery app is showing the sent folder with images .
Add a .nomedia file in your "Sent" directory.
This will make the "Gallery" app skip your folder and thus it won't be listed.
The .nomedia file is like this inside WhatsApp media directory. It is a zero byte file.
I need a way so that galery can not read the SentFolder.
Do not put SentFolder on external storage. Put it on internal storage.
The .nomedia suggestion may help, but it is a convention, not a rule. Any app that has read access to external storage can get to any files you put on external storage. If you do not want that, do not put the files on external storage.
I want to create a private folder for my app data. This folder has to be deleted automatically when the app is removed from the device. According to http://developer.android.com/training/basics/data-storage/files.html, I have to create a private folder. How can I achieve this. My code below. Folder is not deleted when the app is removed.
public static String getAppFilePath(Context context) {
String path = "";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory()
.getAbsolutePath();
path += "/myFolder";
} else {
ContextWrapper c = new ContextWrapper(context);
path = c.getFilesDir().getPath();
}
File ret = new File(path);
if (!ret.exists()) {
ret.mkdirs();
}
return path;
}
you are doing it wrong.
from the documentation you pointed:
If you want to save files that are private to your app, you can
acquire the appropriate directory by calling getExternalFilesDir()
and passing it a name indicating the type of directory you'd like.
Each directory created this way is added to a parent directory that
encapsulates all your app's external storage files, which the system
deletes when the user uninstalls your app.
For example, here's a method you can use to create a directory for an
individual photo album:
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
If none of the pre-defined sub-directory names suit your files, you
can instead call getExternalFilesDir() and pass null. This returns the
root directory for your app's private directory on the external
storage.
Remember that getExternalFilesDir() creates a directory inside a directory that is deleted when the user uninstalls your app. If the
files you're saving should remain available after the user uninstalls
your app—such as when your app is a camera and the user will want to
keep the photos—you should instead use
getExternalStoragePublicDirectory().
so basically you need to use getExternalFilesDirfunction in the example above to get it deleted when app in uninstalled.
according to documentation for getExternalFilesDir()
Parameters
type The type of files directory to return. May be null for
the root of the files directory or one of the following constants for
a subdirectory: DIRECTORY_MUSIC, DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS,
DIRECTORY_PICTURES, or DIRECTORY_MOVIES.
so apart from predefined types you can use null for root of the directory.
In simple words you cannot.
It is not possible as you cannot handle event after uninstalling the App.
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.