android.os.FileUriExposedException being caused in Oreo (only!) [duplicate]

你。 提交于 2019-12-08 03:00:17

问题


From the Google Play Console, I can see that this exception is only happening on devices with Android 8.0+.

android.os.FileUriExposedException: 
at android.os.StrictMode.onFileUriExposed (StrictMode.java:1975)
at android.net.Uri.checkFileUriExposed (Uri.java:2355)
at android.content.Intent.prepareToLeaveProcess (Intent.java:9975)
at android.content.Intent.prepareToLeaveProcess (Intent.java:9950)
at android.content.Intent.prepareToLeaveProcess (Intent.java:9929)
at android.app.Instrumentation.execStartActivity (Instrumentation.java:1622)
at android.app.Activity.startActivityForResult (Activity.java:4748)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult (BaseFragmentActivityJB.java:10)
at android.support.v4.app.FragmentActivity.startActivityForResult (FragmentActivity.java)
at android.support.v4.app.ActivityCompatJB.finishAffinity (ActivityCompatJB.java)
or                                         .startActivityForResult (ActivityCompatJB.java)
at android.support.v4.app.ActivityCompat.a (ActivityCompat.java:6)
at android.support.v4.app.FragmentActivity.a (FragmentActivity.java:8)
at android.support.v4.app.FragmentActivity$HostCallbacks.a (FragmentActivity.java:2)
at android.support.v4.app.Fragment.a (Fragment.java:38)
at android.support.v4.app.Fragment.a (Fragment.java:1)
at de.test.testapp.FileManagerFragment.onClick (FileManagerFragment.java:113)
at android.view.View.performClick (View.java:6291)
at android.view.View$PerformClick.run (View.java:24931)
at android.os.Handler.handleCallback (Handler.java:808)
at android.os.Handler.dispatchMessage (Handler.java:101)
at android.os.Looper.loop (Looper.java:166)
at android.app.ActivityThread.main (ActivityThread.java:7390)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:926)

the code:

Intent intent = new Intent(Intent.ACTION_VIEW);
ArrayList<Uri> uri = new ArrayList<Uri>();
for (int i=0; i<checkedItems.size(); i++) {
    if (checkedItems.valueAt(i)) {
        intent.setDataAndType(Uri.fromFile(new File(projectDir, filename), "text/plain");
    }
}
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent, "Open RINEX File"));

Manifest:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- To access Google+ APIs: -->
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="de.test.testapp"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_providers_paths" />
    </provider>
</application>

file_providers_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

Why does this work on Android 7 but not on Android 8 anymore? What behaviour changes have happened? I am calling this within a fragment.


回答1:


Try adding this inside onCreate.

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();



回答2:


If you have an app that shares files with other apps using a Uri, you may have encountered this error on API 24+.

This error occurs when you try to share a file:// Uri in an Intent broadcast to share data with other apps. Using file:// Uri’s are discouraged in this scenario because it makes some assumptions about the destination app. For one thing, we assume that the destination app has READ_EXTERNAL_PERMISSION which may not be the case. If the destination app does not have READ_EXTERNAL_PERMISSION, this may result in unexpected behaviour at best or at worst, result in a crash.

As of Android N, in order to work around this issue, you need to use the FileProvider API.

Step 1: Manifest Entry

<manifest ...>
    <application ...>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

Step 2: Create XML file res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Step 3: Code changes

File file = ...;
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
// Old Approach
install.setDataAndType(Uri.fromFile(file), mimeType);
// End Old approach
// New Approach
Uri apkURI = FileProvider.getUriForFile(
                         context, 
                         context.getApplicationContext()
                         .getPackageName() + ".provider", file);
install.setDataAndType(apkURI, mimeType);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// End New Approach
context.startActivity(install);



回答3:


This is cause from android 8 on wards whatever image you take programmatically won't be stored to the gallery, hence you cannot access the gallery files or its URI's, If implementing any image capturing functionality you need to implement and store the captured image to your resources folder and from there you will get the URI. Thats why we do

android:resource="@xml/file_providers_paths"

Actually its good from the security point of view for the user.



来源:https://stackoverflow.com/questions/48948370/android-os-fileuriexposedexception-being-caused-in-oreo-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!