First steps with android services.
authorgumartinm <gu.martinm@gmail.com>
Thu, 1 Mar 2012 07:11:17 +0000 (08:11 +0100)
committergumartinm <gu.martinm@gmail.com>
Thu, 1 Mar 2012 07:11:17 +0000 (08:11 +0100)
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
Android/Testing/Test3/gen/de/android/test3/R.java
Android/Testing/Test3/res/values/strings.xml
Android/Testing/Test3/src/de/android/test3/MobieAdHttpClient.java
Android/Testing/Test3/src/de/android/test3/TestService.java [new file with mode: 0644]

index e7208c7..2b26999 100644 (file)
                        android:process="string" When having my service, here I should write the service process name 
                </provider>-->
        
+               <service
+                   android:name=".TestService"
+               android:process=":testservice" >
+        </service>
+               
     </application>
 
 </manifest>
\ No newline at end of file
index 21d25a0..8659e5d 100644 (file)
@@ -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;
     }
 }
index 2c02d74..055a1ca 100644 (file)
@@ -16,4 +16,7 @@
     <string name="button_login">Log In</string>
     <string name="button_ok">OK</string>
     <string name="button_cancel">Cancel</string>
+    <string name="remote_service_started">Remote Service Started</string>
+    <string name="remote_service_stopped">Remote Service Stopped</string>
+    <string name="remote_service_label">Remote Service Label</string>
 </resources>
index beb90d7..4b07a6d 100644 (file)
@@ -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 (file)
index 0000000..b0ae31e
--- /dev/null
@@ -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<Messenger> mClients = new ArrayList<Messenger>();
+    /** 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);
+    }
+
+}