当我试图打开一个文件时,应用程序崩溃了。它可以在Android Nougat下运行,但在Android Nougat上它会崩溃。只有当我试图从SD卡,而不是从系统分区打开文件时,它才会崩溃。权限问题?

示例代码:

File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line

日志:

android.os.FileUriExposedException: ///storage/emulated/0/test.txt Intent.getData ()

编辑:

当针对Android Nougat时,file:// uri不再被允许。我们应该使用content:// uri。但是,我的应用程序需要打开根目录下的文件。什么好主意吗?


当前回答

我把这种方法使imageuri路径容易获得内容。

enter code here
public Uri getImageUri(Context context, Bitmap inImage)
{
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.PNG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), 
    inImage, "Title", null);
    return Uri.parse(path);
}

其他回答

以下是我的解决方案:

在Manifest.xml

<application
            android:name=".main.MainApp"
            android:allowBackup="true"
            android:icon="@drawable/ic_app"
            android:label="@string/application_name"
            android:logo="@drawable/ic_app_logo"
            android:theme="@style/MainAppBaseTheme">

        <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/provider_paths"/>
        </provider>

在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>

在我的片段中,我有下面的代码:

 Uri myPhotoFileUri = FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", myPhotoFile);               
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, myPhotoFileUri);

Тhat就是你所需要的。

也不需要创造

public class GenericFileProvider extends FileProvider {}

我在Android 5.0, 6.0和Android 9.0上进行了测试,并取得了成功。

这是

 val uri = if (Build.VERSION.SDK_INT < 24) Uri.fromFile(file) else Uri.parse(file.path)
                val shareIntent = Intent().apply {
                    action = Intent.ACTION_SEND
                    type = "application/pdf"
                    putExtra(Intent.EXTRA_STREAM, uri)
                    putExtra(
                        Intent.EXTRA_SUBJECT,
                        "Purchase Bill..."
                    )
                    putExtra(
                        Intent.EXTRA_TEXT,
                        "Sharing Bill purchase items..."
                    )
                }
                startActivity(Intent.createChooser(shareIntent, "Share Via"))

简单地让它忽略URI暴露… 在创建之后添加它

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

@palash k答案是正确的,适用于内部存储文件,但在我的情况下,我想从外部存储打开文件,我的应用程序崩溃时从外部存储如sdcard和usb打开文件,但我设法通过修改provider_paths.xml从接受的答案解决了这个问题

像下面那样修改provider_paths.xml

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

<external-path path="Android/data/${applicationId}/" name="files_root" />

<root-path
    name="root"
    path="/" />

</paths>

和在java类(没有改变作为接受的答案,只是一个小编辑)

Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)

这帮助我修复了外部存储文件的崩溃,希望这将帮助一些人有同样的问题,我的 :)

如果targetSdkVersion大于24,则使用FileProvider授予访问权。

创建一个xml文件(路径: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>

在AndroidManifest.xml中添加一个Provider

    <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>

如果你正在使用androidx, FileProvider路径应该是:

 android:name="androidx.core.content.FileProvider"

和替换

Uri uri = Uri.fromFile(fileImagePath);

to

Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);

编辑:当你用Intent包含URI时,请确保添加以下一行:

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

这样就可以开始了。