Indy and Android

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Indy and Android

Post by Lena »

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?
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

Thank you.
Can you show me link with c++ example TIdSMTP + GMail + Android + attachment?
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

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++
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

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: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

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

Re: Indy and Android

Post by Lena »

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
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

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();
    		 }
		 }
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: Indy and Android

Post by rlebeau »

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
Lena
BCBJ Master
BCBJ Master
Posts: 696
Joined: Sun Feb 06, 2011 1:28 pm

Re: Indy and Android

Post by Lena »

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 70802 times
Post Reply