Service是一个应用程序组件,它能够在后台执行一些耗时较长的操作,并且不提供用户界面。服务能被其它应用程序的组件启动,即使用户切换到另外的应用时还能保持后台运行。此外,应用程序组件还能与服务绑定,并与服务进行交互,甚至能进行进程间通信(IPC)。 比如,服务可以处理网络传输、音乐播放、执行文件I/O、或者与content provider进行交互,所有这些都是后台进行的。
在Activity中,启动服务有两种方式,startService和bindService,首先让我们看看这两种方式下服务的生命周期图:
(1)当我们通过startService启动服务的时候,从生命周期图我们可以看到会调用Service的startCommand方法
我们启动服务是通过intent启动的,可以把参数放到intent里面
Intent service = new Intent(this,ProgressService.class);
service.putExtra("name","main");
startService(service);
然后
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String name = intent.getStringExtra("name");
return super.onStartCommand(intent, flags, startId);
}
(2)通过bindService方式启动服务,通过生命周期图我们可以看到会调用
Service的unBind方法,同理
@Override
public IBinder onBind(Intent intent) {
String name = intent.getStringExtra("name");
Toast.makeText(this,"name"+name,Toast.LENGTH_SHORT).show();
return new ProgressBinder();
}
(1)通过Binder对象
当我们通过bindService启动一个Service的时候,会传入一个ServiceConnection对象,当服务连接成功后,回传回来一个IBinder类型的对象,通过这个对象,Service就可以和Activity通信。
举一个例子:
public class MainActivity extends Activity {
private ProgressBar progressBar;
private ProgressService progressService;
private int progress = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
Intent service = new Intent(this,ProgressService.class);
//绑定服务
bindService(service, connection, Context.BIND_AUTO_CREATE);
}
public void bindService(View view){
//开始下载
progressService.startDownload();
//更新进度
changeProgress();
}
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//当服务连接成功后,获得返回的Binder对象
ProgressBinder binder = (ProgressBinder) service;
//通过binder获得服务对象,这样我们就可以调用服务里面的方法了
progressService = binder.getService();
}
};
/**
* 每隔1秒去检查进度
*/
public void changeProgress(){
new Thread(){
@Override
public void run() {
super.run();
while (progress<=ProgressService.MAX_PROGRESS){
//获取服务中更新后的进度
progress = progressService.getProgress();
progressBar.setProgress(progress);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
/**
* 更新进度的服务
*/
public class ProgressService extends Service{
public static final int MAX_PROGRESS = 100;
public int progress;
@Override
public IBinder onBind(Intent intent) {
return new ProgressBinder();
}
class ProgressBinder extends Binder{
//给外部提供一个方法,获得当前服务的对象
public ProgressService getService(){
return ProgressService.this;
}
}
public int getProgress(){
return progress;
}
/**
* 模拟下载操作
*/
public void startDownload(){
new Thread(){
@Override
public void run() {
super.run();
while (progress<=MAX_PROGRESS) {
progress+=10;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
效果图如下:
在上面的代码中,我们每次都要主动调用getProgress方法来获取最新的进度,有没有感觉有点被动呢,那么有没有主动一点的方法,这个时候可以利用回调。直接上代码
public class MainActivity extends Activity {
private ProgressBar progressBar;
private ProgressService progressService;
private int progress = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
Intent service = new Intent(this,ProgressService.class);
//绑定服务
bindService(service, connection, Context.BIND_AUTO_CREATE);
}
public void bindService(View view){
progressService.startDownload();
progressService.setOnProgressChangedListener(new ProgressService.OnProgressChangedListener() {
@Override
public void onProgressChanged(int progress) {
progressBar.setProgress(progress);
}
});
}
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//当服务连接成功后,获得返回的Binder对象
ProgressBinder binder = (ProgressBinder) service;
//通过binder获得服务对象,这样我们就可以调用服务里面的方法了
progressService = binder.getService();
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
public class ProgressService extends Service{
public static final int MAX_PROGRESS = 100;
public int progress;
OnProgressChangedListener listener;
interface OnProgressChangedListener{
void onProgressChanged(int progress);
}
public void setOnProgressChangedListener(OnProgressChangedListener listener){
this.listener = listener;
}
@Override
public IBinder onBind(Intent intent) {
return new ProgressBinder();
}
class ProgressBinder extends Binder{
//给外部提供一个方法,获得当前服务的对象
public ProgressService getService(){
return ProgressService.this;
}
}
/**
* 模拟下载操作
*/
public void startDownload(){
new Thread(){
@Override
public void run() {
super.run();
while (progress<=MAX_PROGRESS) {
progress+=10;
try {
listener.onProgressChanged(progress);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
(2)利用广播
public class MainActivity extends Activity {
private ProgressBar progressBar;
private ProgressService progressService;
private int progress = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
Intent service = new Intent(this,ProgressService.class);
//绑定服务
bindService(service, connection, Context.BIND_AUTO_CREATE);
//添加过滤器,用于过滤发送过来广播
IntentFilter filter = new IntentFilter("intent.action.update");
//注册广播
registerReceiver(new ProgressReceiver(),filter);
}
public void bindService(View view){
//开始下载
progressService.startDownload();
}
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//当服务连接成功后,获得返回的Binder对象
ProgressBinder binder = (ProgressBinder) service;
//通过binder获得服务对象,这样我们就可以调用服务里面的方法了
progressService = binder.getService();
}
};
class ProgressReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取发送过来的进度信息
int progress = intent.getIntExtra("progress", 0);
progressBar.setProgress(progress);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
public class ProgressService extends Service{
public static final int MAX_PROGRESS = 100;
public int progress;
@Override
public IBinder onBind(Intent intent) {
return new ProgressBinder();
}
class ProgressBinder extends Binder{
//给外部提供一个方法,获得当前服务的对象
public ProgressService getService(){
return ProgressService.this;
}
}
/**
* 模拟下载操作
*/
public void startDownload(){
new Thread(){
@Override
public void run() {
super.run();
while (progress<=MAX_PROGRESS) {
progress+=10;
try {
Intent intent = new Intent("intent.action.update");
intent.putExtra("progress",progress);
sendBroadcast(intent);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
最后总结一下:
Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法
Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好