From 392c878000e9909d37dae6342df3d6cb8f217a1b Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 23 Feb 2012 16:41:26 +1300 Subject: [PATCH] Add TelemetryService.java and associated files Signed-off-by: Mike Beattie --- altosdroid/AndroidManifest.xml | 27 +++ altosdroid/Makefile.am | 2 + altosdroid/res/drawable-hdpi/am_status.png | Bin 0 -> 804 bytes altosdroid/res/drawable-mdpi/am_status.png | Bin 0 -> 595 bytes .../res/layout/telemetry_service_binding.xml | 42 +++++ .../layout/telemetry_service_controller.xml | 42 +++++ altosdroid/res/menu/option_menu.xml | 6 + altosdroid/res/values/strings.xml | 26 +++ .../altusmetrum/AltosDroid/AltosDroid.java | 8 + .../AltosDroid/TelemetryService.java | 109 +++++++++++ .../TelemetryServiceActivities.java | 171 ++++++++++++++++++ 11 files changed, 433 insertions(+) create mode 100644 altosdroid/res/drawable-hdpi/am_status.png create mode 100644 altosdroid/res/drawable-mdpi/am_status.png create mode 100644 altosdroid/res/layout/telemetry_service_binding.xml create mode 100644 altosdroid/res/layout/telemetry_service_controller.xml create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java 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" /> + + + + + + + + + + + + + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..03f9dd7d612281c3809678774cfc2195d679b14e GIT binary patch literal 804 zcmV+<1Ka$GP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01gxY01gxZ1})bs00007bV*G`2iyV| z10)k^HdK=U00N{*L_t(Y$L*FqOp{R*hM#j=AgBR}12HHn(ddAiG3w&rh{S+#alxdC zQA21AwNQQpTH3Fr1=_?xQ6{5TiO0Ei^XD|vG|y0BWKJ88Epvde+6L0ta{)C%CUHOV%N3;tXK>K zdw_a`CR1fMU1oaw0Kwi~9HkWi1;?S`F`n%KSeCWgW3?rY=!^*W0X#e@3XoE=h(@iG zMtF_TEH3x5fe#BGckUQ^aN}pOv+j~~it|I&d=CbL?*S5t#C$2iOR~P!X`&HpcKv!H zk(@0lw_*;FNTdmocP`|Ox;a-_RiXBxzBD4o6=}ZZ@6K$kM9O{592ZSx|xcX8|YK>yhYKDtG6`@cFpjK7SE2@G>HkycSjH_UbGKJMcQ4HGZDcUlLP4&{pCL8 i3v_16AHA~uBla8B)!~89&=ax%0000X1^@s6IQ*`u00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01gxY01gxZ1})bs00007bV*G`2iyV| z10*X!H0%uk00GlUL_t(I%k7juYg1tu#ee5X+JZW%VCx64BBBrq#bTR+I=K}@ocyym z_$RTV&@@GonB?X*y-5Vo!A%gvS!Z4R0Db~-QK5r$s9@uL9Bu<@+FHf254>=Ac=>V8 z;pK&$*>Zv)m<}7^^j3Flqh-Aw^yF3G0zlYU{09e(;A0qupZ?lG;-Y>AXBk)tgJx#i zfZF}~y7C#1y$BQ$GXPGPMX=r9Pk>*N zQd99-H!I`vQgdnIj}a;hiG6oY;`$0aa?!#8F$vIIjD7)VBWkr;eJgCAna0gbQtEvw zrFXNpXD2sxaAVJt#6_ht28`e$?rPPrRpE{}*osFiNpG-=0^gRht62#&O)_Tjz= z<#IW>Bpm{d;ec!4r;dC2xSNjxbUMkSQt9C=_pU{hN~Hsc=O)XV877_zuA~PBh4jkI zPD{ef-r$_i<#V4OJgX+ya + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + 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. --> + + 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 @@ Connect a device - Secure Connect a device - Insecure Make discoverable + + + AltOS Telemetry Service + Telemetry Service Started + Telemetry Service Stopped + + + + Start/Stop Service + Bind/Unbind Service + + App/Service/Local Service Controller + This demonstrates how you can implement persistent services that + may be started and stopped as desired. + Start Service + Stop Service + + App/Service/Local 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. + Bind Service + Unbind Service + Connected to local service + Disconnected from local service + 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 { + /** + *

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.

+ * + *

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.

+ * + *

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); + } + } +} -- 2.30.2