From 248d645ade721f69775c1156210874ddcd679a5f Mon Sep 17 00:00:00 2001 From: gumartinm Date: Thu, 1 Mar 2012 08:11:17 +0100 Subject: [PATCH] First steps with android services. Trying to create an android service running in a different process and using IPC. I have no time but this looks like fun. --- Android/Testing/Test3/AndroidManifest.xml | 5 + Android/Testing/Test3/gen/de/android/test3/R.java | 3 + Android/Testing/Test3/res/values/strings.xml | 3 + .../src/de/android/test3/MobieAdHttpClient.java | 5 +- .../Test3/src/de/android/test3/TestService.java | 134 +++++++++++++++++++++ 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 Android/Testing/Test3/src/de/android/test3/TestService.java diff --git a/Android/Testing/Test3/AndroidManifest.xml b/Android/Testing/Test3/AndroidManifest.xml index e7208c7..2b26999 100644 --- a/Android/Testing/Test3/AndroidManifest.xml +++ b/Android/Testing/Test3/AndroidManifest.xml @@ -61,6 +61,11 @@ android:process="string" When having my service, here I should write the service process name --> + + + \ No newline at end of file diff --git a/Android/Testing/Test3/gen/de/android/test3/R.java b/Android/Testing/Test3/gen/de/android/test3/R.java index 21d25a0..8659e5d 100644 --- a/Android/Testing/Test3/gen/de/android/test3/R.java +++ b/Android/Testing/Test3/gen/de/android/test3/R.java @@ -36,6 +36,9 @@ public final class R { public static final int error_dialog_userpwd_error=0x7f040002; public static final int hello=0x7f040003; public static final int password=0x7f040006; + public static final int remote_service_label=0x7f04000c; + public static final int remote_service_started=0x7f04000a; + public static final int remote_service_stopped=0x7f04000b; public static final int username=0x7f040005; } } diff --git a/Android/Testing/Test3/res/values/strings.xml b/Android/Testing/Test3/res/values/strings.xml index 2c02d74..055a1ca 100644 --- a/Android/Testing/Test3/res/values/strings.xml +++ b/Android/Testing/Test3/res/values/strings.xml @@ -16,4 +16,7 @@ Log In OK Cancel + Remote Service Started + Remote Service Stopped + Remote Service Label diff --git a/Android/Testing/Test3/src/de/android/test3/MobieAdHttpClient.java b/Android/Testing/Test3/src/de/android/test3/MobieAdHttpClient.java index beb90d7..4b07a6d 100644 --- a/Android/Testing/Test3/src/de/android/test3/MobieAdHttpClient.java +++ b/Android/Testing/Test3/src/de/android/test3/MobieAdHttpClient.java @@ -84,8 +84,9 @@ public class MobieAdHttpClient implements Runnable //after a certain period of inactivity in order to conserve system resources, quite often without informing the client. //In case the default strategy turns out to be too optimistic, one may want to provide a custom keep-alive strategy. - //So AndroidHttpClient infinite timeout - //and the connection can be kept forever. + //AndroidHttpClient infinite time out (we could wait here forever if we do not use a timeout see: 2.1. Connection parameters + //http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html) The same for execute without handler. + //In that case the connection can be kept forever. StringBuilder builder = httpClient.execute(httpGet, handler); JSONTokener tokener = new JSONTokener(builder.toString()); JSONArray finalResult = new JSONArray(tokener); diff --git a/Android/Testing/Test3/src/de/android/test3/TestService.java b/Android/Testing/Test3/src/de/android/test3/TestService.java new file mode 100644 index 0000000..b0ae31e --- /dev/null +++ b/Android/Testing/Test3/src/de/android/test3/TestService.java @@ -0,0 +1,134 @@ +package de.android.test3; + +import java.util.ArrayList; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.widget.Toast; + +public class TestService extends Service { + + /** For showing and hiding our notification. */ + NotificationManager mNM; + /** Keeps track of all current registered clients. */ + ArrayList mClients = new ArrayList(); + /** Holds last value set by a client. */ + int mValue = 0; + + /** + * Command to the service to register a client, receiving callbacks + * from the service. The Message's replyTo field must be a Messenger of + * the client where callbacks should be sent. + */ + static final int MSG_REGISTER_CLIENT = 1; + + /** + * Command to the service to unregister a client, ot stop receiving callbacks + * from the service. The Message's replyTo field must be a Messenger of + * the client as previously given with MSG_REGISTER_CLIENT. + */ + static final int MSG_UNREGISTER_CLIENT = 2; + + /** + * Command to service to set a new value. This can be sent to the + * service to supply a new value, and will be sent by the service to + * any registered clients with the new value. + */ + static final int MSG_SET_VALUE = 3; + + /** + * Handler of incoming messages from clients. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_REGISTER_CLIENT: + mClients.add(msg.replyTo); + break; + case MSG_UNREGISTER_CLIENT: + mClients.remove(msg.replyTo); + break; + case MSG_SET_VALUE: + mValue = msg.arg1; + for (int i=mClients.size()-1; i>=0; i--) { + try { + mClients.get(i).send(Message.obtain(null, + MSG_SET_VALUE, mValue, 0)); + } catch (RemoteException e) { + // The client is dead. Remove it from the list; + // we are going through the list from back to front + // so this is safe to do inside the loop. + mClients.remove(i); + } + } + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + @Override + public void onCreate() { + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + + // Display a notification about us starting. + showNotification(); + } + + @Override + public void onDestroy() { + // Cancel the persistent notification. + mNM.cancel(R.string.remote_service_started); + + // Tell the user we stopped. + Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show(); + } + + /** + * When binding to the service, we return an interface to our messenger + * for sending messages to the service. + */ + @Override + public IBinder onBind(Intent intent) { + return mMessenger.getBinder(); + } + + /** + * Show a notification while this service is running. + */ + private void showNotification() { + // In this sample, we'll use the same text for the ticker and the expanded notification + CharSequence text = getText(R.string.remote_service_started); + + // Set the icon, scrolling text and timestamp + Notification notification = new Notification(R.drawable.stat_sample, text, + System.currentTimeMillis()); + + // The PendingIntent to launch our activity if the user selects this notification + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, Controller.class), 0); + + // Set the info for the views that show in the notification panel. + notification.setLatestEventInfo(this, getText(R.string.remote_service_label), + text, contentIntent); + + // Send the notification. + // We use a string id because it is a unique number. We use it later to cancel. + mNM.notify(R.string.remote_service_started, notification); + } + +} -- 2.1.4