Service是一个没有UI且长驻系统的程序,可以通过两种方式来启动:startService()和BindService()。startService方式启动则调用stopService()结束Service,或者在Service继承类中调用stopSelf(),通常是开启的服务只执行一个任务且不返回结果给caller,当任务完成后服务也应该终结自己;bindService()可以通过unbindService()方法来结束或者结束与其绑定的组件,绑定的Service可以与其他组件通信,send requests, get results,甚至进行进程间的通信(IPC)。
两种方式启动Service对Service的生命周期影响是不一样的。通过startService()启动会经历:onCreate -> onStart -> onDestroy(调用stopService()),Service有Activity启动但并不依赖于它,当Activity结束时,Service依然运行直至被stop()生命周期结束。而通过bindService()启动会经历:onCreate -> onBind -> onUnbind -> onDestory(调用onUnbind或绑定的组件终结)
另外需要注意的是Service是运行在主线程的,别忘了Manifest文件中注册Service。
实例一:生命周期演示
这里不贴代码了,讲一下程序框架,通过Logcat来分析一下Service生命周期还有startService()和BindService()的不同。
程序界面如上,不同的操作的结果如下。
1、先start后stop结果:
当start后,退出程序,这时后台的Service仍在运行不会停止!只有再次打开程序点击stop它才正在运行,说明了Service是不依赖于Activity和程序的。
2、先start再start结果:
说明Service只会被create一次,除非stop掉,否则Service一直存在,这也与上面的结果契合。
3、进入bindedActivity,先bind在unbind结果:(此时不会再create了)
4、进入bindedActivity,先bind后按back键结束bindedActivity的生命周期,结果:
3和4的结果是一样的,Service和bindedActivity是绑定的,当bindedActivity结束时,Service也结束。
实例二:Activity与Service通信
①新建一个类继承Service类,建立一个内部类继承Binder,里面有两个假设的方法。
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder(); // 实例化DownloadBinder
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
System.out.println("==>> onBind");
return mBinder; // 返回DownloadBinder对象
}
class DownloadBinder extends Binder {
public void startDownload() {
System.out.println("==>> startDownload");
}
public void stopDownload() {
System.out.println("==>> stopDownload");
}
}
}
②Activity
package com.example.servicedemo;
import com.example.servicedemo.MyService.DownloadBinder;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends ActionBarActivity {
private Button button1, button2;
private MyService.DownloadBinder binder; // 创建一个引用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, conn, BIND_AUTO_CREATE); // 绑定Service,
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
unbindService(conn); // 取消绑定
}
});
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
binder = (DownloadBinder) arg1; // 绑定Service后,将onBind()方法返回的对象赋给引用
binder.startDownload(); // 执行Service中的两个方法
binder.stopDownload();
}
};
}
实例三:前台服务
前台服务的作用是用户常常需要感知到它的存在,还有前台服务可以预防被系统回收。其实挺简单的,就是调用在继承服务类中startForeground就可以了,它以Notification形式显示在前台。
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("==>> onCreate");
Notification notification = new Notification(R.drawable.ic_launcher,
"ticker", System.currentTimeMillis());
Intent intent = new Intent(MyService.this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(MyService.this, 0, intent,
0);
notification.setLatestEventInfo(this, "Title", "Text", pi);
startForeground(1, notification); // 第一个参数不能为0
}
取消调用stopForeground (boolean removeNotification)即可,当然如果后台服务终结了,这个前台也会被stop掉。
最后,介绍一下IntentService,之前说过startService开启的服务有时只是执行一个任务,假设我们开启一个线程来完成这个任务,任务执行完后服务还在,需要手动stopSelf。而IntentService就是提供了一种机制,开启一个线程执行任务,完了后就结束服务。用法和普通Service一样,同样也需要在Manifest中注册。
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
// TODO Auto-generated constructor stub
}
@Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getId()); // 打印出来的并不是主线程,说明是新开的线程
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("==>> onDestroy");
}
}