Android open an external directory using an intent - java

There is not a straightforward or a clear way to make an implicit intent to open a folder/directory in Android.
Specifically here I want to open getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).
I tried these ones but they will just open a FileManager app, not the directory I want:
val directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
val uri = Uri.parse(directory.path)
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.setDataAndType(uri, "*/*")
startActivity(Intent.createChooser(openIntent, "Open Folder"))
Another example:
val directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
val uri = Uri.parse(directory.path)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "resource/folder")
startActivity(Intent.createChooser(openIntent, "Open Folder"))

Opening 'THE' Downloads folder
If you want to open the downloads folder, you need to use DownloadManager.ACTION_VIEW_DOWNLOADS, like this:
Intent downloadIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
downloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(downloadIntent);
No need to use mime type resource/folder as Android doesn't have an official folder mime type, so you could produce some errors in some devices. Your device seems not to support that mime type. You need to use the code above, as it just passes to the intent the official folder you want to go to.
Edit: For other custom directories, I don't think that you can just pass a path to the intent like the one. I don't think that there is a reliable way to open a folder in Android.
Using FileProvider(Test)
Edit: Try instead of just parsing the Uri, if you are using FileProvider, which you should, use getUriForFile(). Like this:
val dir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
val intent = new Intent(Intent.ACTION_VIEW)
val mydir = getUriForFile(context, "paste_your_authority", dir)
intent.setDataAndType(mydir, "resource/folder")
startActivity(intent);
or instead of using resource/folder, use:
DocumentsContract.Document.MIME_TYPE_DIR
Moral of the story:
There is no standard way of opening files. Every device is different and the code above is not guaranteed to work in every single device.

Related

Open file from specific folder with Intent.ACTION_OPEN_DOCUMENT

I would like to open the file picker at a specific path. The user should be able to pick any file on the phone, but the SAF should show a specific folder first. I tried the following but it always opens the downloads folder. Thanks!
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
Uri uri = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
intent.setDataAndType(uri,"image/*");
startActivityForResult(intent, 1);
you need to use the extra EXTRA_INITIAL_URI

Is there way to share *.json file via Intent or something else?

In my app I need to share *.json file to other app (messenger, google disk, etc). How can I do this via Intent or something else?
But when I trying to do this via Intent, I have some problems.
override fun shareBackupData(path: String) {
val uri = Uri.parse(path)
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
shareIntent.type = "*/*"
startActivity(Intent.createChooser(shareIntent, "Choose"))
}
When I run this code, I choose app to share and then I see toast "unsupported attachment"
I had similar problems with this and I found this article where it recommends us to use FileProvider.
What it does is :
FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri for a file instead of a file:/// Uri.
I recommend you to take a look to the article and also if you want code, take a look at this Stackoverflow post
i think you can use the file as ExtrtaStream the following code is sharing image file you can change it to your json file
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jpg");
final File photoFile = new File(getFilesDir(), "foo.jpg");//change it with your file
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(photoFile));
startActivity(Intent.createChooser(shareIntent, "Share image using"));

Android Share Intents - Some files won't share

I am having some issues with Android share intents. I am able to succesfully share image files (jpg, png, gifs), but when I try to share any other files (doc, docx, xlsx, ppt), I get errors from the apps saying that there were errors opening the files, but when I try to open them from the file manager, they work fine.
var uri = Android.Net.Uri.Parse(System.IO.Path.Combine(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads).AbsolutePath, fileName));
string auth = "xamarintestapp.xamarintestapp.fileprovider";
string mimeType = Android.Webkit.MimeTypeMap.Singleton.GetMimeTypeFromExtension(Android.Webkit.MimeTypeMap.GetFileExtensionFromUrl(fileName.ToLower()));
if (mimeType == null)
mimeType = "*/*";
var file = new Java.IO.File(System.IO.Path.Combine(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads).AbsolutePath, fileName));
Android.Net.Uri intentUri = null;
Intent intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, mimeType);
intent.SetFlags(ActivityFlags.GrantReadUriPermission);
Forms.Context.StartActivity(Intent.CreateChooser(intent, "Choose an App"));
I have tried checking the MIME type, and they seem to be correct (application/vnd.openxmlformats-officedocument.wordprocessingml.document for doc and docx files). Any help would be greatly appreciated.
You need to use a file scheme-based based uri instead of just passing a filesystem-based path.
Note: The Downloads directory is a publicly accessible file location on Android so no granting of rights, nor content provider, is needed, but if these files, doc|x or not, are coming from within your app's sandbox, then you would need to implement a content provider and share a content://-based provider uri to Word, Excel and other apps...
Example:
var fileName = "demo.docx";
var mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(MimeTypeMap.GetFileExtensionFromUrl(fileName)) ?? "*/*";
var downloads = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads);
using (var intent = new Intent(Intent.ActionView))
using (var uri = new Uri.Builder()
.Scheme("file")
.Authority("localhost")
.AppendEncodedPath(downloads.CanonicalPath)
.AppendEncodedPath(fileName)
.Build())
{
intent.SetDataAndType(uri, mimeType);
StartActivity(Intent.CreateChooser(intent, "Choose an App"));
}
Update:
....exposed beyond app through ClipData.Item.getUri()
Compiling against, say Android P/API-28, and using a minSDKVersion but no targetSDKVersion in the manifest (Xamarin calls it "automatic") and this code will work (I have Android P apps using the latest APIs running using the above code but they do not "target" a specific API level at runtime.)
But you are targeting a specific API >= Nougat thus you will have to implement a file provider to "share" even public files and thus provide content://-based uris to the app you are sharing to.

When using Android file provider, files don't have correct permissions despite FLAG_GRANT_WRITE_URI_PERMISSION being flagged in intent

I'm trying to load documents from files in my app using Microsoft Word and PDF viewers and I'm using a FileProvider to handle Android 7.0+ not allowing file URIs to be passed freely. I get the URI like so and and set the Intent flags to allow reading and writing before opening it, like so:
// From the byte array create a file containing that data, and get extension and MIME type.
File fileToOpen = byteArrayToFile(documentData, shortFileName);
String fileExtension = UtilityMethods.getFileExtension(fileToOpen.getName());
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
// Get the Uri for the file from the file provider, open using intent.
Uri documentUri = FileProvider.getUriForFile(getContext(), "com.mycompany.provider", fileToOpen);
Intent intent = new Intent();
intent.setDataAndType(documentUri, mime);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setAction(Intent.ACTION_VIEW);
startActivity(intent);
However when the file loads in MS Word the file is read only, and cannot be edited, which is not the desired behaviour. Where am I going wrong?

Android list applications that can view an unknown file

Hi I'm working on an app where I need to list all types of applications able to open a file. If the file were an image I would do something like this normally to show all applications capable of viewing the image.
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "image/*");
context.startActivity(intent);
However say I have an unknown file how could I list all applications able to view a file so the user can select the appropriate application to open the file in my application.
I also need the titles listed in an arraylist if possible so I can list them in a listview.
Thank you for any help with getting a list of applications capable of viewing a file
===================================
Edit
Alright well something easier how can i get the applications from the above intent into an arraylist i could just do image/* audio/* etc and add them all to a list and then list them in a listview and that would solve my problem
As far as i know there is no API in android that links files to a program like in windows. Your best choose I'm afraid is to build a database of known file types and program/android app linked to them.
Okay well i figured my problem out what i was looking for was
Intent audioIntent = new Intent(android.content.Intent.ACTION_VIEW);
audioIntent.setDataAndType(Uri.fromFile(Opener.file), "audio/*");
List<ResolveInfo> audio = packageManager.queryIntentActivities(audioIntent, 0);
for (ResolveInfo info : audio){
String label = info.loadLabel(packageManager).toString();
Drawable icon = info.loadIcon(packageManager);
String packageName = info.activityInfo.packageName;
String name = info.activityInfo.name;
iconlabel.add(a.new HolderObject(label, icon, audioIntent, "audio/*", packageName, name));
}
But the main thing in the code above is the queryIntentActivities method that was what solved my issue allowing me to add those apps to a list
This may help you to list the application that are capable of opening a particular file.
// extension : The file extension (.pdf, .docx)
String extension = filePath.substring(filePath.lastIndexOf(".") + 1);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
if (null == mimeType) {
// Need to set the mimetype for files whose mimetype is not understood by android MimeTypeMap.
mimeType = "";
}
File file = new File(filePath);
Uri data = Uri.fromFile(file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(data, mimeType);
context.startActivity(Intent.createChooser(intent, "Complete action using"));

Categories