I have an application in Delphi that plays video. When I open another application, but blank the screen, I hear the Video sound all the time.
How can I detect that the screen has been blanked, or there has been a switch to another application ?
I found a solution.
uses FMX.Platform;
procedure TMyForm.FormCreate(Sender: TObject);
var
AppEventSvc:IFMXApplicationEventService;
begin
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService,IInterface(AppEventSvc)) then
begin
AppEventSvc.SetApplicationEventHandler(AppEvent);
end;
end;
function TMyForm.AppEvent(AAppEvent:TApplicationEvent;AContext:TObject):Boolean;
begin
if AAppEvent=TApplicationEvent.WillTerminate then
begin
// Do soomething
end;
Result:=True;
end;
Related
I am dealing with the following issue with Firemonkey (Delphi 10.4): When the Android OS will shut down and my app is still running, it does not trigger the OnCloseQuery, OnClose, and nor the OnDestroy events. Is there a way to detect or intercept the OS shutdown event? The same issue is presented when I kill the app with the square button (that is when I show the recently opened apps with the square button and I close the app that way).
Thank you in advance.
I finally found a solution from a TMS customer (Ken Randall "Randall_Ken" Active Customer.)
uses FMX.Platform;
procedure TMyForm.FormCreate(Sender: TObject);
var
AppEventSvc: IFMXApplicationEventService;
begin
if TPlatformServices.Current.SupportsPlatformService
(IFMXApplicationEventService, IInterface(AppEventSvc)) then
begin
AppEventSvc.SetApplicationEventHandler(AppEvent);
end;
end;
function TMyForm.AppEvent(AAppEvent: TApplicationEvent;
AContext: TObject): Boolean;
begin
if AAppEvent = TApplicationEvent.WillTerminate then
begin
// Do soomething
end;
Result := true;
end;
On Delphi XE8 i have simple function to check internet connection:
function TForm1.Internet: boolean;
begin
result:=false;
try
IdTCPClient1.ReadTimeout:=2500;
IdTCPClient1.ConnectTimeout:=2500;
IdTCPClient1.Port:=80;
IdTCPClient1.Host:='google.pl';
IdTCPClient1.Connect;
IdTCPClient1.Disconnect;
result:=true;
except
result:=false;
end;
end;
Everything works just fine in older android version but in andoid 6 the app just crashes (close) when i call IdTCPClient1.Connect.
Then I learned that this is blocking function and it has to be in worker thread so i wrote something like this:
type
TTest = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
and in the implementation section:
procedure TThread.Execute;
begin
try
Form1.IdTCPClient1.ReadTimeout:=2500;
Form1.IdTCPClient1.ConnectTimeout:=2500;
Form1.IdTCPClient1.Port:=80;
Form1.IdTCPClient1.Host:='google.pl';
Form1.IdTCPClient1.Connect;
Form1.IdTCPClient1.Disconnect;
except
showmessage('no internet connection');
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Test : TTest;
begin
Test := TTest.Create(False);
end;
but unfortunately the app is still closing on android 6 when i call TForm1.Button1Click (on windows and older android versions works just fine)
Please help me ;)
Is there something that can be checked from code point of view when an App is resumed on iOS and Android?
e.g. when an app gets minimized and restored (app is still running in background of device).
You need to use IFMXApplicationEventService to register a callback where the application will be notified:
uses FMX.Types, FMX.Platform;
function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
begin
case AAppEvent of
TApplicationEvent.FinishedLaunching: Log.d('Launched.');
TApplicationEvent.BecameActive: Log.d('Gained focus.');
TApplicationEvent.EnteredBackground: Log.d('Now running in background.');
TApplicationEvent.WillBecomeForeground: Log.d('Restoring from background.');
TApplicationEvent.WillBecomeInactive: Log.d('Going to lose focus.');
TApplicationEvent.WillTerminate: Log.d('Quitting the application.');
TApplicationEvent.LowMemory: Log.d('Device running out of memory.');
// iOS only
TApplicationEvent.TimeChange: Log.d('Significant change in time.');
TApplicationEvent.OpenURL: Log.d('Request to open an URL.');
end;
Result := True;
end;
procedure TForm11.FormCreate(Sender: TObject);
var
aFMXApplicationEventService: IFMXApplicationEventService;
begin
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService,
IInterface(aFMXApplicationEventService))
then
aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent)
else
Log.d('Application Event Service not supported.');
end;
More info about the event types here.
A good article on the subject by Paweł Głowacki (for Delphi XE5, but still useful).
In iOS You can add flag in
applicationDidEnterBackground
in appDelegate to know if the user enters the background and,
applicationDidBecomeActive
to know that the user returns to the app from background
Typically in a Delphi VCL application which uses a TDataset descendent as data storage (eg TClientDataset), in the Dataset1BeforeDelete handler we do something like this:
procedure TClientModule1.MyCDSBeforeDelete(DataSet: TDataSet);
begin
if MessageDlg('Delete?', mtCOnfirmation, [mbyes, mbNo], 0) <> mrYes then
SysUtils.Abort
end;
Now in a FMX application designed to run on Android, this becomes:
procedure TClientModule1.MyCDSBeforeDelete(DataSet: TDataSet);
MessageDlg('Delete?'
,
TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
if AResult <> mrYes then
Abort;
end
);
end;
Except, that's not going to work! The messagedlg is going to hold the user's attention, but the event handler code is going to continue and allow the record to be deleted anyway.
What's the solution?
Because modal window and Message Box currently are not supported in FMX for Android you should use some kind of "dog-nail" solution
Ad-Hoc solution #1, .
In main form or in form which should open Modal window write code like:
procedure TForm1.btnSelectClick(Sender: TObject);
begin
if fmSelect = nil then
begin
Application.CreateForm(TfmSelect, fmSelect);
fmSelect.Callback := Yahoo;
end;
fmSelect.Show;
end;
procedure TForm1.Yahoo(ASelectedItem: String);
begin
ShowMessage(ASelectedItem);
end;
in fmSelect should be your message and buttons with options (like Yes, No, May be, Not today).
in fmSelect form you should declare PUBLIC variable Callback: TCallback;
Once user press some button, you should call this function and close form:
procedure TfmSelect.btnSelectClick(Sender: TObject);
begin
if Assigned(Callback) then
Callback('user press button XXX');
Close;
end;
TCallback just regular function which return String type (you could change it to Integer).
TCallback = procedure (ASelected: String) of object;
Ad-Hoc solution #2
simulat to first, but with using hidden TComboBox. In combobox items will be stored all options, like "Yes", "No", "Maybe tomorrow". Once ComboBox was closed OnClosePopup event, you get value of user choise.
3. Take a look how it's done somewhere in Embarcadero samples (from XE8):
http://docwiki.embarcadero.com/RADStudio/XE8/en/Mobile_Tutorial:_Using_FireDAC_and_SQLite_%28iOS_and_Android%29
So in your case will be
private
procedure FCloseDialogProc(const AResult: TModalResult);
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageDlg('Want something', TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0, FCloseDialogProc);
end;
procedure TForm1.FCloseDialogProc(const AResult: TModalResult);
begin
Label1.Text := IntToStr(AResult);
// -1 -- click outside
// 6 -- yes
// 7 -- no
end;
The same project runs perfect on Windows/iOS platform, but cause deadlock on Android (two different android devices) after running for uncertain duration.
procedure TTestThread.FSynProc;
begin
Inc(Form1.FExecuted); //Variable of TForm
Form1.Text1.Text:= IntToStr(Form1.FExecuted);
end;
procedure TTestThread.Execute;
var
begin
while not Self.Terminated do
begin
Self.Synchronize(FSynProc);
sleep(10);
end;
end;
constructor TTestThread.Create;
begin
inherited Create(True);
Self.FreeOnTerminate:= True;
end;
destructor TTestThread.Destroy;
begin
inherited;
end;
code for launch TTestThread
procedure TForm1.StartTTProc;
begin
ftt:= TTestThread.Create; // Variable of TForm
ftt.Start;
end;
After StartTTProc, the number shows in 'Text1' increase continusely.
After running for an uncertain duration on android device, App freezed.
any advice?