Delphi and Android services (part 2)

  

It’s been a while now since I posted up the link to my Delphi service example on Google Play. I mentioned at the time that it was not a trivial exercise and was somewhat imperfect in implementation (although I’d done my best to disguise this fact). Indeed you only really see an issue if you are looking at the logcat output from the app (either using the command-line adb logcat command, or using the deprecated DDMS tool or the replacement Monitor tool). Alas the app dies while endeavouring to tidy up for exit… I also mentioned at the time that I was hoping to work out some scheme to remedy the situation before releasing the example source, something to do with pride or perfectionism or some such… Anyway, with the day job, the evening job, the prep work for last week’s Be-Delphi 3.0 event in Belgium my plans haven’t been accomplished and I have still to work out if it’s feasible to clean up the shutdown part of the sample. All my current efforts have come to little in resolving it. So, given that there have been a number of requests for the source I have now made it available at this download link. This is the same as the sample online other than it has no splash screen. This example is free of a splash screen to simplify the example and leave it clearer. There are a couple of examples that incorporate a splash screen and have similar custom build steps available in my CodeRage 8 session files. Please note that the archive has a Readme file in it, and you should take the time to read through this file carefully as it explains the non-standard build steps required to get the sample successfully built for deployment. If you don’t follow the Readme file, then you’re unlikely to get any joy with the sample at all. For your convenience I include the text of the ReadMe file below. As you will see, since Delphi has no catering for building Delphi services or broadcast receivers, I’ve had to go “round the houses” to do it, using Java stubs, and pertinent thread-switching between the Java and Delphi threads. As you will also perhaps appreciate, I don’t recommend this as a productive way of building an Android service. However if you need to add a service to a Delphi Android application, then this approach allows you to do so. But… as of the time of posting there is a still the small matter of a (slightly brushed under the carpet) death-by-tombstoning bug on shutdown. If any keen reader can work out a clean way of closing I’d be most obliged to hear of it! [Update] When the small Java source files get compiled, the Android dx tool expects them to be compiled by the JDK 1.6.x compiler as opposed to the JDK 1.7.x compiler. If you have JDK 1.7.x installed, you hit a problem with dx reporting: bad class file magic (cafebabe) or version (0033.0000) However, to avoid forcing a reinstall of JDK 1.6 you might like to modify my build.bat batch files and add in extra command line switches to the javac.exe command-lines. You need to insert this after the javac.exe command to force Java 1.6 byte code output, which is digestible by the Android dx command: -source 1.6 -target 1.6 [Update 2 – Feb ‘15] There has been a longstanding issue with my service sample, which I originally wrote for Delphi XE5. The issue was that when updated and tested in Delphi XE7, it hung on startup with a black screen. This was rather disappointing. Unfortunately I’ve been very much tied up with stuff and haven’t managed to get to looking into the problem up until now. Anyway, Aleksey N’s comment (below) put me onto the way of getting it to work. The OnCreate handler now triggers a timer to start the service, after the initialisation process. The download sample project now incudes both a Delphi XE5 and a Delphi XE7 project. Enjoy! Service example===============This project implements an Android service along with a coupleof broadcast receivers to catch and respond to intent messagesflung around the system. The service and receiver classes areimplemented as extremely shallow Java classes, which need to becompiled and converted to an appropriate executable format(dex), and then merged into the other dex code deployed with anAndroid app.The Java code calls into native Delphi code to implementthe “business end” of the service and receivers.Build the Java support files:—————————-In the project’s java directory are some source files: – java\src\com\blong\test\ActivityReceiver.java – java\src\com\blong\test\SampleService.java – java\src\com\blong\test\ServiceReceiver.javaThese need to be compiled to .class files, archived into a .jarfile, converted from Java byte code to DEX (Dalvik Executable)format and merged into the normally used (by Delphi’s Androiddeployment process) classes.dex.To set this up, follow these steps: – Ensure the useful subdirectory of Android SDK’s build-toolsdirectory is on the system PATH (e.g. C:\Android\android-sdk-windows\build-tools\18.0.1 or C:\Users\Public\Documents\RADStudio\12.0\PlatformSDKs\adt-bundle-windows-x86-20130522\sdk\android-4.2.2) – Ensure the Java Development Kit’s bin directory is on thesystem PATH (e.g. C:\Program Files (x86)\Java\jdk1.6.0_23\bin) – Run a command prompt in the project’s java subdirectory andensure you can successfully launch each of these: – javac – jar – dx – Review the build.bat file and ensure the environmentvariables are set correctly: – ANDROID needs to point to your Android SDK basedirectory, e.g. C:\Users\Public\Documents\RAD Studio\12.0\PlatformSDKs\adt-bundle-windows-x86-20130522\sdk orC:\Android\android-sdk-windows – ANDROID_PLATFORM needs to point at an installed SDKplatform installation, e.g. %ANDROID%\platforms\android-15 or %ANDROID%\platforms\android-17. Check for one that is installed. – DX_LIB needs to point to the lib subdirectory under theAndroid SDK build-tools directory, e.g. %ANDROID%\build-tools\18.0.1\lib or %ANDROID%\build-tools\android-4.2.2\lib – EMBO_DEX needs to point to the Delphi-supplied Androidclasses.dex file, wrapped in quotes to take care of any spacesin the path, e.g. “C:\Program Files (x86)\Embarcadero\RADStudio\12.0\lib\android\debug\classes.dex” – Run build.bat – You should now have a new file in the project directory treecalled java\output\dex\classes.dexThis file replaces the supplied classes.dex and has the Javaservice and broadcast receiver compiled classes included in it.Set the new classes.dex for deployment:————————————–Open the project in the IDEChoose Project | DeploymentNote that the classes.dex file from the project’sjava\output\dex directory is set to be deployed.You must ensure that the default classes.dex file is de-selected. As you switch configurations, this de-selection willbe lost (the file will be re-set to be deployed) and will needto again be de-selected. This is an IDE bug with Delphi XE5 RTMand XE5 UP1 and is logged in Quality Central as bug 118472.Register the service:——————–This has already been done for this demo. It involves thefollowing: – Open the Android manifest template,AndroidManifest.template.xml, which is generated on firstcompile, from the project directory – Add in a description of the service in the applicationelement: <service android:name=”com.blong.test.SampleService” />Build the Delphi Android application library:——————————————–In the IDE choose Project | Compile ServiceApp (or pressCtrl+F9)Deploy the library to an Android application package (.apk):———————————————————–In the IDE choose Project | Deploy libServiceApp.soInstall the app on the device:—————————–In the IDE choose Run | Run Without Debugging (or pressCtrl+Shift+F9).This will implicitly do the compile and deploy steps above, sothey are actually optional.This step will uninstall the app if already installed and theninstall the newly built version.

Comments are closed.