Monday 25 November 2013

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 couple
of broadcast receivers to catch and respond to intent messages
flung around the system. The service and receiver classes are
implemented as extremely shallow Java classes, which need to be
compiled and converted to an appropriate executable format
(dex), and then merged into the other dex code deployed with an
Android app.
The Java code calls into native Delphi code to implement
the "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.java
These need to be compiled to .class files, archived into a .jar
file, converted from Java byte code to DEX (Dalvik Executable)
format and merged into the normally used (by Delphi's Android
deployment process) classes.dex.
To set this up, follow these steps:
 - Ensure the useful subdirectory of Android SDK's build-tools
directory is on the system PATH (e.g. C:\Android\android-sdk-
windows\build-tools\18.0.1 or C:\Users\Public\Documents\RAD
Studio\12.0\PlatformSDKs\adt-bundle-windows-x86-20130522
\sdk\android-4.2.2)
 - Ensure the Java Development Kit's bin directory is on the
system PATH (e.g. C:\Program Files (x86)\Java\jdk1.6.0_23\bin)
 - Run a command prompt in the project's java subdirectory and
ensure you can successfully launch each of these:
    - javac
- jar
- dx
 - Review the build.bat file and ensure the environment
variables are set correctly:
    - ANDROID needs to point to your Android SDK base
directory, e.g. C:\Users\Public\Documents\RAD Studio\12.0
\PlatformSDKs\adt-bundle-windows-x86-20130522\sdk or
C:\Android\android-sdk-windows
    - ANDROID_PLATFORM needs to point at an installed SDK
platform 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 the
Android 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 Android
classes.dex file, wrapped in quotes to take care of any spaces
in the path, e.g. "C:\Program Files (x86)\Embarcadero\RAD
Studio\12.0\lib\android\debug\classes.dex"
 - Run build.bat
 - You should now have a new file in the project directory tree
called java\output\dex\classes.dex
This file replaces the supplied classes.dex and has the Java
service and broadcast receiver compiled classes included in it.
Set the new classes.dex for deployment:
--------------------------------------
Open the project in the IDE
Choose Project | Deployment
Note that the classes.dex file from the project's
java\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 will
be lost (the file will be re-set to be deployed) and will need
to again be de-selected. This is an IDE bug with Delphi XE5 RTM
and XE5 UP1 and is logged in Quality Central as bug 118472.
Register the service:
--------------------
This has already been done for this demo. It involves the
following:
 - Open the Android manifest template,
AndroidManifest.template.xml, which is generated on first
compile, from the project directory
 - Add in a description of the service in the application
element:

<service android:name="com.blong.test.SampleService" />
Build the Delphi Android application library:
--------------------------------------------
In the IDE choose Project | Compile ServiceApp (or press
Ctrl+F9)
Deploy the library to an Android application package (.apk):
-----------------------------------------------------------
In the IDE choose Project | Deploy libServiceApp.so
Install the app on the device:
-----------------------------
In the IDE choose Run | Run Without Debugging (or press
Ctrl+Shift+F9).
This will implicitly do the compile and deploy steps above, so
they are actually optional.
This step will uninstall the app if already installed and then
install the newly built version.

102 comments:

  1. Thanks, All worked well! but also with this example we need to modify these instructions on javac command: -source 1.6 -target 1.6

    ReplyDelete
    Replies
    1. You make a perfectly excellent point. I shall amend the instructions :o)

      Delete
  2. Not working Samsung galaxy S3 , android 4.1.2 (the service close when activity is closed manually)
    But thanks!

    ReplyDelete
    Replies
    1. I can't remember what the code says, but I have a feeling that the app closing (by Back being pressed) deliberately tries to shut down the service. So unless I misunderstand, you're reporting expected behaviour.
      On the other hand, pressing Home should just have the form unregister its broadcast receiver so it doesn't get service messages until it is brought back to the foreground again.

      Delete
    2. Correct, you are right

      Delete
  3. Hi Brain.
    Thanks for your Post.
    İ download and try Google play work fine. but im read all your write and try to install app on my xe5. deploy or copy apk on my devices but not install app.
    return error on devices : "could not install application"
    What is the problem ?
    Thanks...

    ReplyDelete
    Replies
    1. Well, it's a vague error you report. Generally you get better error responses when you install manually via adb.exe.
      Read up on how to get the Android SDK tool adb.exe working in a command prompt, then you can use a command-line such as:

      adb install _path_to_apk_file_

      See if that reports an error at the command prompt, and also look into how you can use the Android SDK tools Monitor or DDMS to see the device's logcat in a GUI, where you might find some clues in the message emitted during the installation failure.

      It would appear you've messed a step somewhere as it works fine for me and others.

      Delete
  4. I've followed the instructions, but I'm experiencing errors (INSTALL_FAILED_DEXOPT). Logcat output;

    12-08 23:25:45.856: I/PackageManager(776): Running dexopt on: com.thoughtcloud.HeavySleeper
    12-08 23:25:45.866: W/dalvikvm(14906): DexOptZ: zip archive '/data/app/com.thoughtcloud.HeavySleeper-1.apk' does not include classes.dex
    12-08 23:25:45.866: W/installd(179): DexInv: --- END '/data/app/com.thoughtcloud.HeavySleeper-1.apk' --- status=0xff00, process failed
    12-08 23:25:45.866: E/installd(179): dexopt in='/data/app/com.thoughtcloud.HeavySleeper-1.apk' out='/data/dalvik-cache/data@app@com.thoughtcloud.HeavySleeper-1.apk@classes.dex' res=65280
    12-08 23:25:45.866: W/PackageManager(776): Package couldn't be installed in /data/app/com.thoughtcloud.HeavySleeper-1.apk

    I setup my system as advised, compiled the classes.dex (with the 1.6 parameters) and made sure to add it to the deployment and uncheck the default one. When it comes to actually installing on the device (Run without Debugging), logcat returns the above.

    To add some further notes, I created a copy of the APK, renamed it to .zip and opened it with alzip to see whether the relevant files were there. Sure enough, on a non-custom/non-service APK, classes.dex is there, but in my service one, it's not present within the APK.

    Any ideas?

    ReplyDelete
    Replies
    1. Well, it looks like the classes.dex file is not actuallybeing deployed to the .apk.
      So I'd suggest analysing the added line in the deployment manager and ensure that it's definitely deploying to the same remote location as the original and to the same name, and also check all the deployment messages to observe whether the line gets executed.
      Clearly something basic is going awry here.

      Delete
    2. Hey Brian, it's John from EMBT support.

      So I ran into this specifically with XE5u2 and it drove me nuts. Turns out Avast started flagging classes.dex as bad and we are in process of getting them to fix. I don't know if you guys have Avast or any other AV software but worth a check.

      It was only the debug version of classes.dex it hit me in 2 different ways. 1) the AV software thoughtfully omitted the classes.dex in the debug folder upon install. The other is 2)even if you turned off AV for the install process, when you build the apk, the AV will either flag or skip classes.dex so your apk will fail.

      So you can turn off AV if this is the cause, or switch to "release" mode as that version of classes.dex did not get flagged.

      Delete
    3. Thanks for the input there John. Sounds like a good thing to know about!

      Delete
  5. Thanks! Brian.

    I got it working on a Samsung Galaxy Note 10.1

    ReplyDelete
  6. Hi Brian. Thx for everything but I have a problem :-/
    I have "- javac","- jar".
    I could not find "- dx" what can I do.
    And sorry my bad english.

    ReplyDelete
    Replies
    1. Hi there. You should find dx.bat in the Android SDK directory tree, so maybe in somewhere like C:\Users\Public\Documents\RAD
      Studio\12.0\PlatformSDKs\adt-bundle-windows-x86-20130522
      \sdk\android-4.2.2 if the SDK was installed by Delphi or perhaps in somewhere like C:\Android\android-sdk-windows\build-tools\18.0.1 if you installed the Android SDK manually in advance.

      Delete
  7. Hi Brian, Thanks for the work and the code. I have a problem running the build.bat: Error: Could not find or load main class com.android.dx.merge.DexMerger

    What can it be? Thank.

    ReplyDelete
    Replies
    1. Hi, have you followed the README? Most likely the DX_LIB environment variable or one of the others not set appropriately.

      Delete
  8. Hi Brian, I have a problem running the build.bat.
    Could not find "android.content" and "android.util"

    src\com\blong\test\ActivityReceiver.java:3: error: android.content not find
    src\com\blong\test\ActivityReceiver.java:3: error: android.util not find

    Thanks.

    ReplyDelete
    Replies
    1. It looks likely you haven't gone through setting all the relevant environment variables in the batch file. One of them (as I recall) points to the Android SDK and one points to where one of the Android API libraries can be found to link against.
      Go through all the variables and make sure they point to valid values (you'll need to check which platforms are installed, for example) and then you should be fine.

      Delete
  9. hi brian, my classes.dex on deployment become grey, and i think that is the cause i cannot compile my apps, its raise an error when installing the .apk [INSTALL_FAILED_DEXOPT], i have follow the instruction carefully, please advice

    ReplyDelete
    Replies
    1. I don't have Delphi on the laptop I'm typing this on, but I would imagine a grey line in the deployment manager would be down to the file not existing. I can only suggest you examine what the deployment manager says is the location of classes.dex, to have a look in that location, and if it is not present, re-run the build.bat script and work out where the problem occurs in building this file.

      Delete
  10. Hello Brian. Thanks for your work!!.

    I have the problem that APP can't install, it says: INSTALL_FAILED_UID_CHANGED, and I can't install with Delphi IDE, ADB way, or copying APK to Android and trying to install with APK intaller..., in both cases I can't install. Please, how I can solve it?. Thanks!!.

    ReplyDelete
    Replies
    1. Make sure you manually uninstall the package from the command-line with adb. Then double check in the phone to ensure all trace has gone Then restart the phone. That sorted it out when I last had that issue.

      Delete
    2. That not work because was the first time that I trying to install app, but I have resolved renaming the project APP in Delphi. I don't know why, but it works :).

      Delete
    3. Cool - glad you got it working.
      The issue does come up if there is a clash with another package of the same name. Maybe that was the case here.

      Delete
    4. Please Brian, how I can use your code example for start ONLY an TTimer in background mode?. I want to execute some little code in TTimer, but I need that it must be an background process. Thanks!!.

      Delete
    5. The code in the sample reads messages sent from an Android service and does something with them (issues a toast message).

      Services are the way to have code execute in the background in Android. You can't really have the app do busy stuff in the background reliably - that's not the Android way. The background execution is done with the service.

      So the service runs in the background and sends messages to the UI, which are picked up by a broadcast receiver.

      Hopefully that helps clarify things. You need to use all the aspects of that service app to do what you require.

      Delete
    6. I have renamed Project file and all works!! Thanks, Brian! A good work.

      Delete
    7. Thanks for the feedback Ivan. Good to know this issue can be resolved by renaming the project.

      Delete
  11. Hi Brian. Thanks for the demo.
    I need that the service continue running if the main application is closed like other services.
    I try to comment the the "stopservice" when the vkHardwareBack is pressed but still the service is gone.
    Can the service stays on even if the software is not running?
    Thanks

    ReplyDelete
    Replies
    1. Hi, I'd imagine you would need to write an OnKeyDown handler and trap the Back button, and not terminate the activity/process. Maybe just send yourself to the background, like Home would do. I think a Delphi app needs its activity to remain present. As soon as the activity dies, the process will be culled, and so the service would go. You would need to work within those parameters.

      Delete
    2. Try the following to keep the process alive:

      function TServiceThread.NullPendingIntent : JPendingIntent;
      var
      service : JService;
      intent : JIntent;
      begin
      service := TJService.Wrap(SampleServiceObjectID);
      intent := TJIntent.Create;
      result := TJPendingIntent.JavaClass.getActivity(service.getApplicationContext,
      0,
      intent,
      0);
      end;

      in TServiceThread.Execute add

      var
      ntf : JNotification;
      begin
      service := TJService.Wrap(SampleServiceObjectID);
      ntf:= TJNotification.Create;
      ntf.icon := Service.getApplicationInfo.icon;
      ntf.setLatestEventInfo(Service.getApplicationContext,
      StrToJCharSequence('App Name),
      StrToJCharSequence('Descriptive text'),
      NullPendingIntent);

      service.startForeground(9999, ntf); // number is your choice

      This will mark the service as ongoing and show a notification icon.

      Thank You

      Delete
    3. Ah, nice one Gordon, thanks for posting.
      I shall have to try that approach out.

      Delete
  12. Hi Brian,
    I followed through the readme.txt to setup all my paths, but when I run build.bat, it throws up these errors :

    "Converting from jar to dex...


    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/ActivityReceiver.class
    ...while processing com/blong/test/ActivityReceiver.class

    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/SampleService.class
    ...while processing com/blong/test/SampleService.class

    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/ServiceReceiver.class
    ...while processing com/blong/test/ServiceReceiver.class
    3 warnings
    no classfiles specified"

    I'd be grateful if you could shed some light on this.

    thanks.

    ReplyDelete
  13. If anyone has the same problem as my last comment, I solved this by installing java jdk version 6, instead of 7.

    ReplyDelete
    Replies
    1. Hi Gareth, that works indeed. However I posted an update to the blog post above that shows a command-line switch that avoids the problem.

      Delete
  14. During build.bat running I have got this:

    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/ActivityReceiver.class
    ...while processing com/blong/test/ActivityReceiver.class

    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/SampleService.class
    ...while processing com/blong/test/SampleService.class

    trouble processing:
    bad class file magic (cafebabe) or version (0033.0000)
    ...while parsing com/blong/test/ServiceReceiver.class
    ...while processing com/blong/test/ServiceReceiver.class
    3 warnings

    ReplyDelete
    Replies
    1. Hi, check the update inline in the blog post that addresses this

      Delete
  15. I can't remember what the code says, but I have a feeling that the app closing (by Back being pressed) deliberately tries to shut down the service. So unless I misunderstand, you're reporting expected behaviour. On the other hand, pressing Home should just have the form unregister its broadcast receiver so it doesn't get service messages until it is brought back to the foreground again. Custom Web Design Services

    ReplyDelete
  16. Hi, i done everything in your readme.txt, buuuut it doesn't work, i know, probably is something i'm doing wrong AND I don't have ideia what i'm doing wrong D:
    The code fail in start on "javac" codeline. I checked and the variables are setted to the right place! Can you help me?

    ReplyDelete
    Replies
    1. If javac isn't found then your path hasn't been set up right. Most other errors are caused by not following the steps and not setting up the environment variables as instructed. Tricky to be more specific without any symptoms I'm afraid.

      Delete
    2. Hm, So
      "Ensure the Java Development Kit's bin directory is on the
      system PATH (e.g. C:\Program Files (x86)\Java\jdk1.6.0_23\bin)"
      Yes i'm sure the path are right there, and i performed the command prompt on this folder and Javac, Jar run normally, dx, i needed to go to android sdk folder to run and it's running normal too.
      I really don't know what's i'm doing wrong :\

      Delete
    3. You haven't yet supplied an error message/symptom, so it's still tricky to diagnose.

      Delete
    4. Oh Sorry! haha. I taked a print of error, so here is the link

      http://i.imgur.com/equ7M80.png

      I think i'm missing this part:
      "Run a command prompt in the project's java subdirectory and
      ensure you can successfully launch each of these:"

      Delete
    5. Well, I maintain you haven't set the paths up. I'm guessing each of those errors is saying that jvac, jar and dx were not available to be executed, and that is because they have not been found on the system path. You'll need to do some work on ensuring the right directories are on the path, or alternatively edit the batch file so that each reference to those 3 programs are fully qualified. That will also work fine.

      Delete
    6. That's is what i don't understand, where i put the right path of Javac, Jar and Dx? My Java are in C:\Program Files (x86)\Java\jdk1.6.0_23\bin. But i don't have idea where i need put this on the .bat.

      Sorry for my noob questions D:

      Delete
    7. Oh right, I see your problem now it's spelled out. Yeah I took for granted that adding to the Windows search path was a known thing. You need to add to the PATH variable, not in the batch file, but in the Windows environment variables (at least that's what the steps are hinting at).
      Instructions can be found at http://msdn.microsoft.com/en-us/library/office/ee537574.aspx or http://www.java.com/en/download/help/path.xml

      Delete
    8. Like i say, sorry for my noob questions. Whatever, much thanks! I resolved 50% percent of my problem haha.
      Now the build just don't created "test_classes.dex", i've seen and the paths are correctly set. I suspect my dx.bat size is too tiny(838kb), that size are normal?

      Delete
    9. I really don't have ideia what's i'm doing wrong, but after some reviews and changes on .bat, IS NOW FULLY WORKING HALLELUJAH!.
      Thanks for helping me, Brian!

      Delete
    10. Glad it's working now :o)

      Delete
  17. Hello,

    I see that in XE6 your QC 117762 has been resolved but I do not see how.
    classes.dex is still there. I supposed they will provide at least embarcadero.jar so we do not need to use dex2jar but I was wrong.
    The only fix is that original classes.dex is not check automatically for deployment?
    And they added in-app advertising component. But this is not the solution for you QC.

    Many thanks for your work.

    ReplyDelete
    Replies
    1. I think that QC was closed and marked as fixed in error. My understanding (after making some enquiries) is that you still must merge up a replacement classes.dex, or some other onerous solution, in Delphi XE6, just as with Delphi XE5.
      As you say, the only thing fixed, was my singular cited example of the problem - the AdMob Java library - not the problem itself.

      Delete
  18. hi Brain.I make an android app with Delphi xe5 .I want to integrate GCM service but i dont receive when app is not active please help me

    ReplyDelete
    Replies
    1. Hello. I didn't try GCM with XE5, but it's covered in these posts:
      http://stackoverflow.com/questions/18838485
      http://www.fmxexpress.com/google-cloud-messaging-on-android-with-delphi-xe5-firemonkey-component
      However you may be better moving to Delphi XE6 where it's already incorporated:
      http://www.fmxexpress.com/send-push-notifications-with-kinvey-in-delphi-xe6-firemonkey-on-android
      http://docwiki.embarcadero.com/RADStudio/XE6/en/What%27s_New_in_Delphi_and_C%2B%2BBuilder_XE6#Push_Notifications_for_iOS_and_Android

      Delete
  19. Hi Brian,

    Thanks for the great work. I have a related question, Is there a way to start an external service from my XE6 App. I am using C++ and here is my code.

    _di_JIntent Intent;
    Intent->setClassName(StringToJString("uk.co.example.bluetooth.service"),StringToJString("uk.co.example.bluetooth.service.example"));
    SharedActivity()->startService(Intent);

    I get a Access Violation when it is executed.

    Thanks

    ReplyDelete
  20. Well, it's a bit tricky without context. And I haven't yet played with C++ & Android. However I'd suggest that you might have not initialised the JIntent interface reference. In Delphi you can do that with something like:

    JIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_POWER_USAGE_SUMMARY);

    I daresay the C++ equivalent could be worked out from looking in the headers.

    Maybe to launch a specific service you initialise the intent with a different action before setting the classname?

    ReplyDelete
  21. Hi Brian,
    I would like to call a 3rd party android service. As I understand your approach i have to write a java class like your ActivityReceiver.java an the corresponding delphi class. To call the service I also have to merge that class into the dex file? Can you explain the steps I have to take?
    Thanks very much.

    Markus

    ReplyDelete
    Replies
    1. Hi, at some point I'll write up the details of dealing with broadcast receivers. For the time being you can see how to do the dex merging by reading through http://blong.com/Articles/DelphiXE5AndroidSplashScreen/SplashScreen.htm or http://blong.com/Articles/DelphiXE5AndroidActivityResult/ActivityResult.htm

      Delete
  22. CAN YOU SERVERAPP TO BACKGROOUND ,NOT SAMPESERVER.JAVA TO BACKGROUND

    ReplyDelete
    Replies
    1. Hello. I can't parse your question. I have no idea what you are looking to do.

      Delete
  23. Unfortunately the service does not start after rebooting.
    I am trying to use "BootReceiver.java" to force the service to start onBoot.
    But it always gives out error on rebooting...

    ReplyDelete
    Replies
    1. You could check out the details in here regarding auto-start support in Delphi Android apps: http://dannywind.nl/auto-start-delphi-xe5-android-app-after-boot

      Delete
    2. It seems like launching _service_ is not the same thing as launching _activity_

      Delete
    3. Oh right. I guess you need to take account of existing zen on the matter, e.g.: http://stackoverflow.com/questions/4562734
      Then you need to work out how readily you can apply that knowledge to a Delphi solution.

      Delete
    4. I know how to run Java-code as service. But this Java-code is unable to run Delphi-code! My BootReceiver successfully calls method "onReceive". Then it starts "SampleService.java". However method "onStartCommand" fails because sampleServiceOnStartCommandNative is unavailable (it is available only when activity is running)

      Delete
    5. It may well be that this is outside the scope of Delphi's ability. I haven't looked into it, but perhaps due to the way Delphi code gets loaded and kick-started, perhaps the activity is a required aspect of it. If I get chance to look into this sort of issue I'll come back and post more on it.

      Delete
  24. Hi Brian,
    thanks for your sample.
    I need that app start like a service but not show the main form.
    It's possible ?

    ReplyDelete
    Replies
    1. Sounds like you need just the service, and not the activity. I'm not sure Delphi is set up to support such things, as it's start-up code is oriented around an activity hosting a main form. But this is speculation - I haven't looked at this sort of issue yet.

      Delete
  25. Thanks for helping me,
    I think somethink like main form visible false when create or start first time.

    ReplyDelete
    Replies
    1. That may work; it's definitely worth a try. However I'm not sure whether Android apps with the main form being hidden will function as expected. Easy to test though :o)

      Delete
  26. Hi Brian
    i have read file Readme.txt and follow your steps, but i have a problem
    Error : Could not find or load main class com.android.dx.merger.DXMerger
    can you give me some solution?
    thanks before

    ReplyDelete
    Replies
    1. Hello. It sounds very much like DX_LIB has not been set up - that variable points to the Java lib that contains the DX merging code that is used to rebuild classes.dex. If you are using Delphi XE7 that aspect can be done much more efficiently now. You need to do the build step to get a .jar file, but the dexing and merging into classes.dex is not required as XE7 allows you to add a .jar directly to the project now - it takes care of those final details.
      If you read through all the fine detail in one of my Delphi Android articles, it might add detail onto the build process for this example. Maybe try the XE5 activity example at http://blong.com/Articles/DelphiXE5AndroidActivityResult/ActivityResult.htm

      Delete
  27. Hello Brian,
    The sample project does not compile in XE7. Mostly because Androidapi.Helpers is missing and aeYYY are now became TApplicationEvent.FinishedLaunching etc.

    Nice work! :)

    ReplyDelete
    Replies
    1. Yeah, I hear you Petar. It was written some while back :o)
      I'll try and find some time to write this up in an article that is more up to date.

      Delete
  28. Can I ask the reason that 'StartService; ' called twice on FormCreatre event and on StartServiceButtonClick.
    Is this a no problem One Call 'StartService;' ?

    ReplyDelete
    Replies
    1. There is probably no problem with a single call. I'm not sure offhand. Next time I open the project I'll double-check.
      However next time I open the project I will also need to look at why the code does not work in XE7 - I'm not sure what has changed, but the app, when altered suitably to compile, goes POP pretty quickly...

      Delete
  29. Hello Brian, good job, it works! The only problem is that I need te process be running also when I close the application. Can you explain how to do that please?

    ReplyDelete
    Replies
    1. I haven't looked into whether it's feasible to keep a service running when the Delphi activity closes down. Something for the lengthy to-do list methinks.

      Delete
  30. Hi Brain, i rebuild sources for xe7 , but the application crashes(halt) after splash screen...

    ReplyDelete
  31. logcat:I/ANRManager( 661): startAsyncDump: AnrDumpRecord{ Executing service com.blong.ServiceApp/com.blong.test.SampleService ProcessRecord{42128c48 6759:com.blong.ServiceApp/u0a95} IsCompleted:false IsCancelled:false }

    I/ActivityManager( 661): appNotResponding-before get this lock: ProcessRecord{42128c48 6759:com.blong.ServiceApp/u0a95} Executing service com.blong.ServiceApp/com.blong.test.SampleService

    I/ActivityManager( 661): appNotResponding-got this lock: ProcessRecord{42128c48 6759:com.blong.ServiceApp/u0a95} Executing service com.blong.ServiceApp/com.blong.test.SampleService

    I/ANRManager( 661): dumpAnrDebugInfo begin: AnrDumpRecord{ Executing service com.blong.ServiceApp/com.blong.test.SampleService ProcessRecord{42128c48 6759:com.blong.ServiceApp/u0a95} IsCompleted:false IsCancelled:false }

    I/ANRManager( 661): dumpAnrDebugInfoLocked: AnrDumpRecord{ Executing service com.blong.ServiceApp/com.blong.test.SampleService ProcessRecord{42128c48 6759:com.blong.ServiceApp/u0a95} IsCompleted:false IsCancelled:false }

    D/ANRManager( 661): Filepath isn't exist

    ReplyDelete
    Replies
    1. Hello Aleksey. Yes, I similarly found when I did a quick test in XE7 that things have changed such that the app hangs with ANR. It's something to do with the thread switching, as I recall.
      I wasn't too impressed. I really want to sort the issue out but I haven't got the time capacity to look into it just yet. I will get to it in the near future, though, and work out what the problem is and provide updated sample code.
      If anyone else works out how to resolve the problem before I do, I hope they post the fruits of their labour, as I would.

      Delete
    2. hi Brain. it's not work if StartService is in Main Form Create , and work onButtonClick. And i have another problem, i want sart service on BOOT_COMPLETED i added permissions, and write






      but is not work, have you any thinks?

      Delete
    3. why ServiceReceiverOnReceiveNative hav't implementation when its starts on action without activity... if fires i run activity all is ok!

      Delete
    4. Hi Aleksey, that's an interesting point. It looks like you worked out where my problem resides! I'll check that out.
      There was an article on how to run a Delphi app on boot completion, but I'm not sure what other issues would be introduced by the presence of a service, rather than just an activity.
      Not sure what you were trying to convey in your 6th Dec comment.

      Delete
    5. Thanks Aleksey - I updated the sample to use a one-shot timer and that gets things back up and running.

      Delete
  32. Hello Everyone and Happy New Year.I successfully implemented this demo in my project but my problem is i cannot make the service to not stop when app is killed from Recents .Does somebody done this and can you help me .Best Regards

    ReplyDelete
    Replies
    1. Hi, I don't believe Delphi's Android support is set up to permit the service to continue after the app is killed. At least I haven't seen a way to achieve this yet.

      Delete
  33. Hello. Maybe someone has a working example for XE7? For me app is starting and then does not respond...

    ReplyDelete
    Replies
    1. Hi there. I haven't got round to working out why it does that with XE7 yet. It's rapidly rising up my to do list. Hopefully get to it next week! I'll post on the blog when I've worked out what magic is required to get it back working.

      Delete
    2. All fixed now with the updated sample for XE7.

      Delete
  34. Hi Brian. I have Delphi xe5 with no updates. Im getting this error when trying to merge the files running the build.bat:

    "Exception in thread "main" com.android.dex.DexException: unknown output extensio
    n: Programaci¾n
    at com.android.dex.Dex.(Dex.java:115)
    at com.android.dx.merge.DexMerger.main(DexMerger.java:1111)

    Finished Merging"

    Which could be the reason for this?

    ReplyDelete
  35. Hi Mr Brain, Execelent Blog Post. I am trying compile your sample. Following the post, I did the settings but I am have many compile errors. I am a newbie in java complie.
    Could you give a help about what is wrong?
    Thanks in advance, Luiz

    C:\....\DelphiServiceDemo\XE7\java>build

    Compiling the Java service activity source files

    warning: [options] bootstrap class path not set in conjunction with -source 1.6
    src\com\blong\test\ActivityReceiver.java:3: error: package android.content does
    not exist
    import android.content.BroadcastReceiver;
    ^
    src\com\blong\test\ActivityReceiver.java:4: error: package android.content does
    not exist
    import android.content.Intent;
    ^
    src\com\blong\test\ActivityReceiver.java:5: error: package android.content does
    not exist
    import android.content.Context;
    ^
    src\com\blong\test\ActivityReceiver.java:6: error: package android.util does not
    exist
    import android.util.Log;
    ^
    src\com\blong\test\ActivityReceiver.java:8: error: cannot find symbol
    public class ActivityReceiver extends BroadcastReceiver
    ^
    symbol: class BroadcastReceiver
    src\com\blong\test\ActivityReceiver.java:12: error: cannot find symbol
    public native void activityReceiverOnReceiveNative(Context context, Inte
    nt receivedIntent);
    ^
    src\com\blong\test\SampleService.java:15: error: cannot find symbol
    Log.d(TAG, "Constructor");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:23: error: cannot find symbol
    Log.d(TAG, "onDestroy");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:30: error: cannot find symbol
    Log.d(TAG, "Native onDestroy implementation is missing.
    Either the app was built wrong or it is exiting.");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:20: error: method does not override or imp
    lement a method from a supertype
    @Override
    ^
    src\com\blong\test\SampleService.java:38: error: cannot find symbol
    Log.d(TAG, "onBind");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:35: error: method does not override or imp
    lement a method from a supertype
    @Override
    ^
    src\com\blong\test\SampleService.java:47: error: cannot find symbol
    Log.d(TAG, "onStartCommand");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:54: error: cannot find symbol
    Log.d(TAG, "Native onStartCommand implementation is miss
    ing. Either the app was built wrong or it is exiting.");
    ^
    symbol: variable Log
    location: class SampleService
    src\com\blong\test\SampleService.java:55: error: cannot find symbol
    return START_STICKY;
    ^
    symbol: variable START_STICKY
    location: class SampleService
    src\com\blong\test\SampleService.java:44: error: method does not override or imp
    lement a method from a supertype
    @Override
    ^
    src\com\blong\test\ServiceReceiver.java:17: error: cannot find symbol
    Log.d(TAG, "onReceive");
    ^
    symbol: variable Log
    location: class ServiceReceiver
    src\com\blong\test\ServiceReceiver.java:14: error: method does not override or i
    mplement a method from a supertype
    @Override
    ^
    41 errors
    1 warning

    Creating jar containing the new classes

    output\classes\com : no such file or directory
    Tidying up

    The system can not found the specified path

    ReplyDelete
    Replies
    1. Hello. It looks like you haven't updated the variable definitions in the build batch file correctly. The things it is complaining about are part of the Android SDK library. So update ANDROID and ANDROID_PLATFORM (read the notes above) appropriately and you should get further.

      Delete
  36. Hi, I have seen my error. It´s working now.
    Based on your post I did a GCMReceiver to gcm push notifications . It´s working only when the app is active. I am using XE7 and I´d like to change the behaviour of xe7 pushservice. I´d like to add custom songs and icon with push notfications summary stacked on status bar when I receive new notifications. for exampe:"ICON My new message(5)" Is there a way of to do it? Also, I´d like the app to continue to work when the app is inactive or closed.
    Regards, Luiz

    ReplyDelete
    Replies
    1. Great to hear you have the code up and running.
      I haven't explored the GCM stuff so am not too familiar with what you can or can't do with it. However to have things happening in the background you pretty much need a service, which Delphi isn't too well set up for, unfortunately. It's more designed for regular applications.

      Delete
  37. Hi Brain, thanks for your code.
    I done everything in your readme.txt, but in my sony xperia z1 phone appear this error: "Unfortunately, Delphi Service Demo App has stopped."
    In my Lenovo Tablet this program works well.

    ReplyDelete
    Replies
    1. The first port of call here is to run up monitor.bat from the Android SDK folder tree and look at the logcat messages that are emitted from your app, and scrutinise those that appear around the crash.
      They may be instructive.

      Delete
  38. Hello Brian, i did exactly as the instructions in the readme.txt
    but get this and doesn't work.

    Glad for any help, thank you.


    warning: [options] bootstrap class path not set in conjunction with -source 1.6
    [parsing started RegularFileObject[c:\Java\bin\src\com\blong\test\ActivityReceiv
    er.java]]
    [parsing completed 10ms]
    [parsing started RegularFileObject[C:\Java\bin\src\com\blong\test\SampleService.
    java]]
    [parsing completed 1ms]
    [parsing started RegularFileObject[C:\Java\bin\src\com\blong\test\ServiceReceive
    r.java]]
    [parsing completed 1ms]
    [search path for source files: C:\Java\Android\platforms\android-21\android.jar]

    [search path for class files: c:\Java\jre\lib\resources.jar,c:\Java\jre\lib\rt.j
    ar,c:\Java\jre\lib\sunrsasign.jar,c:\Java\jre\lib\jsse.jar,c:\Java\jre\lib\jce.j
    ar,c:\Java\jre\lib\charsets.jar,c:\Java\jre\lib\jfr.jar,c:\Java\jre\classes,c:\J
    ava\jre\lib\ext\access-bridge-64.jar,c:\Java\jre\lib\ext\dnsns.jar,c:\Java\jre\l
    ib\ext\jaccess.jar,c:\Java\jre\lib\ext\localedata.jar,c:\Java\jre\lib\ext\sunec.
    jar,c:\Java\jre\lib\ext\sunjce_provider.jar,c:\Java\jre\lib\ext\sunmscapi.jar,c:
    \Java\jre\lib\ext\zipfs.jar,C:\Java\Android\platforms\android-21\android.jar]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /Object.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /String.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/app/Service.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/os/IBinder.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/ComponentCallbacks2.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/ComponentCallbacks.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/ContextWrapper.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/view/ViewDebug.class)]]

    [wrote RegularFileObject[C:\Java\bin\output\classes\com\blong\test\ActivityRecei
    ver.class]]
    [checking com.blong.test.SampleService]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /Error.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/pm/PackageManager.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/pm/PackageManager$NameNotFoundException.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/util/AndroidException.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /Exception.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /Throwable.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /RuntimeException.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/IntentSender.class)]]
    [loading ZipFileIndexFileObject[C:\Java\Android\platforms\android-21\android.jar
    (android/content/IntentSender$SendIntentException.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/io/I
    OException.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/io/F
    ileNotFoundException.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /UnsatisfiedLinkError.class)]]
    [loading ZipFileIndexFileObject[c:\Java\lib\ct.sym(META-INF/sym/rt.jar/java/lang
    /LinkageError.class)]]
    [wrote RegularFileObject[C:\Java\bin\output\classes\com\blong\test\SampleService
    .class]]
    [checking com.blong.test.ServiceReceiver]
    [wrote RegularFileObject[C:\Java\bin\output\classes\com\blong\test\ServiceReceiv
    er.class]]
    [total 408ms]
    1 warning
    Incorrect command syntax...

    ReplyDelete
    Replies
    1. Hi, this output verbosity is not very familiar to me. However reading though it, it looks like it has compiled my 3 Java files and emitted 3 .class files for them.
      I haven't got the batch file here in front of me, but I assume the next step is to combine them into a single .jar file with the JDK jar.exe command. You should probably confirm this by looking in the batch file.
      It *seems* that an objection is being raised about this command.
      Maybe remove the ECHO OFF from the batch file and verify what is going on and where the failure arises; that would be a good start to diagnosing this problem.

      Delete