I am creating a simple game for Android using Delphi XE5. I have a few resources, PNGs and Jpegs, I wanted to show a loading screen while my program loads up all the resources.
But I found putting TBitmap.LoadFromFile, or TBitmap.LoadFromStream code inside a android thread, caused the App to quit immediately and return to Launcher, in debug mode Delphi don't even catch an exception. (The code works perfectly on Windows, and without thread on Android)
I had to open logcat to see what went on, I saw something like "Error creating drawing context".
My question is there a way to make a loading screen for Android using Delphi XE5? So that a progress screen shows while images gets loaded in memory.
I created test project just to isolate the problem, here are the result. LoadFromFile is Thread 1. The log suggests thread actually ran, but Exceptions were raised afterwards???
Logcat screenshot: Source code: http://www.pockhero.com/wp-content/uploads/2013/10/threadtest1.7z
This apparently is a bug that is supposed to be fixed in the next update. To apply the fix to your code, declare this procedure:
uses
Androidapi.NativeActivity,
Posix.Pthread;
procedure MyEndThreadProc(ExitCode:Integer);
var
PActivity: PANativeActivity;
begin
PActivity := PANativeActivity(System.DelphiActivity);
PActivity^.vm^.DetachCurrentThread(PActivity^.vm);
pthread_exit(ExitCode);
end;
and assign it to the EndThreadProc from System.Classes:
procedure TForm1.FormCreate(Sender: TObject);
begin
EndThreadProc := MyEndThreadProc;
end;
With this fix you can set, for example, your thread with
FreeOnTerminate := true;
and then a code like this won't crash the application anymore:
TYourThread.Create(something, somethingelse).Start;
I have to give credit to Antonio Tortosa for posting this solution in Embarcadero forums.
After a lots of testing and colleague's help, my colleague and I solved the problem. The solution is not to terminate the thread and keep the thread running.
I know this is a bit odd. I tried to turn FreeOnTerminate off, but it only control the thread object, not the actually thread. It appears as if syncrhonized call is not syncrhonized. I have no idea when and where the bitmap is actually being used or copied. Possiblly there is another GUI thread somewhere, since Delphi compiled Android lib code don't run in the main thread anyway.
Here is working code.
procedure TBitmapThread.Execute;
begin
inherited;
BeforeExecute;
try
fBitmap := TBitmap.CreateFromFile(TPath.Combine(TPath.GetDocumentsPath, 'koala.jpg'));
// Sleep(2000);
Synchronize(UpdateImage);
// Keep the thread running
while not Terminated do
begin
Sleep(100);
end;
fBitmap.Free;
except
on E:Exception do
begin
Log.d('TestThread Exception: ' + E.message);
end;
end;
AfterExecute;
end;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.