public class RSSPullService extends IntentService {
@Override
protected void onHandleIntent(Intent workIntent) {
// Gets data from the incoming Intent
String dataString = workIntent.getDataString();
...
// Do work here, based on the contents of dataString
...
}
}
<service
android:name=".RSSPullService"
android:exported="false"/>
mServiceIntent = new Intent(getActivity(), RSSPullService.class);
mServiceIntent.setData(Uri.parse(dataUrl));
// Starts the IntentService
getActivity().startService(mServiceIntent);
为了在 IntentService 中向其他组件发送任务状态,首先创建一个 Intent 并在 data 字段中包含需要传递的信息。作为一个可选项,还可以给这个 Intent 添加一个 action 与 data URI。
下一步,通过执行 LocalBroadcastManager.sendBroadcast() 来发送 Intent。Intent 被发送到任何有注册接受它的组件中。为了获取到 LocalBroadcastManager 的实例,可以执行 getInstance()。代码示例如下:
public final class Constants {
...
// Defines a custom Intent action
public static final String BROADCAST_ACTION =
"com.example.android.threadsample.BROADCAST";
...
// Defines the key for the status "extra" in an Intent
public static final String EXTENDED_DATA_STATUS =
"com.example.android.threadsample.STATUS";
...
}
public class RSSPullService extends IntentService {
...
/*
* Creates a new Intent containing a Uri object
* BROADCAST_ACTION is a custom Intent action
*/
Intent localIntent =
new Intent(Constants.BROADCAST_ACTION)
// Puts the status into the Intent
.putExtra(Constants.EXTENDED_DATA_STATUS, status);
// Broadcasts the Intent to receivers in this app.
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
...
}
下一步是在发送任务的组件中接收发送出来的 broadcast 数据。
为了接受广播的数据对象,需要使用 BroadcastReceiver 的子类并实现BroadcastReceiver.onReceive() 的方法,这里可以接收 LocalBroadcastManager 发出的广播数据。
// Broadcast receiver for receiving status updates from the IntentService
private class ResponseReceiver extends BroadcastReceiver
{
// Prevents instantiation
private DownloadStateReceiver() {
}
// Called when the BroadcastReceiver gets an Intent it's registered to receive
@
public void onReceive(Context context, Intent intent) {
...
/*
* Handle Intents here.
*/
...
}
}
一旦定义了 BroadcastReceiver,也应该定义 actions,categories 与 data 用过滤广播。为了实现这些,需要使用 IntentFilter。如下所示:
// Class that displays photos
public class DisplayActivity extends FragmentActivity {
...
public void onCreate(Bundle stateBundle) {
...
super.onCreate(stateBundle);
...
// The filter's action is BROADCAST_ACTION
IntentFilter mStatusIntentFilter = new IntentFilter(
Constants.BROADCAST_ACTION);
// Adds a data filter for the HTTP scheme
mStatusIntentFilter.addDataScheme("http");
...
为了给系统注册这个 BroadcastReceiver 和 IntentFilter,需要通过 LocalBroadcastManager 执行 registerReceiver() 的方法。如下所示:
// Instantiates a new DownloadStateReceiver
DownloadStateReceiver mDownloadStateReceiver =
new DownloadStateReceiver();
// Registers the DownloadStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver,
mStatusIntentFilter);
...
一个 BroadcastReceiver 可以处理多种类型的广播数据。每个广播数据都有自己的 ACTION。这个功能使得不用定义多个不同的 BroadcastReceiver 来分别处理不同的 ACTION 数据。为 BroadcastReceiver 定义另外一个 IntentFilter,只需要创建一个新的 IntentFilter 并重复执行 registerReceiver() 即可。例如:
/*
* Instantiates a new action filter.
* No data filter is needed.
*/
statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
...
// Registers the receiver with the new filter
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mDownloadStateReceiver,
mIntentFilter);
发送一个广播 Intent 并不会启动或重启一个 Activity。即使是你的 app 在后台运行,Activity 的 BroadcastReceiver 也可以接收、处理 Intent 对象。但是这不会迫使你的 app 进入前台。当你的 app 不可见时,如果想通知用户一个发生在后台的事件,建议使用 Notification。永远不要为了响应一个广播 Intent 而去启动 Activity。