Unable to open trivial text file with FileProvider - android

I'm going crazy, I used the new Android FileProvider in the past but I can't get it to work with a (trivial) just-created file in the Download folder.
In my AsyncTask.onPostExecute I call
Intent myIntent = new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider", output));
myIntent.setType("text/plain");
myIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(myIntent);
My FileProvider XML is like this
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="Download" path="Download"/>
</paths>
In Genymotion emulator I always get, choosing Amaze Text Editor as target app:
While I can see the file content with HTML Viewer:
I can't understand this behavior and fix what should be a trivial thing like opening a pure-text file with the desidered text editor.
thanks a lot
nicola

OK, there are two problems here. One is a bug in your code that triggers a bug in Amaze, and one is a bug in Amaze that you can work around.
setType() has a nasty side effect: it wipes out your Uri in the Intent. It is the equivalent of calling setDataAndType(null, ...) (where ... is your MIME type). That's not good. So, instead of putting the Uri in the constructor and calling setType(), call setDataAndType() and provide the Uri there.
This gets you past the initial Amaze bug, where they fail to handle a null Uri correctly.
Then, though, they try to open the Uri in read-write mode. You are only granting read access, so this fails. Their second bug is that they think that they get a FileNotFoundException when they cannot open the file in read-write mode, and at that point they try read-only mode. In reality, at least on Android 8.1, they get a SecurityException. You can work around this by providing both read and write permissions.
So, unless you specifically want to block write access, this code works:
Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setDataAndType(FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider", output), "text/plain");
myIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivity(myIntent);

Related

Open default Photos app with specific album / folder

Unfortunately, all existing answers to this topic are totally outdated.
I wish to launch an Intent that will open an external app with a specific images folder.
Since Android 7.0, the following method does not work:
Intent i=new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(new File(path)), "image/*");
startActivity(i);
I am trying using a FileProvider.
MyFileProvider:
public class MyFileProvider extends FileProvider {
}
from AndroidManifest.xml:
<provider
android:name=".util.MyFileProvider"
android:authorities="${applicationId}.common.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/my_file_paths"/>
</provider>
my_file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="files"
path="/My_bugreport"/>
<external-path name="external_files" path="."/>
</paths>
Intent launch code in main activity onCreate():
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "/Pirin 1/"; // Some hard-coded folder I have on my device
Log.d(TAG, "MyDashboardActivity: onCreate: path=" + path);
Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".common.fileprovider", new File(path));
grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.setDataAndType(uri, "image/*");
startActivity(i);
I am getting the Photos app with an empty black screen and a spinning loader.
LogCat doesn't contain any useful info.
Device: Google Pixel 3
Tried many things already, many different paths, etc., almost giving up...
I wish to launch an Intent that will open an external app with a specific images folder.
There is no official support for this in Android.
Unfortunately, all existing answers to this topic are totally outdated.
Any answer other than "there is no reliable way to do this" is wrong.
Since Android 7.0, the following method does not work
It does not work prior to Android 7.0 either. If path points to a directory, then you are lying to the third-party app, saying that there is an image at that location, when there is no image there (since it is a directory, not a file). I would expect most ACTION_VIEW apps to not handle that well. Expecting them to magically show the contents of the directory is just wishful thinking — there is no requirement for an app that supports ACTION_VIEW for an image to have any ability to show the contents of a directory, let alone fall back to that behavior upon receiving a corrupt ACTION_VIEW Intent.
I am trying using a FileProvider
FileProvider does not serve directories in a way that would fit your needs. For example, there is no means with FileProvider to get the list of content at a particular directory.
Moreover, since ACTION_VIEW does not support directories, you would be back where you started.
(also note that your grantUriPermission() call isn't going to do anything meaningful)

How to simply open directory/folder?

DONT mark this as duplicate, before reading what I need.
I have seen many similar topics, but in none of them I've found solution.
I need the simplest thing: In my application I have button "View Media Files". After clicking that button, i need to be opened (with built-in File Explorer) this directory - SD_CARD/my_folder where are media files (and I want to click any of them and they should be opened in default Media player)..
I have used all suggested answers on SO , like this:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri mydir = Uri.parse("/sdcard/Recorder_Videos");
intent.setDataAndType(mydir, "*/*");
startActivity(intent);
but all they do: after clicking button, it opens "Choose File" menu:
(Where I cant still play media files when clicking)
The solution (not complete) I have found, was that I was missing file:// prefix. Here is my solution (however, it shows all kinds of applications on first view):
public void openFolder(String location)
{
// location = "/sdcard/my_folder";
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri mydir = Uri.parse("file://"+location);
intent.setDataAndType(mydir,"application/*"); // or use */*
startActivity(intent);
}
p.s. Strange and surprising, but there doesnt exist the standard definition of "File Browser" in stock Android systems (unless you install 3rd party "File Explorer")..
That's why "resource/folder" mime-type doesnt work by default..
However, let's say a simple truth. File-Browser is a SIMPLE and ESSENTIAL part of any OS system. And it's quite disrespectful from Android, saying that it's not their job, and throwing the responsiblity to 3rd party apps.
You can use type DocumentsContract.Document.MIME_TYPE_DIR which works on several devices and launches File Explorer. You can refer this SO for more details.

E/PdfViewerActivity: fetchFile:file: java.io.FileNotFoundException: file does not exist

I'm trying to open a pdf after creating it via an intent. The file exists and is readable but save inside the apps directory.
Currently the file is saved in the following manner
OutputStream out;
try {
//TODO: expose through a content provider
out = mContext.openFileOutput(outputFileName, Context.MODE_WORLD_READABLE);
document.writeTo(out);
out.close();
and the file is sent to an intent with the following code
final Intent viewIntent = new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
viewIntent.setDataAndType(Uri.fromFile(file), "application/pdf");
mActivity.startActivity(viewIntent);
The app trying to open it is the google drive viewer and I see in the Android monitor
E/PdfViewerActivity: fetchFile:file: java.io.FileNotFoundException: file does not exist
This previously worked and I don't think I've changed anything related to this code however I have updated my tooling. I've tried changing the buildToolsVersion in the build.gradle back to what it was before as well as the support libraries 'com.android.support:appcompat-v7:22.+' and 'com.android.support:design:22.+' instead of version 24.2.1
I've tried using the debugger to set the file to be readable just before sending the intent but that did not work.
Thanks
I found the answer starting with the Android 7 Behavior Changes documentation. Sharing files is no longer allowable when setting MODE_WORLD_READABLE even though the documentation doesn't mention any of this
I followed the documentation on sharing files to fix the issue but the sample code in the documentation was more complicated than what I needed. I still had to add the file provider to the AndroidManifest.xml as well as create the fileprovider.xml.
The resulting code is now
final Intent viewIntent = new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
Uri fileUri = FileProvider.getUriForFile(mActivity, "my.authority.fileprovider", file);
viewIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
viewIntent.setDataAndType(fileUri, "application/pdf");

Android Attaching a file to GMAIL - Can't attach empty file

I had a program that would always attach the same file to GMAIL (Compose > Attach File > Open From > "MyProgram"). It would always select the same file.
What it was doing was:
String path = Environment.getExternalStorageDirectory() + "/file.3gp";
File f = new File(path);
Uri data = Uri.fromFile(f);
Intent i = new Intent();
i.setData(data);
setResult(Activity.RESULT_OK, i);
finish();
This was working fine until Android 6.0.
Now, I receive the following error when trying to use it:
Can't attach empty file
Astro File Sharing is giving me the same error (can be an old build).
However, I installed ES File Explorer, and when I do the same routine, and select the file, I receive a Dialog which says:
Pick up file as
Normal Android Way (For MMS,Gmail,...)
File Way (Try this if above fails)
The "File Way" will fail as my program does. The "Normal Android Way" will work fine.
Does anyone have any idea on what it does, so I can replicate?
Thanks in advance!
OBS: Already tried the putExtra(STREAM, path) a lot of times, but without success.
Ok, got it to work now, after a lot of research and intercepting some Intents.
What I had to do was change the file:/// to content://.
I did this following this information from Android: https://developer.android.com/reference/android/support/v4/content/FileProvider.html
The only major change was that I used a hard-coded path to /sdcard/file.ext.
Also, the line
getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
was changed to
Uri contentUri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", newFile);
Also had to include:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
i.setData(contentUri);
I do not really understand why I had to change from File to Content, but after this, the file is now being attached again! See the link if you face this issue, and don't forget about the new .xml that needs to be created.
See the following question:
android-6-cannot-share-files-anymore
This behavior is with Android 6.0 and Gmail. Please see the following thread.
Issue 3141 - android-developer-preview
If you go to Settings->Apps->Gmail->Permissions and enable the
"Storage" permission manually, then the share works.
Gmail should ask for "Storage" permission in this scenario and it
would work as it did in all the past version of Android.
Other email apps should handle attachments correctly.
Here is how to fix it.
Go to Settings -> Apps -> Gmail -> Permissions
Turn on the permission for "Storage"
That work-around solved the issue for me.
I couldn't find a clear answer(sending an attachment on gmail without SD card) I tried to copy to another file name but no cigar. The way I got it to work was copy to the Downloads folder and go from there.
Get the path for Downloads with this
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
pulls the full path to downlaods folder copy the attachemnt to there and we are good. Files over 20M don't go
Share any file using INTENT provided given file path
//File file= shareable File Path
Uri uri = FileProvider.getUriForFile(this, "com.example.myapp.fileprovider", file);
//FileProvider authorities from Manifest
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("*/*");
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(sharingIntent);
Just match your authorities from the manifest in arguments of method getUriForFile.
In Manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>

Opening a local Android File with spaces

I am trying to open a local file in Android (4.0) using intents. The following is the code to do the action. This works fine as long as the file has no special spaces (For example: if the file is /data/data/com.xxxx.yyyy/files/Downloads/Documents/ProductFeature.pptx, the it opens fine, but if the file name is /data/data/com.xxxx.yyyy/files/Downloads/Documents/Product Feature.pptx (note the space in name), then it fails. The Uri.fromFile encodes the space correctly, but the other apps cant seem to interpret them and seem fail opening.
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(new File( selectedEntry.get(Defs.PATH_KEY)));
System.out.println("openFileWith: File to open: " + uri);
intent.setDataAndType(uri,type);
startActivity(Intent.createChooser(intent, "Open With ..."));
I also tried to use "file://" + unencoded path without much help.
So how do you handle this condition? Any help is appreciated
You need to replace the spaces with "\ ". Note that if you are using String.replace() then you need to escape the slash as well ("\\ ").
The main problem for me turned out to be I was storing files in application directory of internal storage and the access to the files had to be given explicitly. I was giving permissions using chmod 755 command. But the files with spaces were not getting the permissions set correctly which prevented those files being opened.
I have since moved to use external (Activity.getExternalFilesDir()) and that folder allows access permission to every other application and that solved the issue for me.

Categories

Resources