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

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

我有一个应用程序,它build立在一个文本文件中的数据,并需要发送一个电子邮件中的文本文件,自动附加。 我已经尝试了很多方法来获得这个附加,它显然适用于Gmail 4.9及以下,但5.0有一些新的权限function,禁用它做我想做的事情。

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(); } 

数据空间可能是空的,但for循环下面的当前文件行总是可靠的,并且总是附着一些东西。

我试过改变

 Uri.fromFile() 

 Uri.parse() 

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

我也试过使用

 getCacheDir() 

代替

 getFilesDir() 

它有相同的结果。

我在这里做错了什么,我该如何去修复它? 一些示例代码将真的非常方便,因为我是Android开发新手,解释我需要做什么而不需要某种推送可能不会最终帮助。

非常感谢。

Solutions Collecting From Web of "试图将文件附加到电子邮件意图的“附件的权限被拒绝”(在Gmail 5.0上)"

好吧伙计们。 rest一下,回来了,算出来了。

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

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

然后,您的文件必须从应用程序的内部存储目录复制到应用程序的外部目录中。 我build议你使用内部存储,这就是我在这里做的,所以你可以自己找出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 } } 

遇到相同的附件被拒绝。 清单中的权限没有任何效果,而是自API 23以来没有任何效果。最后解决方法如下。

首先需要在运行时检查和授予权限,我在我的主要活动中做了:

 public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001; private void checkPermission(){ if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { // Show an explanation to the user asynchronously } else { // No explanation needed, we can request the permission. this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_STORAGE); } } } 

现在发送时,在PUBLIC目录中创build一个文件(尝试保存到我的应用程序文件夹 – 相同的拒绝问题)

 public File createFile(){ String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>"; File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html"); try { FileWriter writer = new FileWriter(file ,false); writer.write(htmlStr); } writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); return null; } return file; } 

现在使用uri将发送intent和putExtra组合到公用存储中的用户必须授予权限的文件,并且现在不会导致任何问题

 public void send(){ Intent intentSend = new Intent(android.content.Intent.ACTION_SEND); intentSend.setType("text/html"); File file = createFile(); if(file!=null){ intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); } startActivity(Intent.createChooser(intentSend, "Send using:")); }