Wrong name of the shared file when choosing the app from Intent.createChooser - android

My app can share internally stored files with the androidx.core.content.FileProvider.
The intent and the chooser are created with the following snippet:
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(
Intent.EXTRA_STREAM,
FileProvider.getUriForFile(this, authority, file, displayName),
)
type = document.mimeType.mediaType
}
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_title)))
I explicitly pass the displayName to the FileProvider, but in the app chooser, I see the file's local name (see image).
Is there a way to show the correct display name in the chooser?

Related

how to open files using intent action with latest Android storage framework?

Since Android introduced major changes in storage framework recently much of the documentation talks about permissions and scoped storage. But I couldn't find details on how to process Uri of a file, for it to be readable by other apps.
The intent action to view/read a file by other apps fail. I don't understand what's the problem here;
Does it have to do with difference between java.io.File and java.nio.File?
The Uri has missing permissions or the Uri is not well formatted.
The Android storage samples (FileManager) has this bug as well. It lists all the files in a directory successfully but can't open a selected image, or a document. I've reported this issue but no help so far.
Following snippet is from FileManager (storage-samples)
fun openFile(activity: AppCompatActivity, selectedItem: File) {
// Get URI and MIME type of file
val uri = Uri.fromFile(selectedItem).normalizeScheme()
val mime: String = getMimeType(uri.toString())
// Open file with user selected app
val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.data = uri
intent.type = mime
return activity.startActivity(intent)
}
After the hints from the comments, I found the answer in developer docs.
Caution: If you want to set both the URI and MIME type, don't call setData() and setType() because they each nullify the value of the other. Always use setDataAndType() to set both URI and MIME type.
The reason behind openFile didn't throw FileUriExposedException in android-storage-samples is that after setting intent.type, the Uri gets nullified and when I changed it to setDataAndType() I got the exception. The final snippet looks like
fun openFile(activity: AppCompatActivity, selectedItem: File) {
// Get URI and MIME type of file
val uri = FileProvider.getUriForFile(activity.applicationContext, AUTHORITY, selectedItem)
// val uri = Uri.fromFile(selectedItem).normalizeScheme()
val mime: String = getMimeType(uri.toString())
// Open file with user selected app
val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
// intent.data = uri
// intent.type = mime
intent.setDataAndType(uri, mime)
return activity.startActivity(intent)
}
I think they forgot to update the samples over time, let me create a pull request to commit this change over there as well.

How to open DCIM/Camera folder in default Files app from intent

I am making a camera app which takes both front camera and back camera images/video and I do not want individual thumbnails on the Camera preview for each file.
I want to open "/storage/emulated/0/DCIM/Camera" folder using the Files app and further open the photo/video which is not possible with ACTION_GET_CONTENT as it selects the image and exits the Files app as tried here -
val intent = Intent(Intent.ACTION_GET_CONTENT)
val uri: Uri = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path.toString() + "/Camera")
intent.setDataAndType(uri, "*/*")
startActivity(Intent.createChooser(intent, "Open folder"))
I tried ACTION_VIEW too, but it is not specific to one folder and opens the gallery showing all media as tried here -
val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.type = "image/*"
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
"image/*" shows images and videos too in the gallery for me which is good. When "*/*" is used we can use the Files app too but it opens the downloads folder.
One solution I found works only with ES Explorer as tried here -
val uri: Uri = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path.toString() + "/Camera")
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "resource/folder")
startActivity(intent)
This is due to "resource/folder" not supported leading to a crash. Changing "resource/folder" to "*/*" makes Files app open the downloads folder and Photos app to hang.
It seems gallery can do it via buckets, but it too is not universal.
I am not asking for much, just to display my Camera folder from where I can open and view any photo/video.
It was not possible if the user had not once selected a file using ACTION_GET_CONTENT was the opinion.
But now... try this code:
String scheme = "content://com.android.externalstorage.documents/document/primary%3APictures";
// String scheme = "content://com.android.externalstorage.documents/document/primary%3ADCIM%2FCamera";
Uri uri = Uri.parse(scheme);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri); // Added in API level 26
startActivityForResult(intent, 12345);
Toast.makeText(context, "Picker opened in:\n\n" + uri.toString(), Toast.LENGTH_LONG).show();
It works here and i'm pretty amazed.
To open the Files app starting with a certain folder you can use below code but only for Android 11 devices sadly.
//String scheme = "content://com.android.externalstorage.documents/document/primary%3APictures";
//String scheme = "content://com.android.externalstorage.documents/document/primary%3ADownload";
//String scheme = "content://com.android.externalstorage.documents/document/10F9-2E19%3ADownload";
String scheme = "content://com.android.externalstorage.documents/document/primary%3ADCIM%2FCamera";
Uri uri = Uri.parse(scheme);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "vnd.android.document/root");
startActivity(intent );
Toast.makeText(context, "Files app opening in:\n\n" + uri.toString(), Toast.LENGTH_LONG).show();

How to open a uri in file manager in Android

I'm trying to make a button in my app when user click on it, it'll open a specific URI in file manager but the best I could've done is that the button opens recent tab in default file manager.
Please, if it's possible, suggest me a code which opens a chooser for user to choose between his file manager applications and when user chose, that file manager opens in specific URI that I defined in my code.
Here is my code:
val intent = Intent(Intent.ACTION_GET_CONTENT)
val uri = Uri.parse(
//my path
)
intent.data = uri
intent.type = "*/*"
startActivity(Intent.createChooser(intent, "Open folder"))
Also one of the users suggested me to use INITIAL_URI I've did it like this but didn't work :
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
val uri = Uri.parse(
//my path
)
intent.data = uri
intent.type = "*/*"
intent.putExtra("android.provider.extra.INITIAL_URI", uri)
intent.putExtra("android.content.extra.SHOW_ADVANCED", true)
startActivity(Intent.createChooser(intent, "Open folder"))
suggest me a code which opens a chooser for user to choose between his file manager applications and when user chose, that file manager opens in specific URI that I defined in my code
That has never been a pattern in Android app development. There is no standard Intent action for what you seek that is likely to be implemented by much of anything, let alone a significant number of file manager apps.
fun openNewTabWindow(urls: String, context : Context) {
val uris = Uri.parse(urls)
val intents = Intent(Intent.ACTION_VIEW, uris)
val myV = Bundle()
myV.putBoolean("new_window", true)
intents.putExtras(myV)
context.startActivity(intents)
}

Android - Retrieve file after ACTION_GET_CONTENT intent

I need my user to upload a file in the app. For that purpose, I used an intent
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "application/pdf"))
}
startActivityForResult(intent, IMPORT_INTENT_CODE)
That intent is working, I can select an image from the phone storage.
However, in the onActivityResult I cannot retrieve the file I selected. When I try to get the file from the URI, I get a nonexisting file.
My final purpose is to get a base64 value for the file but I cannot access the file.
What should I do?

Content provider grant uri permission

I searched and read android developer files but I did not find any satisfactory answer for content provider grant uri permission. Can anybody explain more detailed and more simple. My questions are:
What grant uri is using for?
What is the differences between grant uri permission true and false
When we should use true? when false?
and any more detail are appreciated.
What grant uri is using for?
The "grant Uri permissions" feature allows you to have a ContentProvider that is normally inaccessible by third parties, yet selectively allow access to individual Uri values to individual third-party apps for a short period of time (e.g., long enough to view the PDF that the provider serves).
What is the differences between grant uri permission true and false
android:grantUriPermissions="true" indicates that your Java code can use FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION for any Uri served by that ContentProvider.
android:grantUriPermissions="false" indicates that only the Uri values specified by child <grant-uri-permission> elements can be used with FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION.
Say you need to mail some file that is on your application cache directory.
No other apps can access that file, unless you specify that other apps can access content of your application. For this you create content provider, and say, all uri's in form content://com.your.app/file you 'redirect' to your application cache directory.
Some code:
File f = ...; // Some local file.
Uri uri = Uri.parse("content://com.your.app/" + f.getName());
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Body");
intent.putExtra(Intent.EXTRA_STREAM, uri);
// You only can add flag FLAG_GRANT_READ_URI_PERMISSION if your app has
// android:grantUriPermissions="true" in manifest or see quote below.
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intent, "Send Email"));
As CommonsWare said:
android:grantUriPermissions="false" indicates that only the Uri values
specified by child <grant-uri-permission> elements can be used with
FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION.
with adapter class and In Kotlin :-
val uri: Uri? = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID, file)
val sharingIntent = Intent(Intent.ACTION_SEND)
sharingIntent.type = "image/*"
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Images ")
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri)
val chooser = Intent.createChooser(sharingIntent, "Share File")
val resInfoList: List<ResolveInfo> = mContext.packageManager
.queryIntentActivities(chooser, PackageManager.MATCH_DEFAULT_ONLY)
for (resolveInfo in resInfoList) {
val packageName = resolveInfo.activityInfo.packageName
mContext.grantUriPermission(
packageName,
uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
mContext.startActivity(chooser)

Categories

Resources