Add TelemetryService.java and associated files
authorMike Beattie <mike@ethernal.org>
Thu, 23 Feb 2012 03:41:26 +0000 (16:41 +1300)
committerKeith Packard <keithp@keithp.com>
Sun, 3 Jun 2012 02:39:55 +0000 (19:39 -0700)
Signed-off-by: Mike Beattie <mike@ethernal.org>
altosdroid/AndroidManifest.xml
altosdroid/Makefile.am
altosdroid/res/drawable-hdpi/am_status.png [new file with mode: 0644]
altosdroid/res/drawable-mdpi/am_status.png [new file with mode: 0644]
altosdroid/res/layout/telemetry_service_binding.xml [new file with mode: 0644]
altosdroid/res/layout/telemetry_service_controller.xml [new file with mode: 0644]
altosdroid/res/menu/option_menu.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java [new file with mode: 0644]

index b72f03844cc2bf17d79b11bcf4d6ec664f68f9bf..1d55737dac47788f12cf51a6501bb7521cfb807d 100644 (file)
                   android:label="@string/select_device"
                   android:theme="@android:style/Theme.Dialog"
                   android:configChanges="orientation|keyboardHidden" />
+
+
+        <!-- Service Samples -->
+
+        <service android:name=".TelemetryService" />
+
+        <activity android:name=".TelemetryServiceActivities$Controller"
+                android:label="@string/activity_telemetry_service_controller"
+                android:launchMode="singleTop">
+<!--
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+-->
+        </activity>
+
+        <activity android:name="TelemetryServiceActivities$Binding"
+                android:label="@string/activity_telemetry_service_binding">
+<!--
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+-->
+        </activity>
+
     </application>
 </manifest>
index 557a572208fc4e8d961fd6a4a74d57a4a8c688ad..0732087b437cc32bbf281605658b963d8f030bd5 100644 (file)
@@ -18,6 +18,8 @@ SRC_DIR=src/org/altusmetrum/AltosDroid
 
 SRC=\
        $(SRC_DIR)/AltosDroid.java \
+       $(SRC_DIR)/TelemetryService.java \
+       $(SRC_DIR)/TelemetryServiceActivities.java \
        $(SRC_DIR)/BluetoothChatService.java \
        $(SRC_DIR)/DeviceListActivity.java
 
diff --git a/altosdroid/res/drawable-hdpi/am_status.png b/altosdroid/res/drawable-hdpi/am_status.png
new file mode 100644 (file)
index 0000000..03f9dd7
Binary files /dev/null and b/altosdroid/res/drawable-hdpi/am_status.png differ
diff --git a/altosdroid/res/drawable-mdpi/am_status.png b/altosdroid/res/drawable-mdpi/am_status.png
new file mode 100644 (file)
index 0000000..07f7f07
Binary files /dev/null and b/altosdroid/res/drawable-mdpi/am_status.png differ
diff --git a/altosdroid/res/layout/telemetry_service_binding.xml b/altosdroid/res/layout/telemetry_service_binding.xml
new file mode 100644 (file)
index 0000000..950d0d3
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+     See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+    android:gravity="center_horizontal"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:paddingBottom="4dip"
+        android:text="@string/telemetry_service_binding"/>
+
+    <Button android:id="@+id/bind"
+        android:layout_width="wrap_content" android:layout_height="wrap_content" 
+        android:text="@string/bind_service">
+        <requestFocus />
+    </Button>
+
+    <Button android:id="@+id/unbind"
+        android:layout_width="wrap_content" android:layout_height="wrap_content" 
+        android:text="@string/unbind_service">
+    </Button>
+
+</LinearLayout>
+
diff --git a/altosdroid/res/layout/telemetry_service_controller.xml b/altosdroid/res/layout/telemetry_service_controller.xml
new file mode 100644 (file)
index 0000000..189d2f6
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+     See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+    android:gravity="center_horizontal"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:paddingBottom="4dip"
+        android:text="@string/telemetry_service_controller"/>
+
+    <Button android:id="@+id/start"
+        android:layout_width="wrap_content" android:layout_height="wrap_content" 
+        android:text="@string/start_service">
+        <requestFocus />
+    </Button>
+
+    <Button android:id="@+id/stop"
+        android:layout_width="wrap_content" android:layout_height="wrap_content" 
+        android:text="@string/stop_service">
+    </Button>
+
+</LinearLayout>
+
index 18de725c94e8dc4acc90715e8b12735599021d28..27625e9c3bda21bb8309d59ac7b585ceb9f784fc 100644 (file)
      limitations under the License.
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/telemetry_service_control"
+          android:icon="@android:drawable/ic_menu_manage"
+          android:title="@string/telemetry_service_control" />
+    <item android:id="@+id/telemetry_service_bind"
+          android:icon="@android:drawable/ic_menu_rotate"
+          android:title="@string/telemetry_service_bind" />
     <item android:id="@+id/secure_connect_scan"
           android:icon="@android:drawable/ic_menu_search"
           android:title="@string/secure_connect" />
index 60823b12c27196d12645dcd7e9b239499804eda1..0b2f922749b26e33181d9bc78b5488e5475eab4a 100644 (file)
     <string name="secure_connect">Connect a device - Secure</string>
     <string name="insecure_connect">Connect a device - Insecure</string>
     <string name="discoverable">Make discoverable</string>
+
+    <!-- Service -->
+    <string name="telemetry_service_label">AltOS Telemetry Service</string>
+    <string name="telemetry_service_started">Telemetry Service Started</string>
+    <string name="telemetry_service_stopped">Telemetry Service Stopped</string>
+
+
+
+    <string name="telemetry_service_control">Start/Stop Service</string>
+    <string name="telemetry_service_bind">Bind/Unbind Service</string>
+
+    <string name="activity_telemetry_service_controller">App/Service/Local Service Controller</string>
+    <string name="telemetry_service_controller">This demonstrates how you can implement persistent services that
+        may be started and stopped as desired.</string>
+    <string name="start_service">Start Service</string>
+    <string name="stop_service">Stop Service</string>
+
+    <string name="activity_telemetry_service_binding">App/Service/Local Service Binding</string>
+    <string name="telemetry_service_binding">This demonstrates how you can connect with a persistent
+        service.  Notice how it automatically starts for you, and play around with the
+        interaction between this and Local Service Controller.</string>
+    <string name="bind_service">Bind Service</string>
+    <string name="unbind_service">Unbind Service</string>
+    <string name="telemetry_service_connected">Connected to local service</string>
+    <string name="telemetry_service_disconnected">Disconnected from local service</string>
+
 </resources>
index 87f89cf9b76317e610309644e80ec6bebc762b4d..b4a3227cde7664d4e4b8d1a99f1c9edf84ec8352 100644 (file)
@@ -339,6 +339,14 @@ public class AltosDroid extends Activity {
     public boolean onOptionsItemSelected(MenuItem item) {
         Intent serverIntent = null;
         switch (item.getItemId()) {
+        case R.id.telemetry_service_control:
+            serverIntent = new Intent(this, TelemetryServiceActivities.Controller.class);
+            startActivity(serverIntent);
+            return true;
+        case R.id.telemetry_service_bind:
+            serverIntent = new Intent(this, TelemetryServiceActivities.Binding.class);
+            startActivity(serverIntent);
+            return true;
         case R.id.secure_connect_scan:
             // Launch the DeviceListActivity to see devices and do scan
             serverIntent = new Intent(this, DeviceListActivity.class);
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
new file mode 100644 (file)
index 0000000..40dff35
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.Toast;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import org.altusmetrum.AltosDroid.R;
+
+
+
+public class TelemetryService extends Service {
+    private NotificationManager mNM;
+
+    // Unique Identification Number for the Notification.
+    // We use it on Notification start, and to cancel it.
+    private int NOTIFICATION = R.string.telemetry_service_started;
+
+    /**
+     * Class for clients to access.  Because we know this service always
+     * runs in the same process as its clients, we don't need to deal with
+     * IPC.
+     */
+    public class TelemetryBinder extends Binder {
+        TelemetryService getService() {
+            return TelemetryService.this;
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+        // Display a notification about us starting.  We put an icon in the status bar.
+        showNotification();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.i("TelemetryService", "Received start id " + startId + ": " + intent);
+        // We want this service to continue running until it is explicitly
+        // stopped, so return sticky.
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        // Cancel the persistent notification.
+        mNM.cancel(NOTIFICATION);
+
+        // Tell the user we stopped.
+        Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    // This is the object that receives interactions from clients.  See
+    // RemoteService for a more complete example.
+    private final IBinder mBinder = new TelemetryBinder();
+
+    /**
+     * 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.telemetry_service_started);
+
+        // Set the icon, scrolling text and timestamp
+        Notification notification = new Notification(R.drawable.am_status, text,
+                System.currentTimeMillis());
+
+        // The PendingIntent to launch our activity if the user selects this notification
+        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+                new Intent(this, TelemetryServiceActivities.Controller.class), 0);
+
+        // Set the info for the views that show in the notification panel.
+        notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label),
+                       text, contentIntent);
+
+        // Send the notification.
+        mNM.notify(NOTIFICATION, notification);
+    }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java
new file mode 100644 (file)
index 0000000..5191cfa
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+public class TelemetryServiceActivities {
+    /**
+     * <p>Example of explicitly starting and stopping the local service.
+     * This demonstrates the implementation of a service that runs in the same
+     * process as the rest of the application, which is explicitly started and stopped
+     * as desired.</p>
+     * 
+     * <p>Note that this is implemented as an inner class only keep the sample
+     * all together; typically this code would appear in some separate class.
+     */
+    public static class Controller extends Activity {
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            setContentView(R.layout.telemetry_service_controller);
+
+            // Watch for button clicks.
+            Button button = (Button)findViewById(R.id.start);
+            button.setOnClickListener(mStartListener);
+            button = (Button)findViewById(R.id.stop);
+            button.setOnClickListener(mStopListener);
+        }
+
+        private OnClickListener mStartListener = new OnClickListener() {
+            public void onClick(View v) {
+                // Make sure the service is started.  It will continue running
+                // until someone calls stopService().  The Intent we use to find
+                // the service explicitly specifies our service component, because
+                // we want it running in our own process and don't want other
+                // applications to replace it.
+                startService(new Intent(Controller.this,
+                        TelemetryService.class));
+            }
+        };
+
+        private OnClickListener mStopListener = new OnClickListener() {
+            public void onClick(View v) {
+                // Cancel a previous call to startService().  Note that the
+                // service will not actually stop at this point if there are
+                // still bound clients.
+                stopService(new Intent(Controller.this,
+                        TelemetryService.class));
+            }
+        };
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Example of binding and unbinding to the local service.
+     * This demonstrates the implementation of a service which the client will
+     * bind to, receiving an object through which it can communicate with the service.</p>
+     * 
+     * <p>Note that this is implemented as an inner class only keep the sample
+     * all together; typically this code would appear in some separate class.
+     */
+    public static class Binding extends Activity {
+        private boolean mIsBound;
+
+
+        private TelemetryService mBoundService;
+        
+        private ServiceConnection mConnection = new ServiceConnection() {
+            public void onServiceConnected(ComponentName className, IBinder service) {
+                // This is called when the connection with the service has been
+                // established, giving us the service object we can use to
+                // interact with the service.  Because we have bound to a explicit
+                // service that we know is running in our own process, we can
+                // cast its IBinder to a concrete class and directly access it.
+                mBoundService = ((TelemetryService.TelemetryBinder)service).getService();
+                
+                // Tell the user about this for our demo.
+                Toast.makeText(Binding.this, R.string.telemetry_service_connected,
+                        Toast.LENGTH_SHORT).show();
+            }
+
+            public void onServiceDisconnected(ComponentName className) {
+                // This is called when the connection with the service has been
+                // unexpectedly disconnected -- that is, its process crashed.
+                // Because it is running in our same process, we should never
+                // see this happen.
+                mBoundService = null;
+                Toast.makeText(Binding.this, R.string.telemetry_service_disconnected,
+                        Toast.LENGTH_SHORT).show();
+            }
+        };
+        
+        void doBindService() {
+            // Establish a connection with the service.  We use an explicit
+            // class name because we want a specific service implementation that
+            // we know will be running in our own process (and thus won't be
+            // supporting component replacement by other applications).
+            bindService(new Intent(Binding.this, 
+                    TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE);
+            mIsBound = true;
+        }
+        
+        void doUnbindService() {
+            if (mIsBound) {
+                // Detach our existing connection.
+                unbindService(mConnection);
+                mIsBound = false;
+            }
+        }
+        
+        @Override
+        protected void onDestroy() {
+            super.onDestroy();
+            doUnbindService();
+        }
+
+
+        private OnClickListener mBindListener = new OnClickListener() {
+            public void onClick(View v) {
+                doBindService();
+            }
+        };
+
+        private OnClickListener mUnbindListener = new OnClickListener() {
+            public void onClick(View v) {
+                doUnbindService();
+            }
+        };
+        
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            setContentView(R.layout.telemetry_service_binding);
+
+            // Watch for button clicks.
+            Button button = (Button)findViewById(R.id.bind);
+            button.setOnClickListener(mBindListener);
+            button = (Button)findViewById(R.id.unbind);
+            button.setOnClickListener(mUnbindListener);
+        }
+    }
+}