Unable to open trivial text file with FileProvider

2019-07-24 16:44发布

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: enter image description here

While I can see the file content with HTML Viewer: enter image description here

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

1条回答
做自己的国王
2楼-- · 2019-07-24 17:34

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);
查看更多
登录 后发表回答