2

Using code below which I found on another post, the email appears ready to send with the attachment, but when email is received, there is no attachment. Also, the email address has to be manually entered, it is not populated by the CreateEmail statement. I am sending from a gmail account. Anyone help please?

procedure TForm1.CreateEmail(const Recipient, Subject, Content,
 Attachment: 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_EMAIL, StringToJString(Recipient));
 Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Subject));
 Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Content));
 AttachmentFile := SharedActivity.getExternalFilesDir
   (StringToJString(Attachment));

 Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);

 Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM,
   TJParcelable.Wrap((Uri as ILocalObject).GetObjectID));

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

 SharedActivity.startActivity(Intent);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 CreateEmail('xxx@shaw.ca', 'Test Results', Memo1.Lines.text,'/sdcard/Download/Demo.pdf');
end;
Community
  • 1
  • 1
Motherless
  • 23
  • 1
  • 5

2 Answers2

3

Intent.EXTRA_EMAIL is documented as expecting an array of string values, but you are passing it a single string instead.

You are also not using SharedActivity.getExternalFilesDir() correctly. Its type parameter specifies the type of folder you want to lookup (MUSIC, PODCASTS, PICTURES, etc), and then it returns a JFile that represents that folder. You can then append a filename to the path of that folder as needed. However, in this case, your Attachment string contains a full path to the actual file that you want to attach, so you should not be calling getExternalFilesDir() at all. Create a JFile from the path as-is instead.

Try this:

procedure TForm1.CreateEmail(const Recipient, Subject, Content, Attachment: string);
var
  JRecipient: TJavaObjectArray<JString>;
  Intent: JIntent;
  Uri: Jnet_Uri;
  AttachmentFile: JFile;
begin
  JRecipient := TJavaObjectArray<JString>.Create(1);
  JRecipient.Items[0] := StringToJString(Recipient);

  Intent := TJIntent.Create;
  Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, JRecipient);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Subject));
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Content));

  if Attachment <> '' then
  begin
    AttachmentFile := TJFile.JavaClass.init(StringToJString(Attachment));
    Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);
    Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID));
  end;

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

  SharedActivity.startActivity(Intent);
end;

Read this article for more details about sending emails in Android:

Launching activities and handling results in Delphi XE5 Android apps | Sending an email

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Hi Remy - how can I add multiple attachments to the email? – sandman Mar 24 '17 at 11:10
  • I imagine it would just be a matter of calling `Intent.putExtra(EXTRA_STREAM)` for each individual attachment. – Remy Lebeau Mar 24 '17 at 18:00
  • Remy, when startActivity is run, it chooses only the last EXTRA_STREAM attachment that was called. Does it not have to be done like an array similar to your JRecipient example above? – sandman Mar 27 '17 at 07:54
  • Apparently 2 ways are to do Intent.ACTION_SEND_MULTIPLE or Intent.putStringArrayListExtra but I don't know how to do the TJavaObjectArray or even variant arrays with the Uri wrap code above - please help, thanks – sandman Mar 27 '17 at 09:18
  • @sandman what is unclear to you about `TJavaObjectArray` exactly? The constructor takes the number of items to allocate for the array, then you use the `Items` property to fill in each item as needed. – Remy Lebeau Mar 27 '17 at 14:57
  • Remy I just didn't know how to use it together with the parcelable Uri code above. It is a lot easier with the Intent.putParcelableArrayListExtra code I provided below. – sandman Mar 28 '17 at 06:07
3

Here is working code for multiple attachments. Works in 10.1 Berlin.

procedure TForm1.ItemShare;
var
  chooserIntent, Intent: JIntent;
  Uri: Jnet_Uri;
  Uris: JArrayList;
  AttachmentFile: JFile;
begin
  {$IFDEF ANDROID}
    intent := TJIntent.Create;    
    intent.setAction(TJIntent.JavaClass.ACTION_SEND_MULTIPLE);
    intent.setType(StringToJString('text/*'));
    intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString('Email header'));

    Uris:= TJArrayList.Create;
    while i<condition
    begin
      AttachmentFile := TJFile.JavaClass.init(StringToJString('filename'));
      Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);
      Uris.add(i,Uri);
      inc(i);
    end;   

    Intent.putParcelableArrayListExtra(TJIntent.JavaClass.EXTRA_STREAM, Uris);    
    Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString('body'));   
    chooserIntent := TJIntent.JavaClass.createChooser(Intent, StrToJCharSequence('Share using'));
    TAndroidHelper.Activity.startActivityForResult(chooserIntent, 0);
  {$ENDIF}
end;
sandman
  • 2,050
  • 9
  • 17