当接收到ACTION_SEND意图时,Gmail 5.0应用程序失败,并且“权限拒绝附件”

我的应用程序创build附件的邮件,并与Intent.ACTION_SEND使用意图启动邮件应用程序。

它适用于我testing过的所有邮件应用程序,除了新的Gmail 5.0(它适用于Gmail 4.9),邮件打开时没有附件,显示错误:“拒绝附件的权限”。

在logcat上没有来自Gmail的有用消息。 我只在Android KitKat上testingGmail 5.0,但在多个设备上testing。

我创build了这样的附件文件:

 String fileName = "file-name_something_like_this"; FileOutputStream output = context.openFileOutput( fileName, Context.MODE_WORLD_READABLE); // Write data to output... output.close(); File fileToSend = new File(context.getFilesDir(), fileName); 

我知道MODE_WORLD_READABLE的安全问题。

我发送这样的意图:

 public static void compose( Context context, String address, String subject, String body, File attachment) { Intent emailIntent = new Intent(Intent.ACTION_SEND); emailIntent.setType("message/rfc822"); emailIntent.putExtra( Intent.EXTRA_EMAIL, new String[] { address }); emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject); emailIntent.putExtra(Intent.EXTRA_TEXT, body); emailIntent.putExtra( Intent.EXTRA_STREAM, Uri.fromFile(attachment)); Intent chooser = Intent.createChooser( emailIntent, context.getString(R.string.send_mail_chooser)); context.startActivity(chooser); } 

在创build文件或发送意图时是否有任何错误? 有没有更好的方式来启动附件的邮件应用程序? 另外 – 有人遇到这个问题,并find了解决办法吗?

谢谢!

Solutions Collecting From Web of "当接收到ACTION_SEND意图时,Gmail 5.0应用程序失败,并且“权限拒绝附件”"

GMail 5.0添加了一些安全检查,以从意向收到的附件。 这些与unix权限无关,所以文件可读性并不重要。

当附件Uri是一个file://时,它只接受来自外部存储器的文件,gmail本身的专用目录或来自调用应用程序的私人数据目录的世界可读文件。

这个安全检查的问题是,它依靠gmail能够find调用者的应用程序,这是唯一可靠的,当调用者询问结果。 在上面的代码中,你不要求结果,因此gmail不知道调用者是谁,并拒绝你的文件。

由于它在4.9中工作,但不在5.0中,你知道这不是一个unix权限问题,所以原因必须是新的检查。

TL; DR答案: 用startActivityForResultreplacestartActivity。

或者更好的是,使用内容提供者。

我能够通过一个意图从我的应用程序通过截图.jpeg文件到GMail 5.0。 关键是在这个答案 。

我从@natasky的代码中得到的所有内容几乎都是相同的,但是我有文件的目录

 context.getExternalCacheDir(); 

其中“表示应该保存caching文件的外部存储目录”(文档)

使用getExternalCacheDir()File.createTempFile

使用以下命令在外部caching目录中创build一个临时文件:

 String fileExtension = ".tmp"; File temporaryFile = File.createTempFile( fileName, fileExtension, context.getExternalCacheDir() ); 

我testing了一下,发现这绝对是私人存储访问问题。 当您将某个文件附加到Gmail(超过5.0)时,请不要使用私有存储(例如/ data / data / package /)中的文件。 尝试使用/ storage / sdcard。

您可以成功附加您的文件。

你应该实现一个FileProvider ,它可以为你的应用程序的内部文件创buildUris。 其他应用程序被授予阅读这些Uris的权限。 然后,简单地而不是调用Uri.fromFile(附件),你实例化你的FileProvider并使用:

 fileProvider.getUriForFile(attachment); 

不知道为什么GMail 5.0不喜欢某些文件path(我已经确认它具有读访问权限),但是更好的解决scheme是实现自己的ContentProvider类来提供文件。 这实际上有点简单,我在这里find了一个体面的例子: http : //stephendnicholas.com/archives/974

一定要将标签添加到您的应用程序清单,并在其中包含一个“android:grantUriPermissions =”true“”。 您还需要实现getType()并为文件URI返回适当的MIMEtypes,否则某些应用程序将无法使用这个…在链接的注释部分有一个例子。

Google有这个问题的答案 :

  • 将数据存储在您自己的ContentProvider ,确保其他应用程序具有访问您的提供商的正确权限。 提供访问的首选机制是使用per-URI权限 ,这是临时的,只允许访问接收应用程序。 像这样创build一个ContentProvider的简单方法是使用FileProvider helper类。

  • 使用系统MediaStoreMediaStore主要针对video,audio和图像MIMEtypes,但是从Android 3.0(API级别11)开始,它还可以存储非媒体types(有关更多信息,请参阅MediaStore.Files )。 可以使用scanFile()将文件插入到MediaStore之后将适合共享的content:// style Uri传递给提供的onScanCompleted()callbackonScanCompleted() 。 请注意,一旦添加到系统MediaStore ,设备上的任何应用程序都可以访问该内容。

你也可以尝试为你的文件设置权限 :

 emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

最后,您可以将文件复制/存储在外部存储器中 – 不需要那里的权限。

我遇到这个问题,终于find一个简单的方法发送电子邮件附件。 这是代码

 public void SendEmail(){ try { //saving image String randomNameOfPic = Calendar.DAY_OF_YEAR+DateFormat.getTimeInstance().toString(); File file = new File(ActivityRecharge.this.getCacheDir(), "slip"+ randomNameOfPic+ ".jpg"); FileOutputStream fOut = new FileOutputStream(file); myPic.compress(Bitmap.CompressFormat.JPEG, 100, fOut); fOut.flush(); fOut.close(); file.setReadable(true, false); //sending email Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zohabali5@gmail.com"}); intent.putExtra(Intent.EXTRA_SUBJECT, "Recharge Account"); intent.putExtra(Intent.EXTRA_TEXT, "body text"); //Uri uri = Uri.parse("file://" + fileAbsolutePath); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivityForResult(Intent.createChooser(intent, "Send email..."),12); }catch (Exception e){ Toast.makeText(ActivityRecharge.this,"Unable to open Email intent",Toast.LENGTH_LONG).show(); } } 

在这个代码中,“myPic”是由相机意图返回的位图