-
Notifications
You must be signed in to change notification settings - Fork 104
Build your own Background Service
Before you start to build your own background service, I would advise that you review Using the MyService Sample. This takes you through a sample background service I have already produced and should provide a reasonable template to begin your own work.
This article assumes you have a reasonable knowledge of Java and Javascript.
You will need Eclipse (or similar) to perform the below.
If not adding to an existing project then create on (based on Cordova Android Getting Started):
- cordova create hello com.example.hello "HelloWorld"
- cd hello
- cordova platform add android
The bgs-core plugin provides all the core logic for the background service we are going to create. This is added to your project through the Cordova CLI:
cordova plugin add https://github.com/Red-Folder/bgs-core.git
This plugin will load the following into your project:
- Java source file in src\com.red_folder.phonegap.plugin.backgroundservice (it will also load some aidl files which are required for inter-process communication)
- backgroundservice.js which provides the core Javscript interface for the plugin
- Add the background service plugin into res/xml/config.xml
- Makes changes to your AndroidManifest.xml to enable boot start of the background service. Note that you have to registerForBootStart in your application to enable boot start.
The entire logic for your background service will be with a Java class.
Start by creating a new Java class - for this example we will call it MyService.java. Note at this point it is important to note the package of the class (first line) - the package plus the class name make the fully qualified class name - this will be required later. For my example, in keeping with the sample I provide, the package is com.red_folder.phonegap.plugin.backgroundservice.sample - thus making the full qualified class name:
com.red_folder.phonegap.plugin.backgroundservice.sample.MyService
Next add the following imports to your class (just under the package line):
import com.red_folder.phonegap.plugin.backgroundservice.BackgroundService;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Date;
The first three imports are required for any background service you will want to develop. The final three are to allow the production of a date & time format in our Hello World statement - thus are specific for this example and may not be required in your background service.
Next, amend the class statement to extend from BackgroundService. This should read:
public class MyService extends BackgroundService {
At this point, Eclipse is likely to offer to create auto-generated stubs for the methods that you can override. If it doesn't, add the following to your class:
@Override
protected JSONObject doWork() {
return null;
}
@Override
protected JSONObject getConfig() {
return null;
}
@Override
protected void setConfig(JSONObject config) {
}
@Override
protected JSONObject initialiseLatestResult() {
return null;
}
The only method we are going to use in this article is the doWork. More information on the other Java methods can be found in the Java Method Reference.
Within the doWork we are going to simply print the Hello World - along with the current date and time to the logcat. We will also make this message available to the HTML/ Javascript front-end via the result. Amend the doWork to the following:
@Override
protected JSONObject doWork() {
JSONObject result = new JSONObject();
try {
// Following three lines simply produce a text string with Hello World and the date & time (UK format)
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
String now = df.format(new Date(System.currentTimeMillis()));
String msg = "Hello World - its currently " + now;
// We output the message to the logcat
Log.d("MyService", msg);
// We also provide the same message in our JSON Result
result.put("Message", msg);
} catch (JSONException e) {
// In production code, you would have some exception handling here
}
return result;
}
At this point you should be able to save and compile the class.
Edit the AndroidMainfest.xml, and add the following within the application node:
<service android:name="com.red_folder.phonegap.plugin.backgroundservice.sample.MyService">
<intent-filter>
<action android:name="com.red_folder.phonegap.plugin.backgroundservice.sample.MyService" />
</intent-filter>
</service>
Notice the use of the fully qualified class name as discussed above.
Save the AndroidManifest.xml
Either amend your existing index.html, or create a new html file (be sure to include the cordova.js reference).
Within the file, add a script block with the following:
<script type="text/javascript" >
var myService;
document.addEventListener('deviceready', function() {
var serviceName = 'com.red_folder.phonegap.plugin.backgroundservice.sample.MyService';
var factory = cordova.require('com.red_folder.phonegap.plugin.backgroundservice.BackgroundService');
myService = factory.create(serviceName);
getStatus();
}, true);
function getStatus() {
myService.getStatus(function(r){displayResult(r)}, function(e){displayError(e)});
}
function displayResult(data) {
alert("Is service running: " + data.ServiceRunning);
}
function displayError(data) {
alert("We have an error");
}
</script>
The code in the deviceready block uses the bgs-core functionality to produce a Javascript interface for our plugin. Notice that I use the fully qualified class name in the serviceName.
The rest of the code is a basic implementation at this stage to keep it simple. We will add more code later.
At this stage, you should now be able to build and compile your application. If you run the application, you should get an alert box indicating that the background service is not running.
We will now expand the HTML/ Javascript front-end to:
- Register a handler for updated - this will automatically display the most recent result to the HTML page
- Start the service and enable it's timer to run every minute
First, within your HTML add the following:
<div id="resultMessage">None yet</div>
This will be used to display the latest result. This will be populated by the updateHandler - add this function to your script block:
function updateHandler(data) {
if (data.LatestResult != null) {
try {
var resultMessage = document.getElementById("resultMessage");
resultMessage.innerHTML = data.LatestResult.Message;
} catch (err) {
}
}
}
This handler looks to see if we have a LatestResult (see Returned JSON). Then attempts the set the resultMessage div we just added to the LatestResult.Message. We set the Message in step 2 within the doWork.
Now add the following functions to your script block:
function go() {
myService.getStatus(function(r){startService(r)}, function(e){displayError(e)});
};
function startService(data) {
if (data.ServiceRunning) {
enableTimer(data);
} else {
myService.startService(function(r){enableTimer(r)}, function(e){displayError(e)});
}
}
function enableTimer(data) {
if (data.TimerEnabled) {
registerForUpdates(data);
} else {
myService.enableTimer(60000, function(r){registerForUpdates(r)}, function(e){displayError(e)});
}
}
function registerForUpdates(data) {
if (!data.RegisteredForUpdates) {
myService.registerForUpdates(function(r){updateHandler(r)}, function(e){handleError(e)});
}
}
The above chains a number of the plugin Javascript methods together to:
- Get current status of the plugin getStatus
- Start the service if not already started startService
- Enabled the service timer if not already enabled enableTimer
- Registers the updateHander (added above) to received the latest results registerForUpdates
For more on the Javascript methods see [Javascript Method Reference](Javascript Method Reference).
Now amend the deviceready block to call go() instead of getStatus().
document.addEventListener('deviceready', function() {
var serviceName = 'com.red_folder.phonegap.plugin.backgroundservice.sample.MyService';
var factory = cordova.require('com.red_folder.phonegap.plugin.backgroundservice.BackgroundService');
myService = factory.create(serviceName);
go();
}, true);
The application should now compile and run. Every minute you should see the Hello World message in both the logcat and on the screen.
The above is a very primitive service, primarily to show the basics. I would recommend reviewing the following to understand how to expand on it:
- [Using the MyService Sample](Using the MyService Sample)
- [Javascript Method Reference](Javascript Method Reference)
- [Java Method Reference](Java Method Reference)
You may also want to convert your background service into a Plugman format plugin. To convert the above background sample into a plugin see [Build your own Plugin](Build your own Plugin)