第142页
[√]START_REDELIVER_INTENT
如果系统在onStartCommand()方法返回后停止服务,重新创建服务并使用发送给服务的最后Intent调用onStartCommand()方法,全部PendingIntent依次发送。这适合积极执行应该立即恢复工作的服务,如下载文件。
说明: 这些常量都定义在Service类中。
13.2.3 启动服务
开发人员可以从Activity或者其他应用程序组件通过传递Intent对象(指定要启动的服务)到startService()方法启动服务。Android系统调用服务的onStartCommand()方法并将Intent传递给它。
注意: 请不要直接调用onStartCommand()方法。
例如,Activity能使用显式Intent和startService()方法启动前面章节的示例服务(HelloService),其代码如下:
Intent intent = new Intent(this, HelloService.class);
startService(intent);
startService()方法立即返回,然后Android系统调用服务的onStartCommand()方法。如果服务还没有运行,系统首先调用onCreate()方法,接着调用onStartCommand()方法。
如果服务没有提供绑定,startService()方法发送的Intent是应用程序组件和服务之间唯一的通信模式。然而,如果开发人员需要服务返回结果,则启动该服务的客户端能为广播创建PendingIntent(使用getBroadcast()方法)并通过启动服务的Intent进行发送。服务接下来便能使用广播来发送结果。
多次启动服务的请求导致Senice的onStartCommand()方法被调用多次,然而,仅需要一个停止方法(stopSelf()或stopService()方法)来停止服务。
13.2.4 停止服务
启动服务必须管理自己的生命周期,即系统不会停止或销毁服务,除非系统必须回收系统内存而且在onStartCommand()方法返回后服务继续运行。因此,服务必须调用stopSelf()方法停止自身,或者其他组件调用stopService()方法停止服务。
当使用stopSelf()或stopService()方法请求停止时,系统会尽快销毁服务。
然而,如果服务同时处理多个onStartCommand()方法调用请求,则处理完一个请求后,不应该停止服务,因为可能收到一个新的启动请求(在第一个请求结束后停止会终止第二个请求)。为了解决这个问题,开发人员可以使用stopSelf(int)方法来确保停止服务的请求总是基于最近收到的启动请求。即当调用stopSelf(int)方法时,同时将启动请求的ID(发送给onStartCommand()方法的startId)传递给停止请求。这样,如果服务在调用stopSelf(int)方法前接收到新启动请求,会因ID不匹配而不停止服务。
注意: 应用程序应该在任务完成后停止服务,来避免系统资源浪费和电池消耗。如果必要,其他组件能通过stopService()方法停止服务。即便能够绑定服务,如果调用了onStartCommand()方法就必须停止服务。
13.2.5 实例1:继承IntentService输出当前时间
例13.1 在Eclipse中创建Android项目,名称为13.1,实现继承IntentService在后台输出当前时间。(实例位置:光盘\TM\sl\13\13.1)
(1)修改res\layout目录中的main.xml布局文件,设置背景图片并添加一个按钮,然后设置按钮文字的内容、颜色和大小,其代码如下:
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical" >
android:id="@+id/current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/current_time"
android:textColor="@android:color/black"
android:textSize="25dp" />
(2)创建CurrentTimeService类,它继承了IntentService类,用于在后台输出当前时间,其代码如下:
public class CurrentTimeService extends IntentService {
public CurrentTimeService() {
super("CurrentTimeService"); //调用父类非空构造方法
}
@Override
protected void onHandleIntent(Intent intent) {
Time time = new Time(); //创建Time对象
time.setToNow(); //设置时间为当前时间
String currentTime = time.format("%Y-%m-%d %H:%M:%S"); //设置时间格式
Log.i("CurrentTimeService", currentTime); //记录当前时间
}
}
注意: 此处使用的时间格式与Java API中SimpleDateFormat类有所不同。
(3)创建CurrentTimeActivity类,它继承了Activity类。在onCreate()方法中获得按钮控件并为其增加单击事件监听器。在监听器中,使用Intent启动服务,其代码如下:
public class CurrentTimeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); //设置页面布局
Button currentTime = (Button) findViewById(R.id.current_time); //通过ID值获得按钮对象