如何使用FileProvider访问下载文件夹?

5
我制作了一个应用程序,可以在一个由该应用程序创建的文件夹中(同时也在Android的下载文件夹中)创建一个*.csv文件。
该文件可以通过ShareIntent共享,但问题是当该应用程序在Android Oreo上运行并且用户尝试创建*.csv文件时,应用程序会崩溃,抛出的异常为:
android.os.FileUriExposedException: 
  at android.os.StrictMode.onFileUriExposed (StrictMode.java:1958)
  at android.net.Uri.checkFileUriExposed (Uri.java:2348)
  at android.content.ClipData.prepareToLeaveProcess (ClipData.java:941)
  at android.content.Intent.prepareToLeaveProcess (Intent.java:9735)
  at android.content.Intent.prepareToLeaveProcess (Intent.java:9741)
  at android.content.Intent.prepareToLeaveProcess (Intent.java:9720)
  at android.app.Instrumentation.execStartActivity (Instrumentation.java:1795)
  at android.app.Activity.startActivityForResult (Activity.java:4495)
  at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult (BaseFragmentActivityJB.java:50)
  at android.support.v4.app.FragmentActivity.startActivityForResult (FragmentActivity.java:79)
  at android.app.Activity.startActivityForResult (Activity.java:4453)
  at android.support.v4.app.FragmentActivity.startActivityForResult (FragmentActivity.java:859)
  at android.app.Activity.startActivity (Activity.java:4814)
  at android.app.Activity.startActivity (Activity.java:4782)
  at com.bpl.spart.bloodpressurelogbook.MainActivity$createReportTask.onPostExecute (MainActivity.java:517)
  at com.bpl.spart.bloodpressurelogbook.MainActivity$createReportTask.onPostExecute (MainActivity.java:420)

我知道在API级别>24中应该使用FileProvider来创建Uri,但是如何使用FileProvider从Downloads文件夹中的文件获取访问权限?

这是我的当前代码:

        Intent ShareIntent = new Intent(android.content.Intent.ACTION_SEND);
        ShareIntent.setType("text/csv");
        ShareIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {getString(R.string.reporteTomasDePresion)});
        ShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, nombreReporte);

        ShareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
        startActivity(Intent.createChooser(ShareIntent, getString(R.string.compartirReporte)));

其中"f"是对.csv文件的引用。

public File getDocumentsStorageDir(String directorio){
    File file = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS),directorio);

    if(!file.mkdir()){
        Log.e("StatusArchivo","Directorio no creado");
    }

    return file;

}

        File file =  getDocumentsStorageDir(REPORTDIR);
        Calendar cal = Calendar.getInstance();
        //sdf = new SimpleDateFormat("dd-MM-yyyy-HH-mm");
        nombreReporte = "BPReport"+sdf.format(cal.getTime())+".csv";
        f = new File(file.getAbsolutePath(),nombreReporte);
        String csvFIle = "";
        String sistolicaS;
        String diastolicaS;
        String pulsoS;
        String posicionS;
        String extremidadS;
        String notaS;
        String fechaS;

        if(params[0].getCount() > 0 ) {

            try {
                OutputStreamWriter fout = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.ISO_8859_1);
                String nombre = getString(R.string.Nombre);
                String nombreDeUsuario = sharedPref.getString("nombreDelUsuario","");

                String edad = getString(R.string.Edad);
                String edadUsuario = sharedPref.getString("edadDelUsuario","");

                String peso = getString(R.string.Peso);
                String pesoUsuario = sharedPref.getString("pesoDelUsuario","");
                String UnidadDePeso = sharedPref.getString("unidadPeso",getString(R.string.kilos));

                String enfermedades = getString(R.string.Enfermedad);
                String enfermedadesUsuario = sharedPref.getString("enfermedadesDelUsuario","");

                String linea1 = nombre+": ," + nombreDeUsuario + "\n";
                fout.write(linea1);

                String linea2 = edad+": ," + edadUsuario + "\n";
                fout.write(linea2);

                String linea3 = peso+": ," + pesoUsuario + UnidadDePeso + "\n";
                fout.write(linea3);

                String linea4 = enfermedades+": ," + enfermedadesUsuario + "\n";
                fout.write(linea4);

                String tituloColumnas = getString(R.string.presionsistolica) + "," + getString(R.string.presiondiastolica) + "," + getString(R.string.pulsotil) + "," + getString(R.string.posiciontil) + "," + getString(R.string.extremidadtil) + "," + getString(R.string.notatil) + "," + getString(R.string.fechatil) + "\n";
                fout.write(tituloColumnas);


                params[0].moveToFirst();

                if (params[0].moveToFirst()) {
                    for (int j = 0; j < params[0].getCount(); j++) {

                        sistolicaS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.SISTOLICA));
                        diastolicaS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.DIASTOLICA));
                        pulsoS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.PULSO));
                        posicionS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.POSICION));
                        extremidadS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.EXTREMIDAD));
                        notaS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.NOTA));
                        fechaS = params[0].getString(params[0].getColumnIndex(Contrato.Columnas.FECHA));

                        Log.v("CSV1", csvFIle);
                        csvFIle = "\"" + sistolicaS + "\",\"" + diastolicaS + "\",\"" + pulsoS + "\",\"" + posicionS + "\",\"" + extremidadS + "\",\"" + notaS + "\",\"" + fechaS + "\"\n";
                        Log.v("CSV2", csvFIle);
                        fout.write(csvFIle);
                        params[0].moveToNext();

                    }
                }

                fout.close();
                c.close();
1个回答

3
我自己找到了答案,在我的paths.xml文件中我添加了以下内容:
<?xml version="1.0" encoding="utf-8"?>
<paths
    xmlns:android="http://schemas.android.com/apk/res/android">

    <external-path
        name="Descarga"
        path="Download/"/>

    <files-path name="nombre"
        path="reportes" />
</paths>

在Java中:

我进行了更改:

 ShareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
    startActivity(Intent.createChooser(ShareIntent,getString(R.string.compartirReporte)));

职位:

        Uri fileUri = FileProvider.getUriForFile(MainActivity.this,"com.bpl.spart.bloodpressurelogbook.fileprovider",f);

        ShareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
        startActivity(Intent.createChooser(ShareIntent, getString(R.string.compartirReporte)));

同时,在Android Oreo中,FileUriExposedException问题已经解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接