尝试将文件附加到电子邮件意图的"附件权限被拒绝"(在Gmail 5.0上)

Edw*_*nch 9 permissions gmail android android-intent

这个问题之前已经发布过,但没有明确或接受的答案,所提供的所有"工作"的解决方案都不适合我.请参阅此处:Gmail 5.0应用程序在收到ACTION_SEND意图时失败并显示"附件权限被拒绝"

我有一个应用程序,它在文本文件中构建数据,需要在电子邮件中发送文本文件,自动附加它.我已经尝试了许多方法来实现这一点,它显然适用于Gmail 4.9及更低版本,但5.0具有一些新的权限功能,使其无法按照我的意愿行事.

    Intent i = new Intent(Intent.ACTION_SEND);

    String to = emailRecipient.getText().toString();

    i.setType("message/rfc822");
    i.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
    i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data");
    i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app.");
    String[] dataPieces = fileManager.getListOfData(getApplicationContext());
    for(int i2 = 0; i2 < dataPieces.length; i2++){
        i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2])));
    }
    i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()))));
    Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()));
    try {
        startActivity(Intent.createChooser(i, "Send Email"));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
Run Code Online (Sandbox Code Playgroud)

数据带可能是空的但是for循环下面的当前文件行总是可靠的并且总是附加一些东西.

我试过改变

Uri.fromFile()
Run Code Online (Sandbox Code Playgroud)

至

Uri.parse()
Run Code Online (Sandbox Code Playgroud)

当我这样做,它附加,但Gmail然后崩溃​​,当我检查logcat它是由于空指针.这很可能是因为Gmail无权访问该文件,因此结果为null.

我也试过用

getCacheDir()
Run Code Online (Sandbox Code Playgroud)

代替

getFilesDir()
Run Code Online (Sandbox Code Playgroud)

它有相同的结果.

我在这里做错了什么,我应该怎么做呢?一些示例代码真的非常方便,因为我是Android开发的新手,并解释我需要做什么,如果没有某种推迟可能不会最终帮助.

非常感谢.

Edw*_*nch 7

好吧,伙计们.想休息一下然后回来,想通了.

以下是它的工作原理,您需要对外部存储具有写入/读取权限,因此请将这些权限添加到清单中:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

然后,您的文件必须从应用程序的内部存储目录复制到应用程序的外部目录中.我建议你使用内部存储,这就是我在这里所做的,这样你就可以自己弄清楚SD卡了.

这是执行魔术的代码块.包含日志但您可以通过各种方式删除它们.

public void writeToExternal(Context context, String filename){
    try {
        File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source
        InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal
        OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to
        byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer
        Log.i("Available ", is.available() + "");
        int result = is.read(toWrite); //Read the data from the byte array
        Log.i("Result", result + "");
        os.write(toWrite); //Write it to the output stream
        is.close(); //Close it
        os.close(); //Close it
        Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename);
        Log.i("Copying from", context.getFilesDir() + File.separator + filename + "");
    } catch (Exception e) {
        Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there's an error, make a piece of toast and serve it up
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 问题和解决方案之间存在巨大差异 - 问题是关于共享应用程序的私有文件(来自context.getFiles()),并且在答案中它来自一般存储(~context.getExternalFilesDir())...不一样...... (6认同)