Development and remote installation of Java service for the Android Devices

In this article I’ve described:

  • How to develop simple Java service for the Android Devices;
  • How to communicate with a service from the other processes and a remote PC;
  • How toinstalland start the service remotely from the PC.

1. Java Service Development for the Android Devices

Services are long running background processes provided by Android. They could be used for background tasks execution. Tasks can be different: background calculations, backup procedures,internetcommunications, etc. Services can be started on the system requests and they can communicate with other processes using the Android IPC channels technology. The Android system can control the service lifecycle depending on the client requests, memory and CPU usage. Note that the service has lower priority than any process which is visible for the user.

Let’s develop the simple example service. It will show scheduled and requested notifications to user. Service should be managed using the service request, communicated from the simple Android Activity and from the PC.

First we need to install and prepare environment:

  • Download and install latest Android SDK from the official website (http://developer.android.com);
  • Download and install Eclipse IDE (http://www.eclipse.org/downloads/);
  • Also we’ll need to install Android Development Tools (ADT) plug-in for Eclipse.

After the environment is prepared we can create Eclipse Android project. It will include sources, resources, generated files and the Android manifest.

1.1 Service class development

First of all we need to implement service class. It should be inherited from the android.app.Service (http://developer.android.com/reference/android/app/Service.html) base class. Each service class must have the corresponding <service> declaration in its package's manifest. Manifest declaration will be described later. Services, like the other application objects, run in the main thread of their hosting process. If you need to do some intensive work, you should do it in another thread.

In the service class we should implement abstract method onBind. Also we override some other methods:

  1. onCreate(). It is called by the system when the service is created at the first time. Usually this method is used to initialize service resources. In our case the binder, task and timer objects are created. Also notification is send to the user and to the system log:

  1. onStart(Intent intent, int startId). It is called by the system every time a client explicitly starts the service by calling startService(Intent), providing the arguments it requires and the unique integer token representing the start request. We can launch background threads, schedule tasks and perform other startup operations.

  1. onDestroy(). It is called by the system to notify a Service that it is no longer used and is being removed. Here we should perform all operations before service is stopped. In our case we will stop all scheduled timer tasks.

  1. onBind(Intent intent). It will return the communication channel to the service. IBinder is the special base interface for a remotable object, the core part of a lightweight remote procedure call mechanism. This mechanism is designed for the high performance of in-process and cross-process calls. This interface describes the abstract protocol for interacting with a remotable object. The IBinder implementation will be described below.

To send system log output we can use static methods of the android.util.Log class (http://developer.android.com/reference/android/util/Log.html). To browse system logs on PC you can use ADB utility command: adb logcat.

The notification feature is implemented in our service as the special runnable object. It could be used from the other threads and processes. The service class has method showNotification, which can display message to user using the Toast.makeText call. The runnable object also uses it:

Code will be executed in the service thread. To execute runnable method we can use the special object android.os.Handler. There are two main uses for the Handler: to schedule messages and runnables to be executed as some point in the future; and to place an action to be performed on a different thread than your own. Each Handler instance is associated with a single thread and that thread's message queue. To show notification we should set message and call post() method of the Handler’s object.

1.2 IPC Service

Each application runs in its own process. Sometimes you need to pass objects between processes and call some service methods. These operations can be performed using IPC. On the Android platform, one process can not normally access the memory of another process. So they have to decompose their objects into primitives that can be understood by the operating system , and "marshall" the object across that boundary for developer.

The AIDL IPC mechanism is used in Android devices. It is interface-based, similar to COM or Corba, but is lighter . It uses a proxy class to pass values between the client and the implementation.

AIDL (Android Interface Definition Language) is an IDL language used to generate code that enables two processes on an Android-powered device to communicate using IPC. If you have the code in one process (for example, in Activity) that needs to call methods of the object in another process (for example, Service), you can use AIDL to generate code to marshall the parameters.

Service interface example showed below supports only one sendNotification call:

The IBinder interface for a remotable object is used by clients to perform IPC. Client can communicate with the service by calling Context’s bindService(). The IBinder implementation could be retrieved from the onBind method. The INotifyService interface implementation is based on the android.os.Binder class (http://developer.android.com/reference/android/os/Binder.html):

As it was described above, the notifications could be send using the Handler object’s post() method call. The NotificaionRunnable object is passed as the method’s parameter.

On the client side we can request IBinder object and work with it as with the INotifyService interface. To connect to the service the android.content.ServiceConnection interface implementation can be used. Two methods should be defined: onServiceConnected, onServiceDisconnected:

The bindService method can be called from the client Activity context to connect to the service:

The unbindService method can be called from the client Activity context to disconnect from the service:

Context.unbindService(conn);

1.3 Remote service control

Broadcasts are the way applications and system components can communicate. Also we can use broadcasts to control service from the PC. The messages are sent as Intents, and the system handles dispatching them, including starting receivers.

Intents can be broadcasted to BroadcastReceivers, allowing messaging between applications. By registering a BroadcastReceiver in application’s AndroidManifest.xml (using <receiver> tag) you can have your application’s receiver class started and called whenever someone sends you a broadcast. Activity Manager uses the IntentFilters, applications register to figure out which program should be used for a given broadcast.

Let’s develop the receiver that will start and stop notify service on request. The base class android.content.BroadcastReceiver should be used for these purposes (http://developer.android.com/reference/android/content/BroadcastReceiver.html):

To send broadcast from the client application we use the Context.sendBroadcast call. I will describe how to use receiver and send broadcasts from the PC in chapter 2.

1.4 Android Manifest

Every application must have an AndroidManifest.xml file in its root directory. The manifest contains essential information about the application to the Android system, the system must have this information before it can run any of the application's code. The core components of an application (its activities, services, and broadcast receivers) are activated by intents. An intent is a bundle of information (an Intent object) describing a desired action — including the data to be acted upon, the category of component that should perform the action, and other pertinent instructions. Android locates an appropriate component to respond to the intent, starts the new instance of the component if one is needed, and passes it to the Intent object.

We should describe 2 components for our service:

  • NotifyService class is described in the <service> tag. It will not start on intent. So the intent filtering is not needed.
  • ServiceBroadcastReceived class is described in the <receiver> tag. For the broadcast receiver the intent filter is used to select system events:

2. Java service remote installation and start

2.1 Service installation

Services like the other applications for the Android platform can be installed from the special package with the .apk extension. Android package contains all required binary files and the manifest.

Before installing the service from the PC we should enable the USB Debugging option in the device Settings-Applications-Development menu and then connect device to PC via the USB.

On the PC side we will use the ADB utility which is available in the Android SDK tools directory. The ADB utility supports several optional command-line arguments that provide powerful features, such as copying files to and from the device. The shell command-line argument lets you connect to the phone itself and issue rudimentary shell commands.

We will use several commands:

  • Remote shell command execution: adb shell <command> <arguments>
  • File send operation: adb push <local path> <remote path>
  • Package installation operation: adb install <package>.apk

I’ll describe the package installation process in details. It consists of several steps which are performed by the ADB utility install command:

  • First of all the .apk package file should be copied to the device. The ADB utility connects to the device and has limited “shell” user privileges. So almost all file system directories are write-protected for it. The /data/local/tmp directory is used as the temporary storage for package files. To copy package to the device use the command:

adb push NotifyService.apk /data/local/tmp

  • Package installation. ADB utility uses special shell command to perform this operation. The “pm” (Package Manager?) utility is present on the Android devices. It supports several command line parameters which are described in the Appendix I. To install the package by yourself execute the remote shell command:

adb shell pm install /data/local/tmp/NotifyService.apk

  • Cleanup. After the package is installed, ADB removes the temporary file stored in /data/local/tmp folder using the “rm” utility:

adb shell rm /data/local/tmp/NotifyService.apk.

  • To uninstall package use the “pm” utility:

adb shell pm uninstall <package>

2.2 Remote service control

To be able to start and stop the NotifyService from the PC we can use the “am” (Activity Manager?) utility which is present on the Android device. The command line parameters are described in the Appendix II. The “am” utility can send system broadcast intents. Our service has the broadcast receiver which will be launched by the system request.

To start NotifyService we can execute remote shell command:

adb shell am broadcast –a NotifyServiceStart

To stop the NotifyService we can execute remote shell command:

adb shell am broadcast –a NotifyServiceStop

Note, that the NotifyServiceStart and NotifyServiceStop intents were described in the manifest file inside the <receiver> … <intent-filter> tag. Other requests will not start the receiver.

Appendix I. PM Usage (from Android console)

usage: pm [list|path|install|uninstall]
pm list packages [-f]
pm list permission-groups
pm list permissions [-g] [-f] [-d] [-u] [GROUP]
pm list instrumentation [-f] [TARGET-PACKAGE]
pm path PACKAGE
pm install [-l] [-r] PATH
pm uninstall [-k] PACKAGE
pm enable PACKAGE_OR_COMPONENT
pm disable PACKAGE_OR_COMPONENT

The list packages command prints all packages. Use
the -f option to see their associated file.

The list permission-groups command prints all known
permission groups.

The list permissions command prints all known
permissions, optionally only those in GROUP. Use
the -g option to organize by group. Use
the -f option to print all information. Use
the -s option for a short summary. Use
the -d option to only list dangerous permissions. Use
the -u option to list only the permissions users will see.

The list instrumentation command prints all instrumentations,
or only those that target a specified package. Use the -f option
to see their associated file.

The path command prints the path to the .apk of a package.

The install command installs a package to the system. Use
the -l option to install the package with FORWARD_LOCK. Use
the -r option to reinstall an exisiting app, keeping its data.

The uninstall command removes a package from the system. Use
the -k option to keep the data and cache directories around
after the package removal.

Appendix II. AM Usage (from Android console)

usage: am [start|broadcast|instrument|profile]
am start -D INTENT
am broadcast INTENT
am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]
[-w] <COMPONENT>
am profile <PROCESS> [start <PROF_FILE>|stop]
INTENT is described with:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>] [<URI>]
The start command starts activity. Use -D option to make 'DebugOption' true.
The broadcast command sends broadcast.
The instrument command starts instrumentation.
Use -r option to make 'rawMode' true.
Use -e option to add the pair of ARG_NAME and ARG_VALUE into Bundle.
Use -p option to specify profileFile.
Use -w option to make 'wait' true in order to new an instance of InstrumentationWatcher.
Use COMPONENT to specify the name of the instrumentation component.
The profile command turn on/off profiling in a particular process specified by PROCESS.
Use start option to turn on and stop to turn off.Use PROF_FILE to specify the file path of profile.
Use -a to set action specified by ACTION to be performed.
Use -d to create a Uri(data) which parses the given encoded URI string DATA_URI.
Use -t to specify the type specified by MIME_TYPE. Use -c to add a new category specified by
CATEGORY to the intent.
Use -e or --es to add extended data to the intent.EXTRA_KEY specifies the name of the extra data and
EXTRA_STRING_VALUE specifies the string data value.
Use --ez to add extended data to the intent. EXTRA_KEY specifies the name of the extra data and
EXTRA_BOOLEAN_VALUE specifies the serializable data value.
Use -e or --ei to add extended data to the intent. EXTRA_KEY specifies the name of the extra data and
EXTRA_INT_VALUE specifies the serializable data value.
Use -n to explicitly set the component specified by COMPONENT to handle the intent.
Use -f to set special flags controlling how this intent is handled.FLAGS specifies the desired flags.
Use URI to create an intent from a URI.

Resources used:

  • Android Installation Guide.

http://developer.android.com/sdk/1.5_r2/installing.html

  • Android Developer reference.

http://developer.android.com/reference/classes.html

  • Jesse Burns. Developing Secure Mobile Applications for Android.

https://www.isecpartners.com/files/iSEC_Securing_Android_Apps.pdf

  • Designing a Remote Interface Using AIDL

http://developer.android.com/guide/developing/tools/aidl.html



你可能感兴趣的:(android)