Android Service and Broadcast Receiver Tutorial

This tutorial describes how to create and consume Androidservices. It is based on Eclipse 3.6, Java 1.6 and Android 2.3(Gingerbread).

Table of Contents

1. Android Services
1.1. Service 1.2. Own Services 1.3. Broadcast Receiver 1.4. Pending Intent
2. Broadcast Receiver Example 3. System Services and Broadcast Receiver 4. Define and consume your own service 5. Thank you 6. Questions and Discussion 7. Links and Literature
7.1. Source Code 7.2. Android Resources 7.3. vogella Resources

1. Android Services

1.1. Service

A service is a component which runs in the background, withoutinteracting with the user.

The Android platform provides a lot of pre-defined services,usually exposed via a Manager class. In your activity you accessservices via the method getSystemService().

Own Services must be declared via the"AndroidManifest.xml". They runthe main thread of their hosting process.Therefore you should run performance intensive tasks in the background.

1.2. Own Services

You can declare your own service to perform long runningoperations without userinteraction or to supply functionality toother applications. Aactivity can start a service via thestartService() method and stopthe service via the stopService()method. If the activity want tointeract with the service it can usethe bindService() method of theservice. This requires an"ServiceConnection" object which allows toconnectto the service andwhich return a IBinder object. This IBinderobjectcan be usedby theactivityto communicate with the service.

Once a service is started its onCreate() method is called. Afterwardsthe onStartCommand() is called with the Intent data provided by theactivity. startService also allows to provide a flag with determinesthe lifecycle behavior of the services. START_STICKY is used forservices which are explicit started or stopped. Services started withSTART_NOT_STICKY will end automatically after the onStartCommand()method is done.Aservice is started withinthe main threadof theapplication thereforeall long running tasksshould be performedin the background.

A Services needs to be declared in the "AndroidManifest.xml" via a <service android:name="yourclasss"> </service> and the implementing class must extend the class "Service" or one ofits subclasses.

One common case is that the service and the activity are verycloselyrelated. In this case class just case the IBinder to the classtheservice provides. See Local Service Example for an example.

Another example would be the usage ofRemote Messenger Service. In this case activities can send messagestothe service and receive messages as well if they register for them.

1.3. Broadcast Receiver

A broadcast receiver is a class which extends"BroadcastReceiver" and which is registered as a receiver in anAndroid Application via the AndroidManifest.xml (or via code). Thisclass will be able to receive intents via the sendBroadcast() method."BroadCastReceiver" defines the method "onReceive()". Only duringthis method your broadcast receiver object will be valid, afterwardsthe Android system will consider your object as no longer active.Therefore you cannot perform any asynchronous operation.

1.4. Pending Intent

This tutorial will also use a PendingIntent. A PendingIntent isa token that you give to anotherapplication (e.g. NotificationManager, Alarm Manager or other 3rdparty applications), which allowsthisother application to use thepermissions of your application toexecuteapredefined piece of code.

To perform a broadcastvia apending intent so get a PendingIntentviaPendingIntent.getBroadcast(). To perform an activity via anpending intent you receive the activity viaPendingIntent.getActivity().

2. Broadcast Receiver Example

We will define a broadcast receiver which listens to telephonestatechanges. If the phone receives a phone call then our receiver will benotified and log a message.

Create a new project "de.vogella.android.receiver.phone". We donot need an activity. Create the following "AndroidManifest.xml".

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="de.vogella.android.receiver.phone" android:versionCode="1"
	android:versionName="1.0">
	<application android:icon="@drawable/icon" android:label="@string/app_name">


		<receiver android:name="MyPhoneReceiver">
			<intent-filter>
				<action android:name="android.intent.action.PHONE_STATE"></action>
			</intent-filter>
		</receiver>
	</application>
	<uses-sdk android:minSdkVersion="9" />


	<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
</manifest> 	


Create the following class "MyPhoneReceiver".

package de.vogella.android.receiver.phone;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;

public class MyPhoneReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Bundle extras = intent.getExtras();
		if (extras != null) {
			String state = extras.getString(TelephonyManager.EXTRA_STATE);
			Log.w("DEBUG", state);
			if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
				String phoneNumber = extras
						.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
				Log.w("DEBUG", phoneNumber);
			}
		}
	}
}

If you install your application and receive a call, e.gsimulated by the DDMS perspective in Eclipse, then your receiver willbe called and lot a message to the console.

3. System Services and Broadcast Receiver

In this chapter we will use theAlertManager andVibratorManager. The VibratorManager will be called by the broadcastreceiver which will be called by the AlertManager.

Create a new project "de.vogella.android.alarm" with theactivity "AlarmActivity". Create the following layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<EditText android:layout_height="wrap_content" android:id="@+id/time"
		android:layout_width="wrap_content" android:hint="Number of seconds"
		android:inputType="numberDecimal">></EditText>
	<Button android:text="Start Counter" android:id="@+id/ok"
		android:onClick="startAlert" android:layout_width="wrap_content"
		android:layout_height="wrap_content"></Button>
</LinearLayout>

Create the following broadcast receiver class. This class willget the Vibrator service.

package de.vogella.android.alarm;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;
import android.widget.Toast;

public class MyBroadcastReceiver extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "Don't panik but your time is up!!!!.",
				Toast.LENGTH_LONG).show();
		// Vibrate the mobile phone
		Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
		vibrator.vibrate(2000);
	}

}

Maintain this class as broadcast receiver in"AndroidManifest.xml" and allow the vibrate authorization.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="de.vogella.android.alarm" android:versionCode="1"
	android:versionName="1.0">
	<uses-sdk android:minSdkVersion="9" />

	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name=".AlarmActivity" 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="MyBroadcastReceiver"></receiver>

	</application>
	<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
	
</manifest>

Change the code of your Activity "AlarmActivity" to thefollowing. This activity will create anIntent for the Broadcastreceiver and get the AlarmManager service.
package de.vogella.android.alarm;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class AlarmActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	public void startAlert(View view) {
		EditText text = (EditText) findViewById(R.id.time);
		int i = Integer.parseInt(text.getText().toString());
		Intent intent = new Intent(this, MyBroadcastReceiver.class);
		PendingIntent pendingIntent = PendingIntent.getBroadcast(
				this.getApplicationContext(), 234324243, intent, 0);
		AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
		alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
				+ (i * 1000), pendingIntent);
		Toast.makeText(this, "Alarm set in " + i + " seconds",
				Toast.LENGTH_LONG).show();
	}

}
Run your application on the device. Set your time and start thealarm. After the defined number of seconds a Toast should bedisplayed. The vibrator alarm does not work on the simulator.


4. Define and consume your own service

The following will demonstrate how to create and consume aservice from an activity. The service will periodically fetch data.The service will used by an activity which bind itself to the service.The activity will allow to request the latest data from the service.

Create a new project "de.vogella.android.ownservice" with theactivity "ServiceConsumer".

Create a service "WordService" by create the class and the entryin "AndroidManifest.xml".

package de.vogella.android.ownservice;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class WordService extends Service {
	private Timer timer = new Timer();
	private static final long UPDATE_INTERVAL = 5000;
	private final IBinder mBinder = new MyBinder();
	private ArrayList<String> list = new ArrayList<String>();
	private String[] fixedList = { "Linux", "Android", "iPhone", "vogella.de",
			"helpful", "stuff" };
	private int index = 0;

	public void onCreate() {
		super.onCreate();
		pollForUpdates();
	}

	private void pollForUpdates() {
		timer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				// Imagine here a freaking cool web access ;-)
				if (list.size() >= 6) {
					list.remove(0);
				}
				list.add(fixedList[index++]);
				if (index >= fixedList.length) {
					index = 0;
				}
			}
		}, 0, UPDATE_INTERVAL);
		Log.i(getClass().getSimpleName(), "Timer started.");

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (timer != null) {
			timer.cancel();
		}
		Log.i(getClass().getSimpleName(), "Timer stopped.");

	}

	// We return the binder class upon a call of bindService
	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}

	public class MyBinder extends Binder {
		WordService getService() {
			return WordService.this;
		}
	}

	public List<String> getWordList() {
		return list;
	}

}

package de.vogella.android.ownservice;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class WordService extends Service {
	private Timer timer = new Timer();
	private static final long UPDATE_INTERVAL = 5000;
	private final IBinder mBinder = new MyBinder();
	private ArrayList<String> list = new ArrayList<String>();
	private String[] fixedList = { "Linux", "Android", "iPhone", "vogella.de",
			"helpful", "stuff" };
	private int index = 0;

	public void onCreate() {
		super.onCreate();
		pollForUpdates();
	}

	private void pollForUpdates() {
		timer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				// Imagine here a freaking cool web access ;-)
				if (list.size() >= 6) {
					list.remove(0);
				}
				list.add(fixedList[index++]);
				if (index >= fixedList.length) {
					index = 0;
				}
			}
		}, 0, UPDATE_INTERVAL);
		Log.i(getClass().getSimpleName(), "Timer started.");

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (timer != null) {
			timer.cancel();
		}
		Log.i(getClass().getSimpleName(), "Timer stopped.");

	}

	// We return the binder class upon a call of bindService
	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}

	public class MyBinder extends Binder {
		WordService getService() {
			return WordService.this;
		}
	}

	public List<String> getWordList() {
		return list;
	}

}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="de.vogella.android.ownservice"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ServiceConsumer"
                  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="WordService"></service>

    </application>
</manifest>

Change the layout "main.xml" to the following.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/button1"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:onClick="showServiceData"></Button>
	<ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent"></ListView>
</LinearLayout>

Change the activity ServiceConsumer to the following. 

package de.vogella.android.ownservice;

import java.util.ArrayList;
import java.util.List;

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.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class ServiceConsumer extends Activity {
	private WordService s;
	private ArrayList<String> values;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		doBindService();
		values = new ArrayList<String>();
		adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, values);
		ListView list = (ListView) findViewById(R.id.list);
		list.setAdapter(adapter);

		// List<String> wordList = s.getWordList();
		// Toast.makeText(this, wordList.get(0), Toast.LENGTH_LONG).show();
	}

	private ServiceConnection mConnection = new ServiceConnection() {

		public void onServiceConnected(ComponentName className, IBinder binder) {
			s = ((WordService.MyBinder) binder).getService();
			Toast.makeText(ServiceConsumer.this, "Connected",
					Toast.LENGTH_SHORT).show();
		}

		public void onServiceDisconnected(ComponentName className) {
			s = null;
		}
	};
	private ArrayAdapter<String> adapter;

	void doBindService() {
		bindService(new Intent(this, WordService.class), mConnection,
				Context.BIND_AUTO_CREATE);
	}

	public void showServiceData(View view) {
		if (s != null) {
			List<String> wordList = s.getWordList();
			values.clear();
			values.addAll(wordList);
			adapter.notifyDataSetChanged();
		}
	}
}


5. Thank you


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值