为什么我不能在Android N +中附加文件?

问题描述 投票:1回答:2

我正在开发一个导出一些HTML表作为附件的应用程序。我注意到,如果我尝试将html表格附加到Gmail,Google云端硬盘或Android N +中的任何电子邮件提供商,我的代码无效,但它可以将文件上传到OneDrive,WhatsApp,Skype等。问题。

这是我目前的代码:

Intent share = new Intent(Intent.ActionSend);
share.SetType("text/html");
share.AddFlags(ActivityFlags.NewDocument);

var file = CreateDirFile($"Meeting_{DateTime.Now.ToString("dd_MM_yyyy_HH_mm_ss")}.html");

try
{
    FileOutputStream fout = new FileOutputStream(file);
    fout.Write(System.Text.Encoding.ASCII.GetBytes($"<!DOCTYPE html><html><body><table><tr><td>1</td><td>2</td><td>3</td></tr></table></body></html>"));
    fout.Close();
}
catch
{
    Toast.MakeText(context, context.GetString("Please check your storage configuration.").Show();
}

if (Build.VERSION.SdkInt < BuildVersionCodes.N)
{
    share.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(file.AbsoluteFile));
}
else
{
    share.AddFlags(ActivityFlags.GrantReadUriPermission);
    share.PutExtra(Intent.ExtraStream, Android.Net.Uri.Parse(file.Path));
}
share.PutExtra(Intent.ExtraSubject, $"Meeting {DateTime.Now.ToString("dd-MM-yyyy")}");
context.StartActivity(Intent.CreateChooser(share, "Email:"));

CreateDirFile函数:

private Java.IO.File CreateDirFile(string fileName)
{
    string root = null;
    if (Android.OS.Environment.IsExternalStorageEmulated)
    {
        root = Android.OS.Environment.ExternalStorageDirectory.ToString();
    }
    else
    {
        root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
    }

    Java.IO.File myDir = new Java.IO.File($"{root}/Meetings");
    myDir.Mkdir();

    Java.IO.File file = new Java.IO.File(myDir, fileName);

    if (file.Exists())
    {
        file.Delete();
        file.CreateNewFile();
    }

    return file;
}

我测试了很多组合甚至应用了以下代码Android.Net.Uri.Parse(file.Path),因为它在SO或其他论坛的不同答案中提出,但它没有按预期工作。

你们有没有遇到过类似的问题?你知道我应该改变什么吗?提前致谢。

android android-intent xamarin.android email-attachments android-7.0-nougat
2个回答
2
投票

没有尝试这个代码,但它应该工作。至少它已经为我工作了很多次。

在onCreate方法中尽早添加此代码。

if(Build.VERSION.SDK_INT >= 24){
    try{
        Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
        m.invoke(null);
    } catch (Exception e){
        e.printStackTrace();
    }
}

这段代码的作用是禁用android api版本24及更高版本中的严格模式文件uri规则。此代码用于强制使用FileProvider用于打算通过公共URI对象共享包含文件的对象的应用程序。事实证明,大部分时间都像许多其他人一样,这是不必要的。


1
投票

尽管理查德的答案是Java中的正确答案,但C#中还需要进行一些更改,其中包括:

OnCreate事件中:

if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
{
    StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
                        .PenaltyDeathOnFileUriExposure()
                        .Build();
    StrictMode.SetVmPolicy(policy);
}

此外,您只需要具有此意图:

share.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(file.AbsoluteFile));

您不需要验证操作系统版本,必须删除此代码Android.Net.Uri.Parse(file.Path))才能获得正确的行为。

© www.soinside.com 2019 - 2024. All rights reserved.