Перейти к содержанию
Fire Monkey от А до Я
  • 0

Отправка файлов через намерение


Tovenar

Вопрос

Как правильно отправлять файлы через ACTION_SEND. То что пробовал и не смог заставить работать:

uses System.IOUtils, FMX.Helpers.Android,Androidapi.JNI.JavaTypes, Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText;     
procedure TMain.SendFileClick(Sender: TObject);    
var      
Intent: JIntent;    
begin      
Intent := TJIntent.Create;      
Intent.setAction(TJIntent.JavaClass.ACTION_SEND);      
Intent.setDataAndType(StrToJURI('file:' + TPath.Combine(TPath.GetSharedDownloadsPath, 'picture.png')), StringToJString ('image/png'));      
SharedActivity.startActivity(Intent);    
end;

или

var
Intent: JIntent;
begin
Intent := TJIntent.Create;
Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
Intent.setType(StringToJString('image/png'));
Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM , StringToJString('file:mnt/sdcard/pictures/1.png'));
SharedActivity.startActivity(Intent);

При чем с открытием(ACTION_VIEW) все в порядке:

var
  FileName, ExtFile: string;
  mime: JMimeTypeMap;
  ExtToMime: JString;
  Intent: JIntent;
  pathN:string;
begin
    FileName := Item.ItemData.Detail;
    try
      ExtFile := AnsiLowerCase(StringReplace(TPath.GetExtension(FileName), '.', '',[]));
      mime := TJMimeTypeMap.JavaClass.getSingleton();
      ExtToMime := mime.getMimeTypeFromExtension(StringToJString(ExtFile));


      Intent := TJIntent.Create;
      Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
      Intent.setDataAndType(StrToJURI('file:' + FileName), ExtToMime);
      SharedActivity.startActivity(Intent);
    except
      ShowMessage('Невозможно открыть файл!');
    end

end;

Хоть в моих примерах я и пытаюсь передать изображение (я в курсе, что в ActionList есть стандартное действие для отправки изображений), в итоге код будет использоваться для файлов любого типа. 

Как победить?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Путем поисков и мучений:

uses
  FMX.Helpers.Android,
  //  Androidapi.IOUtils,
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Net,
  Androidapi.JNI.Os;
...
var
  Intent  : JIntent;
  uri     : Jnet_Uri;
  j_file  : JFile;
  f_name  : string;
...  
begin
  // имя пересылаемого файла
  f_name := 'picture.png';
  // файл должен быть сохранен по пути: Androidapi.IOUtils.getExternalFilesDir
  // или тоже самое: GetPublicPath
  // К примеру:
  ...SaveToFile(TPath.Combine(TPath.GetPublicPath, f_name));
    
  Intent := TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString('....')); // тема, если нужно
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString('....'));    // текст сообщения, если нужно
  // прикрепляем файл
  j_file := SharedActivity.getExternalFilesDir(StringToJString(f_name));
  uri := TJnet_Uri.JavaClass.fromFile(j_file);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM,TJParcelable.Wrap((uri as ILocalObject).GetObjectID));
  Intent.setType(StringToJString('vnd.android.cursor.dir/email'));
  //
  SharedActivity.startActivity(Intent);
end;

Как приаттачить файл по любому другому пути не знаю.

Изменено пользователем Belov.V.
Ссылка на комментарий
  • 0

Путем поисков и мучений:

А вот у меня ваш код почему то не работает. При отправке файл вкладывается в сообщение

 

5857594.png

но до получателя письмо доходит без вложения. Кроме того, не получается программно добавить адрес получателя. Делаю так

Intent.putExtra( TJIntent.JavaClass.EXTRA_EMAIL, StringToJString( 'aaa@mail.ru' ) );

но поле "кому" остается пустым (на скрине это видно).

Ссылка на комментарий
  • 0

Как вариант, почему нет присоединенного файла - проверьте сохранение файла именно по этому пути:

f_name := 'sample-temp.txt';
//f_path := TPath.Combine(Androidapi.IOUtils.getExternalFilesDir,f_name); // пусть именно такой
// или
f_path := TPath.Combine(TPath.GetSharedDocumentsPath, f_name);        // или тоже самое: GetPublicPath
...SaveToFile(TPath.Combine(TPath.GetSharedDocumentsPath, f_name));

// прикрепляем файл
j_file := SharedActivity.getExternalFilesDir(StringToJString(f_name));

 

В особенности заполнение j_file проверьте.
 
Тоже самое было, когда пробовал по другим путям файл отправки класть. Имя было, но не отправлялось.
 
Удачи!
 
 
Ссылка на комментарий
  • 0

Заполнение поля "Кому:"

Спасибо, помогло!

 

по поводу пути, да, лежат именно в Androidapi.IOUtils.getExternalFilesDir. Буду разбираться.

Изменено пользователем estra
Ссылка на комментарий
  • 0

 

Заполнение поля "Кому:"

Спасибо, помогло!

 

по поводу пути, да, лежат именно в Androidapi.IOUtils.getExternalFilesDir. Буду разбираться.

 

 

Я такой вариант получал, когда j_file не верно записывал. См. выше

Ссылка на комментарий
  • 0

Вот какая беда обнаружилась. Если прикреплять файл к письму руками, то размер файла определяется верно (на скрине слева), а если программно, то неверно (на скрине справа). Возможно проблема в этом, но почему так происходит, непонятно.
 
5866818.png
Belov.V, вы не могли бы выложить небольшой работающий примерчик, если не сложно?

Ссылка на комментарий
  • 0

Вот пример. Соорудил, проверил, вроде работает.

 

Размер файла нормальный. Скриншеты на двух почтовых клиентах:

0_123121_f617be46_orig.png

 

0_123120_ecf605ab_orig.png

 

Upd: в RX небольшие изменения. См. второй пример. (для первого идут предупреждения, хотя тоже работает)

Sample-SendAttach.zip

Sample-SendAttach_RX.zip

Изменено пользователем Belov.V.
Ссылка на комментарий
  • 0

Спасибо за пример, работает отлично. Осталось понять, почему у меня не работало. Если разберусь, отпишусь...

 

Проверьте вот это место в коде:

// прикрепляем файл

j_file := SharedActivity.getExternalFilesDir(StringToJString(f_name));

 

Обратите внимание, что там указано имя прикрепляемого файла без пути к нему. По описанию ситуации очень похоже на ошибку в этом месте.

Изменено пользователем Belov.V.
Ссылка на комментарий
  • 0

Обратите внимание, что там указано имя прикрепляемого файла без пути к нему. По описанию ситуации очень похоже на ошибку в этом месте.

Вы правы, ошибка оказалась именно в этом. Еще раз большое спасибо!

Ссылка на комментарий
  • 0

Подскажите где закралась ошибка. Процедура должна отправлять файл через намерение (файл текстовый). 

aFileName:='/storage/emulated/0/Download/test/тестовый файл для отправки.out.txt';

aComment:='Комментарий к файлу';

procedure ShareFile(aFileName, aComment : String);
var Intent    : JIntent;
    uri       : Jnet_Uri;
    AttachmentFile: JFile;
begin
  Intent := TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(aComment));
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(aComment));
  AttachmentFile := TJFile.JavaClass.init(StringToJString(aFileName));
  Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID));
  Intent.setType(StringToJString('text/plain'));
  SharedActivity.startActivity(Intent);
end;

Наблюдаю следующее:

Gmail - все отлично, файл присоединён, комментарий в теме письма

DropBox - все отлично, файл передан

Google Drive - файл передан, но у него отрезано расширение (в папке лежит файл с именем "тестовый файл для отправки")

Yandex Disk - все работает

Облако Mail.ru  - предлагает создать текстовый файл ("Новый текстовый файл.txt"), в который записывает только две одинаковые строчки "Комментарий к файлу"

 

Уже весь мозг сломал. А заказчик требует работу через все эти системы.

 

 

Ссылка на комментарий
  • 0

 

Подскажите где закралась ошибка. Процедура должна отправлять файл через намерение (файл текстовый). 

aFileName:='/storage/emulated/0/Download/test/тестовый файл для отправки.out.txt';

aComment:='Комментарий к файлу';

procedure ShareFile(aFileName, aComment : String);
var Intent    : JIntent;
    uri       : Jnet_Uri;
    AttachmentFile: JFile;
begin
  Intent := TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(aComment));
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(aComment));
  AttachmentFile := TJFile.JavaClass.init(StringToJString(aFileName));
  Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID));
  Intent.setType(StringToJString('text/plain'));
  SharedActivity.startActivity(Intent);
end;

Наблюдаю следующее:

Gmail - все отлично, файл присоединён, комментарий в теме письма

DropBox - все отлично, файл передан

Google Drive - файл передан, но у него отрезано расширение (в папке лежит файл с именем "тестовый файл для отправки")

Yandex Disk - все работает

Облако Mail.ru  - предлагает создать текстовый файл ("Новый текстовый файл.txt"), в который записывает только две одинаковые строчки "Комментарий к файлу"

 

Уже весь мозг сломал. А заказчик требует работу через все эти системы.

 

 

 

 

Goggle Drive в качестве имени ставит то, что указано в Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(aComment));

Т.е. прописывайте в это поле имя файла без пути,

 

Mail.ru не пробовал.

Изменено пользователем Belov.V.
Ссылка на комментарий
  • 0

Здравствуйте, отцы и боги fm! Подскажите пожалуйста новичку..? Перерыл все, что мог, ответа не нашел. Тыкните пожалуйста носом, если есть какая-нибудь статья. Коротко о моей задаче. Приложение для андройда. Из забитого списка с БД формируется счет с использованием загруженного в TImage изображения (что-то вроде листа А4 с шапкой фирмы) и Canvas, накидывающего на него реквизиты, список товаров, сумму и прочее. С помощью ShowShareSheetAction1.Bitmap.Assign(IMG.Bitmap) отправляется клиенту. Проблема возникла, когда список товаров был больше, чем задумано. Ладно, через условия (if количество товаров > например, 60 then создаем динамический image и записываем остатки туда) можно перекидывать. Но, как отправить сразу эти 2 TImage? Пробовал

ShowShareSheetAction1.Bitmap.Assign(IMG.Bitmap);

ShowShareSheetAction1.Bitmap.Assign(IMG2.Bitmap);

Отправляет последнюю запись. Пробовал что-то вроде:

ShowShareSheetAction1.Bitmap.Assign(IMG1.Bitmap, IMG2.Bitmap); Выдает, естественно, ошибку.

Это как-нибудь вообще можно реализовать? Может, есть какая-нибудь альтернатива? Или, как в примерах выше, путем сохранения этих файлов в память и последующего присоединения?

Изменено пользователем Николай_1988
Ссылка на комментарий
  • 0
8 часов назад, Николай_1988 сказал:

Здравствуйте, отцы и боги fm! Подскажите пожалуйста новичку..? Перерыл все, что мог, ответа не нашел. Тыкните пожалуйста носом, если есть какая-нибудь статья. Коротко о моей задаче. Приложение для андройда. Из забитого списка с БД формируется счет с использованием загруженного в TImage изображения (что-то вроде листа А4 с шапкой фирмы) и Canvas, накидывающего на него реквизиты, список товаров, сумму и прочее. С помощью ShowShareSheetAction1.Bitmap.Assign(IMG.Bitmap) отправляется клиенту. Проблема возникла, когда список товаров был больше, чем задумано. Ладно, через условия (if количество товаров > например, 60 then создаем динамический image и записываем остатки туда) можно перекидывать. Но, как отправить сразу эти 2 TImage? Пробовал

ShowShareSheetAction1.Bitmap.Assign(IMG.Bitmap);

ShowShareSheetAction1.Bitmap.Assign(IMG2.Bitmap);

Отправляет последнюю запись. Пробовал что-то вроде:

ShowShareSheetAction1.Bitmap.Assign(IMG1.Bitmap, IMG2.Bitmap); Выдает, естественно, ошибку.

Это как-нибудь вообще можно реализовать? Может, есть какая-нибудь альтернатива? Или, как в примерах выше, путем сохранения этих файлов в память и последующего присоединения?

Я бы на вашем месте создавал не картинку, а к примеру PDF, там не будет проблем с несколькими страницами

Ссылка на комментарий
  • 0

Доброго времени суток всем.

Ребята, есть Delphi XE 10.3.2, есть следующий код:

procedure TfrmSendEmail.SendEmail();
{$IF DEFINED(ANDROID)}
var
  lIntent: JIntent;
  lJRecipient: TJavaObjectArray<JString>;

  lURI: Jnet_Uri;
  lJFile: JFile;
  lFileName: string;
  lFilePath: string;
{$ENDIF}
begin
  {$IF DEFINED(ANDROID)}
  lJRecipient:= TJavaObjectArray<JString>.Create(1);
  lJRecipient.Items[0]:= StringToJString(eEmail.Text);

  lFileName:= AttachFileName;
  lFilePath:= DMUnit.GetCombineFilePath(lFileName);

  lIntent:= TJIntent.Create;
  lIntent.setAction(TJIntent.JavaClass.ACTION_SEND);
  lIntent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, lJRecipient);
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(eSubject.Text));
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(mEmailMessage.Text));

  lJFile:= TJFile.JavaClass.init(StringToJString(lFilePath));
  lURI:= TAndroidHelper.JFileToJURI(lJFile);
  lIntent.setData(lURI);
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((lURI as ILocalObject).GetObjectID));
  lIntent.setType(StringToJString('vnd.android.cursor.dir/email'));

  TAndroidHelper.Activity.startActivity(lIntent);
  {$ENDIF}

end;

Всё отлично работает, если отправить сгенерированый html файл. Отправляет по e-mail без проблем. вкладывает в письмо и отправляет.

Но стоит только прикрепить только что сгенерированый Excel файл и приложение GMail говорит, что Не удалось прикрепить файл. Помогите побороть.

Ссылка на комментарий
  • 0
21 час назад, Алексей Данильченко сказал:


  lIntent.setType(StringToJString('vnd.android.cursor.dir/email'));

Но стоит только прикрепить только что сгенерированый Excel файл и приложение GMail говорит, что Не удалось прикрепить файл. Помогите побороть.

Я думаю здесь тип файла должен быть или нет?

Ссылка на комментарий
  • 0

И так тоже не работает:

lExtFile:= AnsiLowerCase(StringReplace(System.IOUtils.TPath.GetExtension(lFileName), '.', '',[]));
  lMime:= TJMimeTypeMap.JavaClass.getSingleton();
  lExtToMime:= lMime.getMimeTypeFromExtension(StringToJString(lExtFile));

lIntent.setDataAndType(lURI, lExtToMime);

Ссылка на комментарий
  • 0

Может кому пригодится. вот решение.

procedure TfrmSendEmail.SendEmail();
{$IF DEFINED(ANDROID)}
var
  lIntent: JIntent;
  lJRecipient: TJavaObjectArray<JString>;
  lURI: Jnet_Uri;
  lJFile: JFile;
  lFileName: string;
  lFilePath: string;
{$ENDIF}
begin
  {$IF DEFINED(ANDROID)}
  lJRecipient:= TJavaObjectArray<JString>.Create(1);
  lJRecipient.Items[0]:= StringToJString(eEmail.Text);

  lFileName:= AttachFileName;
  lFilePath:= System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetSharedDownloadsPath, lFileName);

  lIntent:= TJIntent.Create;
  lIntent.setType(StringToJString('application/excel'));
  lIntent.setAction(TJIntent.JavaClass.ACTION_SEND);
  lIntent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, lJRecipient);
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(eSubject.Text));
  lIntent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(mEmailMessage.Text));

  lJFile:= TJFile.JavaClass.init(StringToJString(lFilePath));
  lURI:= TAndroidHelper.JFileToJURI(lJFile);
  lIntent.setData(lURI);

  lIntent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((lURI as ILocalObject).GetObjectID));
  TAndroidHelper.Activity.startActivity(lIntent);
  {$ENDIF}

 

Изменено пользователем Алексей Данильченко
Ссылка на комментарий
  • 0

Intent selectorIntent = new Intent(Intent.ACTION_SENDTO);

selectorIntent.setData(Uri.parse("mailto:"));

final Intent emailIntent = new Intent(Intent.ACTION_SEND);

emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"address@mail.com"});

emailIntent.putExtra(Intent.EXTRA_SUBJECT, "The subject");

emailIntent.putExtra(Intent.EXTRA_TEXT, "The email body");

emailIntent.setSelector( selectorIntent );

 

activity.startActivity(Intent.createChooser(emailIntent, "Send email..."));

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...