Working with the Android Services Nilanjan Banerjee University
Working with the Android Services Nilanjan Banerjee University of Arkansas Fayetteville, AR nilanjan. banerjee@gmail. com Mobile Systems Programming 1
What is and is not an Android service? A service is not a separate process A service is not a separate thread! A facility for an application to tell the system about something it wants to do be doing in the background (Context. start. Service()) A facility for an application to expose some functionality that other applications can use (Context. bind. Service())
Uses of Android Services Expose services that applications can use get. System. Service() and use of Managers (location. Manager()) Bind to your own services Create your own activity Interact with services from activity
Primer: Broadcast Receiver • Registered as a receiver in an Android application via Android. Manifest. xml • Service sends out Intent using send. Broadcast() method while the Broadcast. Receiver defines a method called on. Receive() to receive the Inten • Example: Application which listens for changes in the phone state <manifest> <application> <receiver android: name=“My. Phone. Receiver”> <intent-filter> <action android: name=“android. intent. action. PHONE_STATE> </action> </intent-filter> </receiver> <uses-permission android: name=“android. permission. READ_PHONE_STATE”></uses-permission> </application> </manifest>
Broadcast Receiver: Phone state example import android. content. Broadcast. Receiver; import android. content. Context; import android. content. Intent; I mport android. os. Bundle; import android. telephony. Telephony. Manager; import android. util. Log; public class My. Phone. Receiver extends Broadcast. Receiver { @Overridepublic void on. Receive(Context context, Intent intent) { Bundle extras = intent. get. Extras(); if (extras != null) { String state = extras. get. String(Telephony. Manager. EXTRA_STATE); Log. w("DEBUG", state); if (state. equals(Telephony. Manager. EXTRA_STATE_RINGING)) { String phone. Number = extras. get. String(Telephony. Manager. EXTRA_INCOMING_NUMBER); Log. w("DEBUG", phone. Number); } }
Primer: Pending Intent – Token that an application gives another application which allows the other application to use permissions of your application to execute code • Other application could be Notification Manager, Alarm manager etc. – Example of a pending Intent and Broadcast. Receiver. Main. xml <? xml version="1. 0" encoding="utf-8"? > <Linear. Layout xmlns: android="http: //schemas. android. com/apk/res/android"android: orientation="vertical" android: layout_width="fill_parent"android: layout_height="fill_parent"> <Edit. Text android: layout_height="wrap_content" android: id="@+id/time"android: layout_width="wrap_content" android: hint="Number of seconds"android: input. Type="number. Decimal">> </Edit. Text> <Button android: text="Start Counter" android: id="@+id/ok"android: on. Click="start. Alert" android: layout_width="wrap_content"android: layout_height="wrap_content"> </Button> </Linear. Layout>
System Services and Broadcast Receiver import android. content. Broadcast. Receiver; import android. content. Context; I mport android. content. Intent; import android. os. Vibrator; import android. widget. Toast; public class My. Broadcast. Receiver extends Broadcast. Receiver { @Override public void on. Receive(Context context, Intent intent) { Toast. make. Text(context, "Don't panik but your time is up!!!!. ", Toast. LENGTH_LONG). show(); // Vibrate the mobile phone Vibrator vibrator = (Vibrator) context. get. System. Service(Context. VIBRATOR_SERVICE); vibrator. vibrate(2000); } } <? xml version="1. 0" encoding="utf-8"? > <manifest xmlns: android="http: //schemas. android. com/apk/res/android"package=“com. android. alarm" android: version. Code="1"android: version. Name="1. 0"> <uses-sdk android: min. Sdk. Version="9" /> <application android: icon="@drawable/icon" android: label="@string/app_name"> <activity android: name=". Alarm. Activity" android: label="@string/app_name"> <intent-filter> <action android: name="android. intent. action. MAIN" /> <category android: name="android. intent. category. LAUNCHER" /> </intent-filter> </activity> <receiver android: name="My. Broadcast. Receiver"></receiver></application> <uses-permission android: name="android. permission. VIBRATE"></uses-permission> </manifest>
System Services and Broadcast Receiver import android. app. Activity; import android. app. Alarm. Manager; import android. app. Pending. Intent; import android. content. Intent; import android. os. Bundle; import android. view. View; import android. widget. Edit. Text; import android. widget. Toast; public class Alarm. Activity extends Activity {/** Called when the activity is first created. */ @Override public void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. main); } public void start. Alert(View view) { Edit. Text text = (Edit. Text) find. View. By. Id(R. id. time); int i = Integer. parse. Int(text. get. Text(). to. String()); Intent intent = new Intent(this, My. Broadcast. Receiver. class); Pending. Intent pending. Intent = Pending. Intent. get. Broadcast(this. get. Application. Context(), 234324243, intent, 0); Alarm. Manager alarm. Manager = (Alarm. Manager) get. System. Service(ALARM_SERVICE); alarm. Manager. set(Alarm. Manager. RTC_WAKEUP, System. current. Time. Millis()+ (i * 1000), pending. Intent); Toast. make. Text(this, "Alarm set in " + i + " seconds", Toast. LENGTH_LONG). show(); } }
Defining and consuming your own service – An activity can start a service • start. Service() --- starts the service from an activity • stop. Service() --- stops the service from the activity – An actvity interacts with a service using bind. Service() • Requires a Service. Connection which allows to connect to a service and which returns a Ibinder object • Lifecycle flow: on. Create() ---- on. Start. Command() • Return value of on. Start. Command() START_STICKY – explicitly stopped or started, START_NOT_STICKY --- end automatically after the on. Start. Commend() <application android: icon="@drawable/icon" android: label="@string/app_name"> <activity android: name=". Service. Consumer" android: label="@string/app_name"> <intent-filter> <action android: name="android. intent. action. MAIN" /> <category android: name="android. intent. category. LAUNCHER" /> </intent-filter> </activity> <service android: name="Word. Service"></service> </application>
Defining and consuming your own service public class Word. Service extends Service { private Timer timer = new Timer(); private static final long UPDATE_INTERVAL = 5000; private final IBinder m. Binder = new My. Binder(); private Array. List<String> list = new Array. List<String>(); private String[] fixed. List = { "Linux", "Android", "i. Phone", "vogella. de", "helpful", "stuff" }; private int index = 0; public void on. Create() {super. on. Create(); poll. For. Updates(); } private void poll. For. Updates() { timer. schedule. At. Fixed. Rate(new Timer. Task() { @Override public void run() { if (list. size() >= 6) {list. remove(0); } list. add(fixed. List[index++]); if (index >= fixed. List. length) {index = 0; }}}, 0, UPDATE_INTERVAL); Log. i(get. Class(). get. Simple. Name(), "Timer started. "); } @Overridepublic void on. Destroy() {super. on. Destroy()}
Defining and consuming your own service public class Word. Service extends Service { if (timer != null) { timer. cancel(); } Log. i(get. Class(). get. Simple. Name(), "Timer stopped. "); } // We return the binder class upon a call of bind. Service @Override public IBinder on. Bind(Intent arg 0) { return m. Binder; } public class My. Binder extends Binder { Word. Service get. Service() { return Word. Service. this; } } public List<String> get. Word. List() { return list; } }
Defining and consuming your own service <? xml version="1. 0" encoding="utf-8"? > <Linear. Layout xmlns: android="http: //schemas. android. com/apk/res/android"android: orientation="vertical" android: layout_width="fill_parent"android: layout_height="fill_parent"> <Button android: text="Reload Data" android: id="@+id/button 1"android: layout_width="wrap_content" android: layout_height="wrap_content"android: on. Click="show. Service. Data"> </Button> <List. View android: id="@+id/list" android: layout_width="match_parent" android: layout_height="match_parent"> </List. View> </Linear. Layout> public class Service. Consumer extends Activity { private Word. Service s; private Array. List<String> values; /** Called when the activity is first created. */ @Overridepublic void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. main); do. Bind. Service(); values = new Array. List<String>(); adapter = new Array. Adapter<String>(this, android. R. layout. simple_list_item_1, values); List. View list = (List. View) find. View. By. Id(R. id. list); list. set. Adapter(adapter); }
Defining and consuming your own service private Service. Connection m. Connection = new Service. Connection() { public void on. Service. Connected(Component. Name class. Name, IBinder binder) { s = ((Word. Service. My. Binder) binder). get. Service(); Toast. make. Text(Service. Consumer. this, "Connected", Toast. LENGTH_SHORT). show(); } public void on. Service. Disconnected(Component. Name class. Name) { s = null; } }; private Array. Adapter<String> adapter; void do. Bind. Service() { bind. Service(new Intent(this, Word. Service. class), m. Connection, Context. BIND_AUTO_CREATE); } public void show. Service. Data(View view) { if (s != null) {List<String> word. List = s. get. Word. List(); values. clear(); values. add. All(word. List); adapter. notify. Data. Set. Changed(); } } }
- Slides: 13