Service概念及用途
Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行,那 我们什么时候会用到Service呢?比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当我们退出播放音乐的应用,如果不用Service,我 们就听不到歌了,所以这时候就得用到Service了。
Service的两种模式
本地服务 Local Service 用于应用程序内部。
它可以启动并运行,直至有人停止了它或它自己停止。在这种方式下,它以调用Context.startService()启动,而以调用Context.stopService()结束。它可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。不论调用了多少次startService()方法,你只需要调用一次stopService()来停止服务。
用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
远程服务 Remote Service 用于android系统内部的应用程序之间。
它可以通过自己定义并暴露出来的接口进行程序操作。客户端建立一个到服务对象的连接,并通过那个连接来调用服务。连接以调用Context.bindService()方法建立,以调用 Context.unbindService()关闭。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
Servicie的生命周期
Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,当我们第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。
服务只会开启一次, oncreate只会在服务创建的时候 执行 ,多次调用startService()方法,不会重复开启服务。多次调用stopService的方法 ,服务只会被停止一次,多次调用不会报错。多次调用bindService方法时,如果服务已经开启了 就不会再去执行oncreate(),如果服务是采用bind的方式 绑定的只能解绑一次。
如果服务被绑定过,就不能通过stopService的方法 停止服务了,要想停止服务 必须先手动的把服务解除绑定.然后才能停止服务:
startService - bindService - unbindservice - stopService(ondestroy);
startService - bindService - stopService(服务停不掉,因为被绑定了)- unbindservice(由于服务已经解除绑定,所以服务就离开的停止了).
如果我们想让服务在后台长期运行又想调用服务里面的方法,执行下列步骤即可:
startService - bindService - unbindservice - stopService(ondestroy);
具体可以参考官方docs:http://developer.android.com/guide/components/services.html
下面通过一个实例来演示Service的生命周期
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start服务" />
<Button
android:id="@+id/bt_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bind服务" />
<Button
android:id="@+id/bt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop服务" />
<Button
android:id="@+id/bt_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="unbind服务" />
<Button
android:id="@+id/bt_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用服务里面的方法" />
</LinearLayout>
MyService.java
package cn.itcast.testservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return new MyBinder();
}
public class MyBinder extends Binder implements IService{
@Override
public void callMethodInService() {
methodInService();
}
}
/**
* 服务里面的一个方法.
*/
public void methodInService(){
Toast.makeText(this, "我是服务里面的方法", 0).show();
}
/**
* 服务第一次被创建 调用的方法
*/
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
System.out.println("onStart");
super.onStart(intent, startId);
}
/**
* 服务在停止的时候 调用的方法
*/
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
DemoActivity.java
package cn.itcast.testservice;
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.view.View.OnClickListener;
import android.widget.Button;
public class DemoActivity extends Activity implements OnClickListener {
private Intent intent;
private MyConn conn;
private IService iService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent = new Intent(this, MyService.class);
findView();
}
private void findView() {
Button bt_start = (Button) findViewById(R.id.bt_start);
Button bt_bind = (Button) findViewById(R.id.bt_bind);
Button bt_stop = (Button) findViewById(R.id.bt_stop);
Button bt_unbind = (Button) findViewById(R.id.bt_unbind);
Button bt_call = (Button) findViewById(R.id.bt_call);
bt_start.setOnClickListener(this);
bt_bind.setOnClickListener(this);
bt_stop.setOnClickListener(this);
bt_unbind.setOnClickListener(this);
bt_call.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start: // start的方式开启服务
startService(intent);
break;
case R.id.bt_bind:// bind的方式开启服务
conn = new MyConn();
bindService(intent, conn, Context.BIND_AUTO_CREATE);
break;
case R.id.bt_stop: // stop的方式停止服务
stopService(intent);
break;
case R.id.bt_unbind:// unbind的方式解除绑定服务
try {
unbindService(conn);
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.bt_call:
// mybinder.callMethodInService();
iService.callMethodInService();
break;
default:
break;
}
}
private class MyConn implements ServiceConnection {
/**
* onServiceConnected 当服务被成功绑定的时候 调用的方法
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iService = (IService) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
unbindService(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
}
IService.java
package cn.itcast.testservice;
public interface IService {
public void callMethodInService();
}
IService是回调接口,在bind 方法的时候,返回一个继承Binder 并且实现IService接口的对象 即: public class MyBinder extends Binder implements IService。这样更符合Java 面向对象的思想。