Почему я не могу прикрепить файл в Android N +? - PullRequest
0 голосов
/ 02 декабря 2018

Я разрабатываю приложение, которое экспортирует некоторые HTML-таблицы в виде вложений.Я заметил, что мой код не работает, если я пытаюсь прикрепить HTML-таблицу к Gmail, Google Drive или любому провайдеру электронной почты в 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 и других форумов, но он не работает должным образом.

Кто-нибудь из вас сталкивался с подобной проблемой?Вы знаете, что я должен изменить?Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Несмотря на то, что ответ Ричарда является правильным в 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)) должен быть удален для правильного поведения.

0 голосов
/ 03 декабря 2018

Не удалось попробовать этот код, но он должен работать.По крайней мере, это сработало для меня много раз.

Добавьте этот код достаточно рано в вашем методе onCreate.

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

Этот код делает то, что он отключает правило uri файла строгого режима вAndroid API версии 24 и выше.Этот код был введен в действие для обеспечения использования FileProvider для приложений, которые намереваются обмениваться объектами, содержащими файлы, через открытый объект URI.Оказывается, в большинстве случаев, как и во многих других, это ненужно.

...