diff options
-rw-r--r-- | altosdroid/AndroidManifest.xml | 27 | ||||
-rw-r--r-- | altosdroid/Makefile.am | 2 | ||||
-rw-r--r-- | altosdroid/res/drawable-hdpi/am_status.png | bin | 0 -> 804 bytes | |||
-rw-r--r-- | altosdroid/res/drawable-mdpi/am_status.png | bin | 0 -> 595 bytes | |||
-rw-r--r-- | altosdroid/res/layout/telemetry_service_binding.xml | 42 | ||||
-rw-r--r-- | altosdroid/res/layout/telemetry_service_controller.xml | 42 | ||||
-rw-r--r-- | altosdroid/res/menu/option_menu.xml | 6 | ||||
-rw-r--r-- | altosdroid/res/values/strings.xml | 26 | ||||
-rw-r--r-- | altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 8 | ||||
-rw-r--r-- | altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 109 | ||||
-rw-r--r-- | altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java | 171 |
11 files changed, 433 insertions, 0 deletions
diff --git a/altosdroid/AndroidManifest.xml b/altosdroid/AndroidManifest.xml index b72f0384..1d55737d 100644 --- a/altosdroid/AndroidManifest.xml +++ b/altosdroid/AndroidManifest.xml @@ -34,5 +34,32 @@ 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> diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am index 557a5722..0732087b 100644 --- a/altosdroid/Makefile.am +++ b/altosdroid/Makefile.am @@ -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 Binary files differnew file mode 100644 index 00000000..03f9dd7d --- /dev/null +++ b/altosdroid/res/drawable-hdpi/am_status.png diff --git a/altosdroid/res/drawable-mdpi/am_status.png b/altosdroid/res/drawable-mdpi/am_status.png Binary files differnew file mode 100644 index 00000000..07f7f073 --- /dev/null +++ b/altosdroid/res/drawable-mdpi/am_status.png diff --git a/altosdroid/res/layout/telemetry_service_binding.xml b/altosdroid/res/layout/telemetry_service_binding.xml new file mode 100644 index 00000000..950d0d3a --- /dev/null +++ b/altosdroid/res/layout/telemetry_service_binding.xml @@ -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 index 00000000..189d2f6c --- /dev/null +++ b/altosdroid/res/layout/telemetry_service_controller.xml @@ -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> + diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index 18de725c..27625e9c 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -14,6 +14,12 @@ 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" /> diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 60823b12..0b2f9227 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -38,4 +38,30 @@ <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> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 87f89cf9..b4a3227c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -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 index 00000000..40dff354 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -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 index 00000000..5191cfa9 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java @@ -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); + } + } +} |