I'm making an Android app which stores some downloaded pdf files inside the device's SD card.
Everything works fine, but now I want to add a function to just pop up the default android file/folder browser showing the directory where my app stores all the PDF (with subdirectories in it) so that the user sees where his documents are stored and can easily browse them.
I've been throught many other SO questions and forum posts, but it seems this can only be done for music/images/contacts/etc. basically those file types which have a 'dedicated browsing system' but not with general file browsing.
I'm actually using this code:
File file = new File("/sdcard/MySorgenia/Documenti/");
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri data = Uri.fromFile(file);
String type = "*/*";
intent.setDataAndType(data, type);
startActivity(intent);
But this will show me a "Choose the application to complete your action" dialog with many applications such as "Music" "Gallery" etc, but no general purpose one.
Thanks!
Because In android there is no any native application which you can use as a File Explorer and responds to Intent type "*/*"
Implement your own File-Explorer Code for this purpose..
Look at these two Links..
openintents
Android-File-Explore
public void loadfile()
{
private static final int gallery=12;
private static final String type="*/*";
Intent i=new Intent(Intent.ACTION_GET_CONTENT);
i.setType(type);
startActivityForResult(Intent.createChooser(i,"select file"), gallery);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == gallery && resultCode == RESULT_OK && data != null) {
Uri uploadfileuri = data.getData();
File file = new File(uploadfileuri.getPath());
}
}
Since Android 4.4 KitKat (API level 19), there is an Android built-in file picker: your app invokes the ACTION_OPEN_DOCUMENT and/or ACTION_CREATE_DOCUMENT intent and receives the files returned by document providers. More info about that can be found here:
Open files using storage access framework | Android Developers
Depending on where you want to store files, you may need to request permission:
Request App Permissions | Android Developers
Here is a how to:
An Android Storage Access Framework Example - Techtopia.
And a great working example is Ian Lake's Local Storage. Its source can be found on GitHub:
https://github.com/ianhanniballake/LocalStorage
And the app can be downloaded from Google Play:
https://play.google.com/store/apps/details?id=com.ianhanniballake.localstorage
Most android distributions do not come with a default file browser, and the behavior you noticed is the default android behavior. If there's any good third party file browser installed, it will automatically show up in that list. However it is not guaranteed that every end user will have a file browser installed. A general purpose fragment-widget can be created for this (and probably shared with others).
Look at this file picker, it's the best one I found:
Related
In my app I need to read a settings file, and that settings file can either be on local storage or on the user's Google Drive storage (with Google Drive app installed).
The following opens up a file chooser, first asking the user which file picker to use, including the option of using the Google Drive file picker:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
Intent chooserIntent = Intent.createChooser(intent, "Open file");
startActivityForResult(chooserIntent, REQUEST_CODE_FILE_PICKER);
In my onActivityResult() function, if the user opted to use a file picker to choose a local file, then I already know how to successfully get the file path and read the file. But if the user instead used the Google Drive file picker to choose a remote file, how do I access the file that the user selected?
These are the bare bones of my onActivityResult() function:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_FILE_PICKER && resultCode == RESULT_OK) {
if (LOCAL FILE) {
Uri uri = data.getData();
File myFile = new File(uri.getPath());
String filePath = myFile.getAbsolutePath();
// now read file store at 'filePath' from local storage (this part is fine)
} else if (GOOGLE DRIVE FILE) {
// what do I do here to retrieve the selected file?
}
}
super.onActivityResult(requestCode, resultCode, data);
}
When selecting a Google Drive file using the Google Drive file picker, the selected file seems to be downloaded (but to where??) but then nothing happens... how do I access the downloaded file to use in my app?
And in onActivityResult() above, how do I tell if the selected file is actually a Google Drive file, so that I can treat it accordingly? i.e. what is the test for if (GOOGLE DRIVE FILE)?
I believe you're using OpenFileActivityBuilder when Drive is selected as the file picker. It will return a EXTRA_RESPONSE_DRIVE_ID which is the Drive ID of the selected file. After this, you just need to call DriveFile.open to open the said file. This can be your flag to check if you selected a Drive File picker or not.
I cannot answer where the file is downloaded, but my best guess for it is its inside your data/ of the application (which you most likely don't have access to)
I have this code:
protected void pickFile(View view){
///Codigo que abre la galeria de imagenes y carga la imagen en displayedImage
Intent intent = new Intent();
intent.setType("file/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Choose File to Upload"), 1);
}
//It's executed when leaving file system
#Override
protected void onActivityResult(int reqCode, int resCode, Intent data){
super.onActivityResult(reqCode, resCode, data);
if (reqCode == 1 && resCode == RESULT_OK && data != null) {
Uri selectedFile = data.getData();
RequestMaker.uploadFile(this, selectedFile, "this is a file");
}
}
What i want to do is to be able to select any file from my phone and send it.
The code works, it opens the chooser and lets me search for any file. However, there are a few problems i am having:
When i try to access via "Internal Storage" option, i cannot select any item. They are all disabled. I fixed that installing a file manager and it lets me choose the files i want, but maybe there is a quick fix for that.
When i select the file and run Uri.getPath(), sometimes the path is valid, others, and in general when i am selecting some image file, there is an error with the path i get in return. Is not the actual one.
I saw some fixes online but they are all for selecting images from the galery, i want the general one.
How can i fix this?
The code works
No, it does not.
First, file/* is not a valid MIME type, or even a wildcard MIME type. There is no MIME type that begins with file/. If you want any MIME type, try */*.
Second, ACTION_GET_CONTENT does not allow the user to "select any file". It allow the user to pick a piece of content, from any app on the device that implements an ACTION_GET_CONTENT activity that elects to honor your MIME type. What is returned by that activity is a Uri pointing to the content. This does not have to be a local file, let alone one that you have direct filesystem access to.
When i select the file and run Uri.getPath(), sometimes the path is valid
No, the path is always valid (at least, for a while). It just is not what you think it is. A Uri is not a file.
For example, presumably you are viewing this Web page in a Web browser. If you look in the address bar of that Web browser, you will see the following URL:
https://stackoverflow.com/questions/33575449/how-to-get-any-type-of-file-with-intent-createchooser-android
By your way of thinking, this is referring to a file, on your hard drive, located at /questions/33575449/how-to-get-any-type-of-file-with-intent-createchooser-android.
That is not the case. Part of the URL indicates a location where the path is relevant; in this case, it refers to a Web server.
A Uri is the same thing. In particular, if the Uri has a scheme other than file:, the Uri is simply an address, one that does not necessarily map to anything you can get to directly. Just as Web browser developers use HTTP to get a stream on the contents of this Web page, so you must use ContentResolver and openInputStream() to get at the contents of content: Uri values.
How can i fix this?
Either:
Use the Uri as a Uri, with openInputStream(), getType(), and similar methods on ContentResolver, or
Do not use ACTION_GET_CONTENT, but instead build your own UI for browsing files that your app happens to be able to reach. This will be a subset of all the files on the device, as not everything is in a location that your app has access to (e.g., files on removable media will be missed). But, it synchronizes your code with your mental model (i.e., that you want files, not content).
Android 5 introduce new API for working with SD-card. If you want to write files into some directory on the SC-card, y need get access to it.
As far as I know, it could be done in this way:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 42);
and then:
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode == RESULT_OK) {
Uri treeUri = resultData.getData();
getActivity().getContentResolver().takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
}
This code launch folder picker, and when folder is picked it requires permissions on the folder by it's Uri.
But is it possible to get permissions on exact directory by it's path? Without using folder picker. I meant that I know directory, which I want get access, and I don't want to launch Folder Picker, because it will confuse user.
How to open DocumentFile without user interaction?
It's impossible. User should choose directory using android's file picker. The only way to get access to folder is using:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 42);
Because file is provided by Storage Access Framework DocumentsProvider. Actually it could return some Uri from 3-rd party app, which is not real file, but some entity, which 3-rd party app present as file.
My ultimate goal is to allow the user to select a folder to save a file to - the file is a video file that will be created at some point after the user has chosen the destination.
I am simply using the storage access framework picker to allow them to select a location for it to be saved in.
First of all, is there a way to allow a user to select only a folder (and not a file/filename)?
The best I can do right now is use the ACTION_CREATE_DOCUMENT Intent in order to get a save location, however I do not really want to specify the filename in the SAF picker (this will be done back in the app)...
Secondly, after reading the Storage Access Framework documentation, and cobbling together some bits from a few code samples, I've got a working DocumentsProvider which almost does what I want - which is to allow the user to browse their external storage (SD Card) directories for a suitable place to save a video file - by adding my own root which points to Environment.getExternalStorageDirectory() to the queryRoots() method.
However, what I really want is for that to be my only root (at the minute I've also got Drive, Downloads etc.).
Is it possible to remove/hide other roots so it essentially becomes an application-specific file picker?
Or even show local storage only (perhaps the Root.FLAG_LOCAL_ONLY flag can help)?
Thanks!
API 21 supports Intent.ACTION_OPEN_DOCUMENT_TREE. This allows you to select the location once and then you can use the provided URI to manipulate its content.
private static final int LOCATION_CHOOSER_REQ_CODE = 4;
public void chooseLocation() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, LOCATION_CHOOSER_REQ_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == LOCATION_CHOOSER_REQ_CODE && resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri uri = data.getData(); // Use this URI to access files
}
}
I am developing on a Android 4.0.3 device. How do I open a file browser for my app? Is there one built in the to Android SDK? Do I have to write my own?
I don't want my app to depend on a the user installing a separate app for file browsing.
To get a file from a file browser, use this:
Intent fileintent = new Intent(Intent.ACTION_GET_CONTENT);
fileintent.setType("gagt/sdf");
try {
startActivityForResult(fileintent, PICKFILE_RESULT_CODE);
} catch (ActivityNotFoundException e) {
Log.e("tag", "No activity can handle picking a file. Showing alternatives.");
}
I'm not quite sure what the gagt/sdf is for... it seems to work in my app for any file.
Then add this method:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Fix no activity available
if (data == null)
return;
switch (requestCode) {
case PICKFILE_RESULT_CODE:
if (resultCode == RESULT_OK) {
String FilePath = data.getData().getPath();
//FilePath is your file as a string
}
}
If the user doesn't have a file manager app installed or preinstalled by their OEM you're going to have to implement your own. You might as well give them a choice.
I hope this one will help you for file picking:
public void performFileSearch() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
// browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones)
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
// To search for all documents available via installed storage providers,
// it would be "*/*".
intent.setType("image/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
The code is from this documentation:
https://developer.android.com/guide/topics/providers/document-provider.html
Refer to it for more information.
If someone would still need it for newer versions, it got updated with developing Storage Access Framework by Google for SDK >= 4.4. Check this Google site for further details:
https://developer.android.com/guide/topics/providers/document-provider.html
There is no single file-management app that is installed across all devices.
You probably want your app to be also working on devices with Android 3.x or lower.
The best choice you have though is writing your own file-manager. It isn't as much effort as it might sound, there is a lot of code on this already out there on the web.