Indy and Android

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Indy and Android

Postby Lena » Fri May 27, 2016 6:59 am

I deployed my application with the sqllite database on the mobile device.
The database is located on this path:
Code: Select all
void __fastcall TForm1::FDConnection1BeforeConnect(TObject *Sender)
{
 #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)
 FDConnection1->Params->Values["Database"] =
 System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), "mikros.s3db");
 #endif
}


I want to add a button to my application by clicking on which I could send the database mikros.s3db to correct email.
Is that possible?
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby rlebeau » Fri May 27, 2016 5:38 pm

Lena wrote:I want to add a button to my application by clicking on which I could send the database mikros.s3db to correct email.
Is that possible?


Indy implements the SMTP protocol for sending emails (the TIdSMTP componet). So your app would have to configure it with an external SMTP server (GMail, Yahoo, etc) and user account authentication so your mobile app can connect to it. Different servers have different requirements about authentication, encryption, etc.

Indy does not have any integration with any iOS/Android native email APIs for sending emails with a mobile device's own email setups.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby Lena » Sat May 28, 2016 4:39 am

Thank you.
Can you show me link with c++ example TIdSMTP + GMail + Android + attachment?
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby rlebeau » Sun May 29, 2016 2:56 pm

Lena wrote:Thank you.
Can you show me link with c++ example TIdSMTP + GMail + Android + attachment?


There are plenty of TIdSMTP examples floating around online if you search around. And there are even several discussions on this same BCBJ forum related to TIdSMTP.

On Android, it is probably best not to use SMTP directly, though. The user is likely to expect using an email account already installed on the device. So you should trigger an Android ACTION_SENDTO Intent containing your email data, and let Android prompt the user which email app+account to send the email with.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby Lena » Sun May 29, 2016 9:37 pm

Today I try TIdSMTP for Windows. No problem.
Which files for Android app I must download from this page: http://indy.fulgan.com/SSL/
AndroidOpenssl1.0.1t.zip
AndroidOpenssl1.0.2h.zip
OpenSSL 1.0.2g Android.zip
?
How correct add this files in Android app just Add->To project libssl.so and libcrypto.so ?

So you should trigger an Android ACTION_SENDTO


I find it hard to use intent, because there are no examples in C++
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby rlebeau » Mon May 30, 2016 10:29 am

Lena wrote:Which files for Android app I must download from this page: http://indy.fulgan.com/SSL/
AndroidOpenssl1.0.1t.zip
AndroidOpenssl1.0.2h.zip
OpenSSL 1.0.2g Android.zip
?


Use the latest version.

Lena wrote:How correct add this files in Android app just Add->To project libssl.so and libcrypto.so ?


https://forums.embarcadero.com/message. ... eID=825670

1. Add the 2 .so files to your project deployment and set them to deploy to the .\assets\internal\ folder

2. add the System.StartupCopy unit as the first unit in your DPR's uses clause.

3. call IdOpenSSLSetLibPath(TPath.GetDocumentsPath) at app startup.


Lena wrote:I find it hard to use intent, because there are no examples in C++


There have been C++ examples posted in the Embarcadero forums. Such as:

https://forums.embarcadero.com/thread.j ... dID=118338
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby Lena » Tue May 31, 2016 5:16 am

Using OpenSSL with Indy

My first step
Code: Select all
#include <System.StartupCopy.hpp>
#include <IdSSLOpenSSLHeaders.hpp>
void __fastcall TForm1::FormCreate(TObject *Sender)
{
 IdOpenSSLSetLibPath(System::Ioutils::TPath::GetDocumentsPath());
}


Do I need use TidAntiFreeze when I use TIdSMTP in Andoid app?
С++ Builder Berlin.

P.S.
Oops no component TidAntiFreeze in С++ Builder Berlin.
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby Lena » Tue May 31, 2016 6:33 am

In Android I have problem with encoding TIdMessage Subject. I got ???? ?????
Attachments
1.jpg
1.jpg (42.7 KiB) Viewed 4514 times
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby Lena » Tue May 31, 2016 7:09 am

I can't send email from code.
In Edit2->Text I type the word tracklogic
Code: Select all
      IdMessage1->Body->Text = L"От: " + Edit2->Text;
      IdMessage1->Recipients->Add();
      IdMessage1->Recipients->Items[0]->Address = Edit2->Text + L"@yandex.ru";
      IdMessage1->Recipients->Items[0]->Domain = L"yandex.ru";
      IdMessage1->Recipients->Items[0]->Text = Edit2->Text + L"@yandex.ru";
      IdMessage1->Recipients->Items[0]->User =  Edit2->Text;
      IdSMTP1->Connect();
      IdSMTP1->Send(IdMessage1);
      IdMessage1->Recipients->Clear();



<????@yandex.ru>: host 127.0.0.1[127.0.0.1] said: 554 5.1.1 Unknown user;
k2DlsLiJ (in reply to end of DATA command)

Delivery status:

Reporting-MTA: dns; mxback5o.mail.yandex.net
X-Yandex-Queue-ID: 1647536A009C
X-Yandex-Sender: rfc822; vlad44b@yandex.ru
Arrival-Date: Tue, 31 May 2016 16:03:32 +0300 (MSK)

Final-Recipient: rfc822; ????@yandex.ru
Original-Recipient: rfc822;????@yandex.ru
Action: failed
Status: 5.1.1
Remote-MTA: dns; 127.0.0.1
Diagnostic-Code: smtp; 554 5.1.1 Unknown user; k2DlsLiJ
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby rlebeau » Tue May 31, 2016 5:22 pm

Lena wrote:
Code: Select all
#include <System.StartupCopy.hpp>



Not sure if this is actually needed (I haven't looked at it yet), but you might need this, too:

Code: Select all
#pragma link "System.StartupCopy"


Lena wrote:
Code: Select all
void __fastcall TForm1::FormCreate(TObject *Sender)



You should NEVER use the OnCreate event in C++. Use the actual constructor instead.

Lena wrote:Do I need use TidAntiFreeze when I use TIdSMTP in Andoid app?


Honestly, I don't know how well (if at all) TIdAntiFreeze works cross-platform. But either way, you are not supposed to block the main UI thread anyway. You should use TIdSMTP in its own worker thread instead.

Lena wrote:Oops no component TidAntiFreeze in С++ Builder Berlin.


There is a design flaw in how Indy packages TIdAntiFreeze that causes issues, so TIdAntiFreeze is disabled in the IDE for FireMonkey projects. But you can still create an instance of TIdAntiFreeze in code at runtime instead, and it will function the same as if you had dropped it on a Form at design-time.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby rlebeau » Tue May 31, 2016 5:23 pm

Lena wrote:In Android I have problem with encoding TIdMessage Subject. I got ???? ?????


To specify a charset used for encoding an email's top-level headers, like Subject, you have to use the TIdMessage::OnInitializeISO event, not the TIdMessage::Charset property (message parts have their own local Charset property instead). In Delphi/C++Builder 2009+, Indy uses UTF-8 by default, you should stick with that. For Russian/Cyrillic, you could use KOI8-R if not UTF-8, but I would not suggest using Windows-1251 either way.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby rlebeau » Tue May 31, 2016 5:34 pm

Lena wrote:In Edit2->Text I type the word tracklogic
...
<????@yandex.ru>: host 127.0.0.1[127.0.0.1] said: 554 5.1.1 Unknown user;
k2DlsLiJ (in reply to end of DATA command)


I could see that happening if Edit2->Text contained non-ASCII characters, but there is no way it could be converting "tracklogic" to "????", and certainly not with the code you have shown. There is no way it could even go from 10 ASCII characters to 4 '?' characters anyway.

BTW, Recipients->Add() returns a TIdEmailAddressItem*, so you don't need to index into Recipients->Items[0] for each sub-property value. And there is no reason to use the Address or Text property if you are using the User and Domain properties, and vice versa. So, use either:

Code: Select all
TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
Item->Address = Edit2->Text + L"@yandex.ru";


Code: Select all
TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
Item->Text = L"<" + Edit2->Text + L"@yandex.ru>";


Code: Select all
TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
Item->User = Edit2->Text;
Item->Domain = L"yandex.ru";
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby Lena » Wed Jun 01, 2016 1:02 am

like Subject, you have to use the TIdMessage::OnInitializeISO event

For Russian/Cyrillic, you could use KOI8-R if not UTF-8, but I would not suggest using Windows-1251 either way.


How to use OnInitializeISO?
Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
  VHeaderEncoding = 'B'; //In Subject got ??????

  //I try KOI8-R or UTF-8 or windows-1251 for VCharSet but got in body ??????
  //VCharSet = L"KOI8-R";

  //only correct body when set in object inspectot:
  //CharSet=windows-1251
}


I try to use SysLocale.PriLangID russian forum
SysLocale.PriLangID = LANG_RUSSIAN;
But: use of undeclared identifier 'LANG_RUSSIAN'

I could see that happening if Edit2->Text contained non-ASCII characters, but there is no way it could be converting "tracklogic" to "????", and certainly not with the code you have shown.


Thank you. It my mistake I must use Edit3 not Edit2.:)

All my code now:
Code: Select all
  try
  {
    try
      {
      //CharSet=windows-1251 in object inspectot and all good for Body
      IdMessage1->Body->Text = L"От: " + Edit2->Text;
//SysLocale.PriLangID = LANG_RUSSIAN; error
      //here problem Subject=???????
      IdMessage1->Subject = L"База данных 1"; //<- test

      TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
      Item->User = Edit3->Text;
      Item->Domain = L"yandex.ru";
      /*
      #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)
       String att = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath
       (), "mikros.s3db");
      #endif

      //TO DO: I have not yet solved the problem with attachment:
      std::unique_ptr<TIdAttachmentFile> attachment(new TIdAttachmentFile(IdMessage1->MessageParts, att));
      */
      Button3->Enabled = false;
      IdSMTP1->Connect();
      IdSMTP1->Send(IdMessage1);
      Button3->Enabled = true;
      //***in Android for MessageDlg****
         struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc>
         {
         void __fastcall Invoke(const System::Uitypes::TModalResult AResult)
           {
            switch (AResult)
            {
               case mrYes :
                {
                 //Application->Terminate();
                 //ShowMessage("You chose Yes");
                }
               break;
               case mrNo:
                ShowMessage("You chose No");
               break;
               case mrCancel:
                ShowMessage("You chose Cancel");
               break;
            }
           }
         };

         _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
         String MES = (L"Письмо отправлено.");
         MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
         //*****end MessageDlg***
      }
      catch (EIdException &E)
      {
         //*******
         struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc>
         {
         void __fastcall Invoke(const System::Uitypes::TModalResult AResult)
           {
            switch (AResult)
            {
               case mrYes :
                {
                 //Application->Terminate();
                 //ShowMessage("You chose Yes");
                }
               break;
               case mrNo:
                ShowMessage("You chose No");
               break;
               case mrCancel:
                ShowMessage("You chose Cancel");
               break;
            }
           }
         };

         _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
         String MES = (L"Problem. " + E.Message);
         MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
         //********
      }

  }
  __finally
       {
        Button3->Enabled = true;
        if(IdSMTP1->Connected())
          {
           IdSMTP1->Disconnect();
           }
       }
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Postby rlebeau » Wed Jun 01, 2016 12:22 pm

Lena wrote:How to use OnInitializeISO?


Set the VCharset parameter to the desired charset (UTF-8, KOI8-R, Windows-1251, etc), and set the VHeaderEncoding parameter to the desired byte encoding (B = Base64, Q = QuotedPrintable, 8 = 8bit Binary).

Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
   VCharSet = L"UTF-8";
   VHeaderEncoding = L'B';
}


Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
   VCharSet = L"Windows-1251";
   VHeaderEncoding = L'Q';
}


Lena wrote:I try to use SysLocale.PriLangID russian forum
SysLocale.PriLangID = LANG_RUSSIAN;
But: use of undeclared identifier 'LANG_RUSSIAN'


That is a Windows-specific constant. It is defined in winnt.h, which is included by windows.h. You can't use Windows LANGIDs in Android, and besides the SysLocale.PriLangID field is not even used on non-Windows platforms.

Even if it were used, setting SysLocale.PriLangID to LANG_RUSSIAN causes the TIdMessage::OnInitializeISO event to default the charset to KOI8-R (LANG_UKRAINIAN defaults to Windows-1251). If you set the charset explicitly instead, you don't need to set SysLocale.PriLangID at all.

Lena wrote:All my code now


Try something like this:

Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
   VCharSet = L"UTF-8";
   VHeaderEncoding = L'B';
}

...

//***in Android for MessageDlg****
struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc>
{
   void __fastcall Invoke(const System::Uitypes::TModalResult AResult)
   {
      switch (AResult)
      {
         case mrYes :
         {
            //Application->Terminate();
            //ShowMessage("You chose Yes");
            break;
         }

         case mrNo:
            ShowMessage("You chose No");
            break;

         case mrCancel:
            ShowMessage("You chose Cancel");
            break;
      }
   }
};

...

Button3->Enabled = false;
try
{
   try
   {
      IdMessage1->Clear();
      IdMessage1->Subject = L"База данных 1"; //<- test

      TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
      Item->User = Edit3->Text;
      Item->Domain = L"yandex.ru";

      #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)

      TIdText *text = new TIdText(IdMessage1->MessageParts);
      text->Body->Text = L"От: " + Edit2->Text;
      text->ContentType = L"text/plain";
      text->CharSet = L"utf-8";

      String att = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), L"mikros.s3db");
      TIdAttachmentFile *attachment = new TIdAttachmentFile(IdMessage1->MessageParts, att);

      IdMessage1->ContentType = L"multipart/mixed";

      #else

      IdMessage1->Body->Text = L"От: " + Edit2->Text;
      IdMessage1->ContentType = L"text/plain";
      IdMessage1->CharSet = L"utf-8";

      #endif

      IdSMTP1->Connect();
      try {
         IdSMTP1->Send(IdMessage1);
      }
      __finally {
         IdSMTP1->Disconnect();
      }

      _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
      String MES = L"Письмо отправлено.";
      MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
   }
   catch (const Exception &E)
   {
      _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
      String MES = L"Problem. " + E.Message;
      MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
   }
}
__finally
{
   Button3->Enabled = true;
}


Alternatively, use TIdMessageBuilderPlain to help you prepare the TIdMessage parts:

Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
   VCharSet = L"UTF-8";
   VHeaderEncoding = L'B';
}

...

//***in Android for MessageDlg****
struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc>
{
   void __fastcall Invoke(const System::Uitypes::TModalResult AResult)
   {
      switch (AResult)
      {
         case mrYes :
         {
            //Application->Terminate();
            //ShowMessage("You chose Yes");
            break;
         }

         case mrNo:
            ShowMessage("You chose No");
            break;

         case mrCancel:
            ShowMessage("You chose Cancel");
            break;
      }
   }
};

...

Button3->Enabled = false;
try
{
   try
   {
      IdMessage1->Clear();
      IdMessage1->Subject = L"База данных 1"; //<- test

      TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
      Item->User = Edit3->Text;
      Item->Domain = L"yandex.ru";

      std::unique_ptr<TIdMessageBuilderPlain> builder(new TIdMessageBuilderPlain);

      builder->PlainText->Text = L"От: " + Edit2->Text;
      builder->PlaintTextCharSet = L"utf-8";
      builder->PlainTextContentTransfer = L"binary";

      #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)

      String att = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), L"mikros.s3db");
      builder->Attachments->Add(att);

      #endif

      builder->FillMessage(IdMessage1);

      IdSMTP1->Connect();
      try {
         IdSMTP1->Send(IdMessage1);
      }
      __finally {
         IdSMTP1->Disconnect();
      }

      _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
      String MES = L"Письмо отправлено.";
      MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
   }
   catch (const Exception &E)
   {
      _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
      String MES = L"Problem. " + E.Message;
      MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
   }
}
__finally
{
   Button3->Enabled = true;
}
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1387
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Indy and Android

Postby Lena » Wed Jun 01, 2016 2:21 pm

Thank you!
I try your code:
Code: Select all
void __fastcall TFormServis::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding,
        UnicodeString &VCharSet)
{
   VCharSet = L"UTF-8";
   VHeaderEncoding = L'B';
}

Code: Select all
Button3->Enabled = false;
    try
   {
       try
       {
          IdMessage1->Clear();
        IdMessage1->Subject = L"Привет мир Hello word"; //<- mix RU+EN

          TIdEMailAddressItem *Item = IdMessage1->Recipients->Add();
          Item->User = Edit3->Text;
          Item->Domain = L"yandex.ru";

          #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)

        //#include "IdText.hpp"
        //Error: no matching constructor for initialization of 'Idtext::TIdText'
        //I am add NULL in constructor. Is it correct?
        TIdText *text = new TIdText(IdMessage1->MessageParts,NULL);
        text->Body->Text = L"От: " + Edit2->Text;
          text->ContentType = L"text/plain";
          text->CharSet = L"utf-8";

          String att = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), L"mikros.s3db");
          TIdAttachmentFile *attachment = new TIdAttachmentFile(IdMessage1->MessageParts, att);

          IdMessage1->ContentType = L"multipart/mixed";

          #else

          IdMessage1->Body->Text = L"От: " + Edit2->Text;
          IdMessage1->ContentType = L"text/plain";
          IdMessage1->CharSet = L"utf-8";

          #endif

          IdSMTP1->Connect();
          try {
             IdSMTP1->Send(IdMessage1);
          }
          __finally {
             IdSMTP1->Disconnect();
          }

          _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
          String MES = L"Письмо отправлено.";
          MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
       }
       catch (const Exception &E)
       {
          _di_TInputCloseDialogProc handler = new TCloseDialogHandler();
          String MES = L"Problem. " + E.Message;
          MessageDlg(MES, TMsgDlgType::mtInformation,   TMsgDlgButtons() << TMsgDlgBtn::mbYes, 0, handler);
       }
    }
    __finally
    {
       Button3->Enabled = true;
    }



However, I got a strange error :(
Attachments
ss.jpg
ss.jpg (46.18 KiB) Viewed 4488 times
Lena
BCBJ Master
BCBJ Master
 
Posts: 429
Joined: Sun Feb 06, 2011 1:28 pm

Next

Return to Technical

Who is online

Users browsing this forum: No registered users and 11 guests

cron