Android Gmail 5.0应用程序失败,出现“0”;“附件的许可被拒绝”;当它收到动作时,发送意图

Android Gmail 5.0应用程序失败,出现“0”;“附件的许可被拒绝”;当它收到动作时,发送意图,android,android-intent,Android,Android Intent,我的应用程序创建带有附件的邮件,并使用带有intent.ACTION\u SEND的intent来启动邮件应用程序 它适用于我测试过的所有邮件应用程序,除了新的Gmail 5.0(它适用于Gmail 4.9),其中邮件打开时没有附件,显示错误:“附件权限被拒绝” logcat上没有来自Gmail的有用消息。我只在安卓KitKat上测试了Gmail 5.0,但在多台设备上进行了测试 我为附件创建如下文件: String fileName = "file-name_something_like_th

我的应用程序创建带有附件的邮件,并使用带有
intent.ACTION\u SEND
的intent来启动邮件应用程序

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

logcat上没有来自Gmail的有用消息。我只在安卓KitKat上测试了Gmail 5.0,但在多台设备上进行了测试

我为附件创建如下文件:

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);
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);
}
我知道
MODE\u WORLD\u READABLE
的安全问题

我的意图如下:

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);
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);
}
在创建文件或发送意图时是否有任何错误?有没有更好的方法启动带有附件的邮件应用程序?或者-是否有人遇到此问题并找到了解决方法


谢谢

我不知道为什么GMail 5.0不喜欢某些文件路径(我已经确认它确实有读取权限),但一个显然更好的解决方案是实现自己的ContentProvider类来为文件提供服务。这其实有点简单,我在这里找到了一个不错的例子:


确保将该标记添加到应用程序清单中,并在其中包含一个“android:grantUriPermissions=“true”。您还需要实现getType()并为文件URI返回适当的MIME类型,否则某些应用程序将无法使用此。。。在链接的评论部分有一个这样的例子。

我测试了它,发现它肯定是私有存储访问问题。 当您将某些文件附加到Gmail(5.0以上)时,请不要使用私人存储(如/data/data/package/)中的文件。尝试使用/storage/sdcard


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

我可以通过Intent将截图.jpeg文件从我的应用程序传递到GMail 5.0。钥匙在里面

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

context.getExternalCacheDir();

它“表示您应该保存缓存文件的外部存储目录”(文档)

GMail 5.0在从Intent接收的附件中添加了一些安全检查。这些与unix权限无关,因此文件是否可读并不重要

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

这种安全检查的问题在于,它依赖于gmail能够找到呼叫者应用程序,只有呼叫者要求结果时,该应用程序才可靠。在上面的代码中,您不要求结果,因此gmail不知道呼叫者是谁,并拒绝您的文件

因为它在4.9中对您有效,但在5.0中不起作用,所以您知道这不是unix权限问题,所以原因一定是新的检查

TL;DR答复: 用startActivityForResult替换startActivity。

或者最好使用内容提供商。

您应该这样做,这样可以为应用程序的内部文件创建URI。其他应用程序被授予读取这些URI的权限。然后,只需实例化文件提供程序并使用以下命令,而不是调用Uri.fromFile(附件):

fileProvider.getUriForFile(附件);
谷歌对此问题有一个解决方案:

  • 将数据存储在您自己的
    ContentProvider
    中,确保其他应用程序具有访问您的提供商的正确权限。提供访问权限的首选机制是使用临时的,并且只授予对接收应用程序的访问权限。像这样创建
    ContentProvider
    的一种简单方法是使用
    FileProvider
    helper类

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

您还可以尝试查找您的文件:

emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
最后,您可以将文件复制/存储到外部存储器中—在那里不需要权限。

使用
getExternalCacheDir()
File.createTempFile
。 使用以下命令在外部缓存目录中创建一个临时文件:

File tempFile = File.createTempFile("fileName", ".txt", context.getExternalCacheDir());

然后将原始文件的内容复制到
tempFile

FileWriter fw = new FileWriter(tempFile);

FileReader fr = new FileReader(Data.ERR_BAK_FILE);
int c = fr.read();
while (c != -1) {
    fw.write(c);
    c = fr.read();
}
fr.close();

fw.flush();
fw.close();

现在把你的文件放在原处

emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));

我遇到了这个问题,终于找到了一个简单的方法来发送带有附件的电子邮件。这是密码

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”是相机意图返回的位图

步骤1:在附加的URI中添加权限

Uri=FileProvider.getUriForFile(上下文,“com.yourpackage”,文件)

与清单文件相同,请提供名称

android:authorities=“com.yourpackage”

步骤2`;添加允许读取的标志


myIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

@nobalG与此问题无关。我也遇到过此问题,附件的位置似乎与此问题有关,因为共享sd卡的附件仍然有效。(这不重要,因为世界可读标志)这可能是一个错误吗?这里也有相同的问题…我仍然可以使用ACTION_SEND将文件发送到Google Drive,但当我选择GMail(使用新版本)时,它会像您看到的那样失败。GMail以前版本上的相同代码没有问题。遇到了相同的问题