Listing files in Downloads directory is limited to images - android

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.

Related

Android Studio: context.getFilesDir() returns a path [/data/user/0/com.example.filesexperimenting/files/] that I can not find. What am I missing?

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()

Can not get Android to create a folder in public external storage

I'm using Android Studio. I have my project set to require API version 11. The Emulator is set for Nexus 5 API23 (standard default settings).
I want to have my application write a simple text file to a location where I can pull the text files created onto my computer by plugging in with a USB cable. So it needs to be in the public external storage.
For whatever reason I can't get the code to create a folder for my text files to go into. I have paired my code down to this little nugget in a "Utilities" class I have:
public static boolean createTheDangFolder(Context c, String fileName, String body) {
boolean saved = true;
//File dir = new File(c.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "MyCustomFolder");
File dir = new File(Environment.getExternalStorageDirectory(), "MyCustomFolder");
if (!dir.exists()) {
saved = dir.mkdirs();
}
return saved;
}
This function always returns false. If I trade comments on the "File" line it will return true but the commented out line is the app memory and I can't access the files via USB.
I have this line in my Manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I can't for the life of me figure out why it's not working and none of the other questions on the site have given me a solution that works.
They changed the permissions to external storage in KitKat. You can only write to public folders (like downloads) and to your own app's private directory on external storage.

Confused on how to access files from a ZipResourceFile (APK extension file)

My app is very image-heavy, so I need to supply expansion files with my APK. I've chosen to store all my images in a ZIP file and use the zip library to get access to my images.
My first intuition was to unzip all files when the app is first started and store them in the app's external directory. The guide gently nudges me to take a different approach:
Reading media files from a ZIP
If you're using your expansion files to store media files, a ZIP file
still allows you to use Android media playback calls that provide
offset and length controls (such as MediaPlayer.setDataSource() and
SoundPool.load()). In order for this to work, you must not perform
additional compression on the media files when creating the ZIP
packages.
So I guess I'll just get an input stream from the zip file when I have to, but I don't really know how long I should have that zip file open.
Suppose I have a gallery activity with a ViewPager that shows one image per page. Do I open my expansion zip file in onCreate and close it in onDestroy, or do I open and close the file for every new image loaded?
From API level 9, you could use the jobb tool to package your assets and use StorageManager to mount/dismount the OBB file. You can also use this tool to encrypt the assets, if need be.
OBBs are a good way of providing large amounts of binary assets without packaging them into APKs as they may be multiple gigabytes in size. However, due to their size, they're most likely stored in a shared storage pool accessible from all programs.
...
The OBB will remain mounted for as long as the StorageManager reference is held by the application. As soon as this reference is lost, the OBBs in use will be unmounted. The OnObbStateChangeListener registered with this call will receive the success or failure of this operation.
I guess a mounted OBB file can dismount at any unexpected time (for example, when the user turns on USB mass storage), so pay extra attention to your OnObbStateChangeListener.
Example from this question:
storage = (StorageManager) getSystemService( STORAGE_SERVICE );
storage.mountObb( obbFilepath, "optional_encryption_key", myListener );
You can use obbContentPath to read files just like they would be on disk.
private final OnObbStateChangeListener myListener = new OnObbStateChangeListener() {
#Override
public void onObbStateChange(String path, int state) {
super.onObbStateChange(path, state);
d(path + " changed to state " + state);
switch (state) {
case ERROR_ALREADY_MOUNTED:
case ERROR_COULD_NOT_MOUNT:
case ERROR_COULD_NOT_UNMOUNT:
case ERROR_INTERNAL:
case ERROR_NOT_MOUNTED:
case ERROR_PERMISSION_DENIED:
case UNMOUNTED:
//TODO
break;
case MOUNTED:
String assetsPath = mStorageManager.getMountedObbPath(mPathToObb);
if (assetsPath == null) throw new NullPointerException("Could not get path to mounted OBB path");
d("Checking if " + assetsPath + "/path/to/file exists");
File f = new File(assetsPath + "/path/to/file");
d("" + f.exists());
break;
default:
break;
}
}
};

Reading all files in the Android file system

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

Android Programming: Where To Start For Creating A Simple File Browser?

I would like to make a file browser that will do two things:
1) Allow the user to browse and select a directory
2) Allow the user to browse all files on their sdcard
I've looked for tutorials but can't seem to find any?
Can someone please help me by either explaining how what my code would need to do in order to have a simple file browser or providing me with a link to a tutorial/source code?
Please and thanks!
If you're actually more interested in learning to write your own, I'd suggest taking a good long read through the File class documentation. That's where you're going to be doing most of the work.
In the case of SD cards/other external storage for Android, you'll want to first check to ensure that the external storage is mounted and available before trying to read it, using the Environment class:
String extState = Environment.getExternalStorageState();
//you may also want to add (...|| Environment.MEDIA_MOUNTED_READ_ONLY)
//if you are only interested in reading the filesystem
if(!extState.equals(Environment.MEDIA_MOUNTED)) {
//handle error here
}
else {
//do your file work here
}
Once you've determined the proper state of the external storage, a simple way to start is to use File's listFiles() method, like so:
//there is also getRootDirectory(), getDataDirectory(), etc. in the docs
File sd = Environment.getExternalStorageDirectory();
//This will return an array with all the Files (directories and files)
//in the external storage folder
File[] sdDirList = sd.listFiles();
You can then start using FileFilters to narrow down your results:
FileFilter filterDirectoriesOnly = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
File[] sdDirectories = sd.listFiles(filterDirectoriesOnly);
From there on, just read through the docs to find the type of thing you're looking to do with it, and then you can work on tying these into list adapters, etc.
Hope this helps!
This is a late answer but I worked on creating an android file explorer recently. https://github.com/mburman/Android-File-Explore
Its really straightforward. Essentially its just 1 file that you would need to integrate into your application.
Take a look at OI File Manager, which is an open-source Android file manager. You can get the source code here.

Categories

Resources