Google+ Photos ACTION_VIEW, FLAG_GRANT_PERSISTABLE_URI_PERMISSION Exception - android

In my app I have internal files that I would like to be able to open in external viewers depending on file type. I have a FileProvider set up like the following in the application manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.myapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/paths" />
</provider>
I user the following code to show an application selector in order to view the file.
Uri contentUri = getUriForFile(getApplicationContext(), "com.myapp.fileprovider", thisFile);
Intent viewIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = getApplicationContext().getContentResolver().getType(contentUri);
viewIntent.setDataAndType(contentUri, mimeType);
viewIntent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(viewIntent);
} catch(ActivityNotFoundException e) {}
This works well for most apps, however if I chose Google+ Photos app in the list, while the image will load fine in the Google+ Photos, it will crash immediately if I try too zoom in to the image by pinching with my fingers. It seem like Google+ Photos lost access to the file and when it tries to read it again it gets denied access.
All other apps I tried works perfectly
Any suggestions appreciated

Related

How to share app's private files via intent?

I am building a photo vault (that helps users hide photos) for Android 11 onwards since the birth of mighty "scoped storage" I am able to hide photos by just moving them to the app's private directory.
Now the problem arises when I want to share an image without moving it to the public (shared) directory.
I followed the implemented FileProvider, which converts the image path to URI but when I share the content URI via an intent, the following error pops up in logcat and the receiver application can not read the image.
Permission Denial: reading androidx.core.content.FileProvider uri content://com.androidbull.incognito.vaultreborn.provider/photos/Screenshot_20211221-105658.jpg from pid=10376, uid=1000 requires the provider be exported, or grantUriPermission()
Here is the code I wrote to perform sharing
val imagePath = File(this.filesDir, "photos")
val newImageFile = File(imagePath, currentImage.imageName)
val imageUri = FileProvider.getUriForFile(this, "$packageName.provider", newImageFile)
//
val shareContentIntent = Intent(Intent.ACTION_SEND)
shareContentIntent.data = imageUri
shareContentIntent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
startActivity(Intent.createChooser(shareContentIntent, null))
and just in case you are wondering here is the my provider in AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths">
</meta-data>
</provider>
And finally the file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="photos"
path="photos/" />
</paths>
Can anyone please help me here?
Thank you :)
Okay, so it turned out that there was a bug in my head, not in the code.
I was only testing it for the very first image that I moved into my vault, somehow this image was showing perfectly but had a file size of 0 bytes, so that was the problem. I tested other images and worked perfectly.
Thanks, everyone for paying attention :)

Passing file to other apps on a Huawai tablet with API level 24

My App is creating a PDF and passes it to other Apps to be displayed elsewhere. I create the file in internal storage to have to ask the user for less permissions.
I create my intent via:
Intent viewIntent = new Intent(Intent.ActionView);
Java.IO.File document = new Java.IO.File(filePath);
Android.Net.Uri contentUri = FileProvider.GetUriForFile(
_context,
_context.PackageName + ".provider",
document);
viewIntent.SetDataAndType(contentUri, GetMimeType(document));
viewIntent.SetFlags(ActivityFlags.NewTask);
viewIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
viewIntent.AddFlags(ActivityFlags.ClearTask);
viewIntent.AddFlags(ActivityFlags.GrantPersistableUriPermission);
viewIntent.AddFlags(ActivityFlags.GrantPrefixUriPermission);
viewIntent.AddFlags(ActivityFlags.GrantWriteUriPermission);
Intent chooser = Intent.CreateChooser(viewIntent, "");
chooser.SetFlags(ActivityFlags.NewTask);
chooser.AddFlags(ActivityFlags.GrantReadUriPermission);
chooser.AddFlags(ActivityFlags.ClearTask);
chooser.AddFlags(ActivityFlags.GrantPersistableUriPermission);
chooser.AddFlags(ActivityFlags.GrantPrefixUriPermission);
chooser.AddFlags(ActivityFlags.GrantWriteUriPermission);
_context.StartActivity(viewIntent);
On the Google Pixel 3 XL where I test, I can open a PDF without any issues.
When I do the same on a Huawei tablet with API level 24, sometimes everything works but at other times Adobe Acrobat shows an error: This file could not be accessed. Check the location or the network and try again.
The behavior isn't deterministic, sometimes I get the error but other times everything works fine.
In the Application node of your Android Manifest make sure you've added a FileProvider definition:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.FileProvider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/provider_paths" />
</provider>
Add a Resources/xml/provider_paths file with the contents:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
You can restrict this later if needed. However, for my use case I put files in external storage, which I share from. You need to adjust this accordingly where you are sharing from.
I.e. if you are sharing the file from internal app storage you will need to add a files-path definition there too.
Then when sharing a file you simply do:
var packageName = context.ApplicationInfo.PackageName;
var fileProviderName = $"{packageName}.FileProvider";
var intent = new Intent(Intent.ActionSend);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
intent.SetType("image/*"); // change mime type if wanting to open in other app
intent.PutExtra(Intent.ExtraStream,
FileProvider.GetUriForFile(context, fileProviderName, new Java.IO.File(filePath)));
StartActivity(intent);
That should be enough, works fine every time for me for sharing images to another app. I don't think you need the flags for your chooser Intent, only for the inner viewIntent. Also the GrantReadUriPermission should be the only thing needed if you are providing flags.

Upload excel file to Dropbox or Google Drive?

I'm currently developing an application which creates an excel file(with apache poi) from the sqlite database in android. Everything is working well, except that I can't send the file to another app.
I implemented an fileprovider so I other apps can have permission to my file:
AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.ria.masterdetailnoten"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="backup" path="backup/"/>
</paths>
ExcelFile.java:
Uri uriFile = FileProvider.getUriForFile(ct, "com.example.ria.masterdetailnoten", backupFile);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setDataAndType(uriFile, "application/vnd.ms-excel");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.createChooser(intent, "Choose");
ct.startActivity(intent);
I know for sure that my file is being created and I can read it again with Apache POI. So the only things which doesn't work is sending the intent to another app.
As an example if I choose Google Drive in the intent chooser then following error appears:
"Upload failed: request contained no data."
If I open it with the Mailbox App following error appears:
"Mailbox could not read the selected file"
I hope you can help me guys, I appreciate your help!
Have you tried using: putExtra(Intent.EXTRA_STREAM, uriFile) instead of: setData(AndType)?
I've managed to work this out with intent.selector = Intent(Intent.ACTION_SEND).apply { data = Uri.parse("file:") }

File provider - Files not accessible even in the own app

I am implementing a File Provider, followed the doc carefully but unable to use the files in the app itself or share any file.
Added manifest, created xml file for dir sharing, generating content uri, granting uri permission, tried sharing files with cache, external, internal dir but nothing is working.
Searched the net but found nothing which is missing in the code.
Below is the code:
Manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="package.widget.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
filepaths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="widgetDoc" path="."/>
</paths>
GetUri:
private Uri getFileUri(Context context, String name){
File newFile = new File(context.getCacheDir() + File.separator + StorageUtil.INTERNAL_DIR, name);
Uri contentUri = FileProvider.getUriForFile(context, "package.widget.fileprovider", newFile);
return contentUri;
}
Code to access pdf file:
Intent target = new Intent(Intent.ACTION_VIEW);
Uri uri = getFileUri(getApplicationContext(), file);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(uri,"application/pdf");
Intent intent = Intent.createChooser(target, "Choose Pdf Viewer...");
startActivity(intent);
Code to access image:
imageview.setImageURI(getFileUri(getApplicationContext(), file));
Kindly help me out where I am going wrong, not even able to use these files in my own app too.
Thanks in advance.
I need to show these image files in a widget and now if am accessing the image files from the widget then it is giving IllegalArgumentException: Failed to find configured root however it is working fine with activity
Ideally, use setImageViewBitmap(), and make sure that your image is small (under 1MB in heap space, such as less than 512x512).
While the RemoteViews can accept a Uri, you have good way of associating Intent.FLAG_GRANT_READ_URI_PERMISSION with a RemoteViews for the purposes of populating an ImageView. And, you cannot export your FileProvider, as FileProvider does not allow that.
You can attempt to identify the user's chosen home screen and use grantUriPermission() to grant the home screen access to this Uri, but I would expect that solution to be fragile.

issue opening document using FLAG_GRANT_WRITE_URI_PERMISSION intent ANDROID

I would like to open my documents saved in application storage using third party applications like polaris office,quickoffice,kingsoft docs etc using chooser.I would like to grant permission to edit the document as well.
If i open the document using FLAG_GRANT_READ_URI_PERMISSION,the document opens fine but if i use FLAG_GRANT_WRITE_URI_PERMISSION insted the external application pushedup but donot display the document selected.Incase of polaris office,the document opens fine using FLAG_GRANT_READ_URI_PERMISSION but if i use FLAG_GRANT_WRITE_URI_PERMISSION it says document type not supported.
The code i use is
File file = new File(
getFilePath(data.getUniqueId(), data.getFileName()));
Uri uri = FileProvider.getUriForFile(context, "com.example.com",
file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_EDIT);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Intent chooserIntent=Intent.createChooser(intent, uri.toString());
context.startActivity(chooserIntent);
In manifest i have mentioned
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.com"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/my_paths" />
</provider>
Please let me know where i am wrong.
I would like to provide temporary permission to third part apps to open and edit the document selected.The documents need to be stored in application storage space.
instead of the line:
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
just put the line:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
I think your provider should also have android:exported attribute set to true (in order to be used by other applications).

Categories

Resources