【问题标题】:cannot display PDF file from assets folder as MODE_WORLD_READABLE no longer supported无法显示资产文件夹中的 PDF 文件,因为不再支持 MODE_WORLD_READABLE
【发布时间】:2018-04-29 14:37:57
【问题描述】:

以下代码在使用 API 22 的设备中运行良好,但在使用 API 24 的设备中会出现以下错误:

java.lang.SecurityException: MODE_WORLD_READABLE no longer supported

这是我的代码:

private void CopyReadAssets(String filename) {
    AssetManager assetManager = getAssets();
    InputStream in = null;
    OutputStream out = null;
    File file = new File(getFilesDir(), filename);

    try {
        in = assetManager.open(filename);
            out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);

        copyFile(in, out);
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file),"application/pdf");

        startActivity(intent);
    } catch (Exception e)
    {
        Log.e("cra",e.toString());
        Toast.makeText(PdfFilesList.this, "cra: "+e.toString(), Toast.LENGTH_SHORT).show();
    }
}

如果我将 MODE_WORLD_READABLE 更改为 MODE_PRIVATE,它将停止在所有设备中工作。 使用 API 22 的设备会出现以下错误

11-16 12:00:53.133 16531-31103/? E/DisplayData: openFd: java.io.FileNotFoundException: Permission denied
11-16 12:00:53.134 16531-31103/? E/PdfLoader: Can't load file (doesn't open)  Display Data [PDF : 818 New Jeevan Nidhi.pdf] +FileOpenable, uri: file:///data/data/com.user.plansmart/files/818%20New%20Jeevan%20Nidhi.pdf

API 24 的设备抛出以下异常

11-16 12:05:00.100 2682-2682/com.user.plansmart E/cra: android.os.FileUriExposedException: file:///data/user/0/com.user.plansmart/files/827%20Jeevan%20Rakshak.pdf exposed beyond app through Intent.getData()

谁能帮我解决这个问题。

谢谢。

【问题讨论】:

  • cannot-display-pdf-file-from-assets-folder 信息错误。您正试图让外部应用程序从您的应用程序内部存储中显示一个 pdf 文件。不是来自资产。

标签: android pdf android-assets android-fileprovider file-uri


【解决方案1】:

您应该使用 FileProvider 通过 Intent.ACTION_VIEW 提供您的文件。

这样你就可以在这个网站上找到很多代码了。

【讨论】:

  • 是的,我开始意识到这只能通过 Fileprovider 完成,是的,有很多代码,但没有一个能满足我的需要。我只是在等待是否有人可以在这里帮助我。
【解决方案2】:

找到了一种解决方法,而不是使用 MODE_WORLD_READABLE,因为查看了 here

int MODE_WORLD_READABLE 此常量在 API 级别 17 中已弃用。 创建世界可读的文件是非常危险的,并且可能会导致应用程序中的安全漏洞。强烈建议不要这样做;相反,应用程序应该使用更正式的交互机制,例如 ContentProvider、BroadcastReceiver 和 Service。无法保证此访问模式将保留在文件上,例如在进行备份和恢复时。

private void CopyReadAssets(String filename) {
    AssetManager assetManager = getAssets();
    InputStream in;
    OutputStream out;

    try {
        in = assetManager.open(filename);
        String outDir = Environment.getExternalStorageDirectory().getAbsolutePath();

        File outFile = new File(outDir, filename);
        if(outFile.createNewFile()){
            return;
        }

        out = new FileOutputStream(outFile);

        copyFile(in, out);
        in.close();
        out.flush();
        out.close();

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(outFile), "application/pdf");

        startActivity(intent);
    } catch (Exception e) {
        Log.e("cra", e.toString());
        Toast.makeText(this, "cra: " + e.toString(), Toast.LENGTH_SHORT).show();
    }
}

对于设备,在 M 之后需要单独请求权限。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission
                        .READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                102);
    }
} else {
    CopyReadAssets("yourpdf.pdf");
}

然后在 onRequestPermissionsResult 实现,你的代码。

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case 102:
            CopyReadAssets("yourpdf.pdf");
            break;
    }
}

希望对你有帮助

【讨论】:

  • 它有帮助,但只是部分,你仍然会有文件 uri 暴露异常。
  • @greenapps 你是对的,使用 FileProvider 是正确的方法
  • 是的,这必须通过 FileProvider 来完成,否则它会抛出 FileUriExposedException。你们中的哪一位可以建议解决方案代码吗?
猜你喜欢
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 2015-09-18
  • 2017-09-09
  • 2018-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多