Indy10 TCP; client for Android and server for win32 - android

I'm new in INDY library, so I use delphi XE8 and indy for TCP client/serverconnection; I built server application for Windows and client for Android, when client application send message"text" to server application it work but the client app don't receive anything:
IdTCPClient1.IOHandler.WriteLn('OK'+edit2.Text+inttostr(incr), IndyTextEncoding_OSDefault());
LLine := IdTCPClient1.IOHandler.ReadLn();
LLine variable is empty and the client don't receive anything from the server app.
I repeat that the client app is created for Android and the server for WIN32 when I tested the client/sever app for WIN32 it work fine but when I test client app for Android, the client app is connected and the server app receive the data but client app don't receive anything.
The Server side code is :
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
LLine: String;
begin
TIdNotify.NotifyMethod( ShowStartServerdMessage );
LLine := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_UTF8);
if ((char(LLine[1])='O') and (char(LLine[2])='K')) then
begin
tg.text:=sg.text;ta.text:=sa.text;
sg.text:=fg.text;sa.text:=fa.text;
fg.text:=(char(LLine[3]));fa.text:=(char(LLine[4]))+(char(LLine[5]))+(char(LLine[6]));
AContext.Connection.IOHandler.WriteLn('OK'+fa.text);
TIdNotify.NotifyMethod(StopStartServerdMessage);
sndPlaySound('C:\defi', SND_NODEFAULT Or SND_ASYNC );
end
else
if (char(LLine[1])='C') then
begin
AContext.Connection.IOHandler.WriteLn('OK'+fa.text);
TIdNotify.NotifyMethod(StopStartServerdMessage);
end;
end;
And the Client side :
procedure TForm1.Button2Click(Sender: TObject);
var
LLine2: String;
begin
if timer1.Enabled=false then
begin timer1.Enabled:=true;label4.text:=edit3.Text; end;
incr:=strtoint(label4.text);
incr:=incr+1;
IdTCPClient1.IOHandler.WriteLn('OK'+edit2.Text+inttostr(incr), IndyTextEncoding_UTF8);
LLine2 := IdTCPClient1.IOHandler.ReadLn();
if ((char(LLine2[1])='O') and (char(LLine2[2])='K')) then
begin
Memo1.Lines.Add('La commande est reçu par le serveur');
end;
end;
And in client side i have a timer on event of timer i have this code :
procedure TForm1.Timer1Timer(Sender: TObject);
var
s:string;
begin
IdTCPClient1.IOHandler.WriteLn('C', IndyTextEncoding_UTF8);
s := IdTCPClient1.IOHandler.ReadLn();
if ((char(s[1])='O') and (char(s[2])='K')) then
begin
label4.text:=char(s[3])+char(s[4])+char(s[5]);
end;
end;

Related

Send notifications when the app is not used?

A client of mine had the question of whether it is possible to send a push notification in the employee app if they have not entered their hours by a certain time.
Is it possible to create a service for Android and iOS apps that checks every hour if the hours of the day have been entered in the database, and if not then send a push notification?
I don't know where to start, and if it is possible. But if other apps can do it, it should be possible with this app as well.
As #SilverWarior Suggests I have created two pieces of code one makes the notifications when the app goes to the background then when the app goes to the foreground I clear Tnotificationcenter. I've used the appevent function to trigger the enterdbackground and willbecomeforground.
The Appevent code looks like this:
function TForm1.AppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
begin
case AAppEvent of
TApplicationEvent.EnteredBackground:
begin
Gethourregistration(FEmployeeNr,NOW);
if dm.MthourregistrationControl.RecordCount<1 then
begin
var Notification := NotificationCenter1.CreateNotification;
try
Notification.Name := 'message1';
Notification.AlertBody := 'You have not yet entered todays hours!';
Notification.FireDate :=Date+encodetime(19,0,0,0);
{ Send notification in Notification Center }
NotificationCenter1.ScheduleNotification(Notification);
Notification.Name := 'message2';
Notification.AlertBody := 'You have not yet entered todays hours!';
Notification.FireDate :=Date+encodetime(21,0,0,0);
{ Send notification in Notification Center }
NotificationCenter1.ScheduleNotification(Notification);
finally
Notification.Free;
end;
end;
end;
TApplicationEvent.WillBecomeForeground:
Notificationcenter1.CancelAll;
end;
end;
I use the OnCreate event for asking permission for sending notifications and trigger the AppEvent.
procedure TForm1.FormCreate(Sender: TObject);
var
AppEventSvc: IFMXApplicationEventService;
begin
if NotificationCenter1.AuthorizationStatus <> TAuthorizationStatus.Authorized then
begin
FPendingAction := Action;
NotificationCenter1.RequestPermission;
end;
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(AppEventSvc)) then
begin
AppEventSvc.SetApplicationEventHandler(AppEvent);
end;
end;
I have tested this code and for me, this works perfectly.

Wordpress xml-rpc client using idhttp fail with EIdConnClosedGracefully on android

Basic facts:
The application was created as a multiplatform default empty application.
Wordpress is on a NonSSL connection.
On windows the code (below) works flawlessly.
On Android the data is being received by the
server flawlessly, However the application is being shut down.
Debug shows the exception IdConnClosedGracefully
The "try except" does not intercept the exception.
XE8, indy 10
Questions:
Am I doing something wrong?
Why is the exception not being intercepted.
What can I do to prevent the shutdown?
the code:
procedure TForm8.Button1Click(Sender: TObject);
var
LPostURL : String;
LXMLStream : TMemoryStream;
LHttp: TIdHttp;
begin
TTask.Run(procedure
var
LPostURL : String;
LXMLStream : TMemoryStream;
LResStream : TMemoryStream;
LHttp: TIdHttp;
begin
LHttp := TIdHTTP.Create;
LHttp.HTTPOptions := LHttp.HTTPOptions - [hoForceEncodeParams];
LHttp.HandleRedirects:=true;
buildpost;
xml.Active:=true;
LPostURL := 'http://benkyo.tk/xmlrpc.php';//edit1.Text;
LXMLStream := TMemoryStream.Create;
XML.SaveToStream(LXMLStream);
try
try
memo1.lines.text:=LHttp.post(LPostURL, LXMLStream);
except
on E:exception do
memo1.Lines.Text:=('IdHTTP1.Post error'+ E.Message);
end;
finally
LHttp.Free;
LXMLStream.Free;
end;
end);
end;

Delphi XE7 Android - No mapping for unicode character exists in the target multi-byte code page

I am trying to fetch an image from a SOAP Web Service into a Delphi XE7 Android App using TSoapAttachment component.
procedure TTabbedwithNavigationForm.Button1Click(Sender: TObject);
Var img: TSOAPAttachment;
strm: TStream;
begin
img:= Service.GetImage('d:\pictures\pic.jpg'); <== Error on this line
if img <> nil then begin
strm:= TMemoryStream.Create;
img.SaveToStream(strm);
strm.Position:= 0;
Image1.Bitmap.LoadFromStream(strm);
strm.Free;
DeleteFile(img.CacheFile);
end;
end;
The Web Service is implemented as follows:
function TMyService.GetImage(const imgfile: AnsiString) : TSOAPAttachment; stdcall;
begin
Result:= TSOAPAttachment.Create;
Result.SetSourceFile(imgfile);
end;
This runs fine on Win32, but on Android gives error "No mapping for Unicode character exists in the target multi-byte code page" on the Service.GetImage line.

Write into the SQLite database from an Android service in Delphi (RAD Studio)

I have an Android application and service in the same process. Write code under RAD Studio Delphi 10.1.
I need to get geographic coordinates in Android Service (that I'm doing well) and write them to the SQLite database.
And from time to time the application can (when the user needs) process the coordinates in the user interface.
When I put TConnection (any - ADO, FireDAC, UniDAC) into DataModule not even make an active connection, the service stops working, even not running the OnStartCommand event.
Monitor.bat shows no obvious errors.
Please tell me how to work with a SQLite database in Android Service and it Android Application at the same time.
I found a solution:
I updated UniDAC components for Berlin to latest version (6.3.12).
TUniConnection and TUniQuery well work with SQLite in Android Service.
Add to Project->Deployment of the host application my SQLite DB-file, Remote Path sets to ".\assets\internal\".
I hope this code will useful for you.
procedure TDM.conSQLiteBeforeConnect(Sender: TObject);
begin
{$IF DEFINED(iOS) or DEFINED(ANDROID)}
conSQLite.Database := TPath.Combine(TPath.GetDocumentsPath, 'mybase.sqlite');
{$ENDIF}
end;
procedure TDM.conSQLiteError(Sender: TObject; E: EDAError; var Fail: Boolean);
begin
Log('--- DB error: %s:', [E.Message]);
Fail := False;
end;
function TDM.AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
Log('+ START with Intent: ' + JStringToString(Intent.getAction.toString), []);
if Intent.getAction.equalsIgnoreCase(StringToJString('StopIntent')) then
begin
try
conSQLite.Disconnect;
Log('- DB disconnected', []);
except
on E: Exception do
Log('- can not to disconnect DB', [E.Message]);
end;
Log('... service to be stoped', []);
JavaService.stopSelf;
Result := TJService.JavaClass.START_NOT_STICKY; // don't reload service
end
else
begin
Log('... service started', []);
try
conSQLite.Connect;
Log('+ DB connected', []);
UniQuery.SQL.Text := 'select count(*) as ALLREC from orders';
UniQuery.Open;
if UniQuery.RecordCount > 0 then
begin
UniQuery.First;
Log('... record count: %s', [UniQuery.FieldByName('ALLREC').AsString]);
end;
UniQuery.Close;
except
on E: Exception do
Log('- can not to connect DB: %s', [E.Message]);
end;
Result := TJService.JavaClass.START_STICKY; // rerun service if it stops
end;
end;
I have struggled the same issue but I started to use TSQLConnection (dbexpress) component with TSQLQuery (dbexpress) component and these are components wrok well in Android service.

Android push notification with actions/parameters

I just made an app with Delphi XE6 that receives push notifications with kinvey based on this example
When the application is running and I send a push the PushEvent handler receives it well, but when the application is closed and I press the notification it only opens my app.
Can I know which notification was pressed and get parameters from it?
Thanks in advance.
Edit:
I get a little bit closer, in my FormCreate ask for Extras:
procedure TForm1.FormCreate(Sender: TObject);
var
LIntent: JIntent;
LExtras: JBundle;
LExtrasArray: TJavaObjectArray<AndroidApi.JNI.JavaTypes.JObject>;
begin
LIntent := SharedActivity.getIntent;
try
if LIntent <> nil then
begin
LExtras := LIntent.getExtras;
if LExtras <> nil then
begin
//Now try to get the data
LExtrasArray := LExtras.KeySet.toArray;
for I := 0 to LExtrasArray.Length - 1 do
Memo1.Lines.Add(JStringToString(LExtrasArray.Items[I].toString));
end;
end;
finally
LIntent := nil;
end;
end;
With this code I get "gcm" in my memo.
So, when the notification fires my app I get this Extra available.
Now the problem is how I get info about that extra?
I tried LExtras.getString(StringToJString('message')) but this writes '' instead of the push message
Sarina DuPont answer me in her Blog
PushEvents component has a property StartupNotification for this purpose
procedure TMainForm.FormShow(Sender: TObject);
begin
if Assigned(PushEvents.StartupNotification) then
//Do something here!
//for example
//Memo.Text := PushEvents.StartupNotification.Message;
end;

Categories

Resources