Android Service简介

来源:互联网 发布:买淘宝店铺哪个网站 编辑:程序博客网 时间:2024/06/15 18:21

本文的主要内容来源于Services和Bound Services,均为google官方文档,如果英文好的话建议直接看原文。下面主要是我自己的一些笔记。

Service

Service是android的四大组件之一,平常用的最多的也就是activity,其他三个都只会在特定的情景下才会使用,所以接触的机会不会太多。这次主要是要在android上做一个计步功能,需要使用到service在后台计步。总的来说,service可以在后台长时间运行一个任务而不依赖于界面,它可以在后台处理网络请求,播放音乐,文件读写等等。

Service有两种启动方式,startService()和bindService(),下面主要介绍两种创建方式。

在使用service之前,需要在manifest文件中声明该service

service的主要方法有:

onStartCommand() 通过startService启动时,会调用该方法,使用这个方法启动的service会一直在后台运行,除非遇到stopSelf()或者stopService()才会停止

onBind() 通过bindService()启动时,会调用该方法,使用这个方法需要提供一个client和service通信的接口(ServiceConnction,比较麻烦)

onCreate() 这个方法会在onStartCommand或onBind之前调用,也就是不管已那种方式启动,第一次创建时都会执行该函数

onDestroy() 这个方法会在系统kill该service时调用,该函数应该释放一些线程、注册监听器、接收器的资源


第一种创建方式 startService()

在activity等组件里通过startService启动service,该方法可以传递一个Intent对象给onStartCommand()。下面介绍两个创建service的类

Service, 这是所有services的基类,直接集成该类,需要新起一个线程,因为该类默认是在主线程中运行的。

IntentService, 这是一个Service的子类,它会在子线程中处理请求,你只需要实现一个onHandlerIntent()方法就可以了。

IntentService例子

public class HelloIntentService extends IntentService {  /**   * A constructor is required, and must call the super IntentService(String)   * constructor with a name for the worker thread.   */  public HelloIntentService() {      super("HelloIntentService");  }  /**   * The IntentService calls this method from the default worker thread with   * the intent that started the service. When this method returns, IntentService   * stops the service, as appropriate.   */  @Override  protected void onHandleIntent(Intent intent) {      // Normally we would do some work here, like download a file.      // For our sample, we just sleep for 5 seconds.      long endTime = System.currentTimeMillis() + 5*1000;      while (System.currentTimeMillis() < endTime) {          synchronized (this) {              try {                  wait(endTime - System.currentTimeMillis());              } catch (Exception e) {              }          }      }  }}
Intent例子

public class HelloService extends Service {  private Looper mServiceLooper;  private ServiceHandler mServiceHandler;  // Handler that receives messages from the thread  private final class ServiceHandler extends Handler {      public ServiceHandler(Looper looper) {          super(looper);      }      @Override      public void handleMessage(Message msg) {          // Normally we would do some work here, like download a file.          // For our sample, we just sleep for 5 seconds.          long endTime = System.currentTimeMillis() + 5*1000;          while (System.currentTimeMillis() < endTime) {              synchronized (this) {                  try {                      wait(endTime - System.currentTimeMillis());                  } catch (Exception e) {                  }              }          }          // Stop the service using the startId, so that we don't stop          // the service in the middle of handling another job          stopSelf(msg.arg1);      }  }  @Override  public void onCreate() {    // Start up the thread running the service.  Note that we create a    // separate thread because the service normally runs in the process's    // main thread, which we don't want to block.  We also make it    // background priority so CPU-intensive work will not disrupt our UI.    HandlerThread thread = new HandlerThread("ServiceStartArguments",            Process.THREAD_PRIORITY_BACKGROUND);    thread.start();    // Get the HandlerThread's Looper and use it for our Handler    mServiceLooper = thread.getLooper();    mServiceHandler = new ServiceHandler(mServiceLooper);  }  @Override  public int onStartCommand(Intent intent, int flags, int startId) {      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();      // For each start request, send a message to start a job and deliver the      // start ID so we know which request we're stopping when we finish the job      Message msg = mServiceHandler.obtainMessage();      msg.arg1 = startId;      mServiceHandler.sendMessage(msg);      // If we get killed, after returning from here, restart      return START_STICKY;  }  @Override  public IBinder onBind(Intent intent) {      // We don't provide binding, so return null      return null;  }  @Override  public void onDestroy() {    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();  }}
开启一个Service

Intent intent = new Intent(this, HelloService.class);startService(intent);
可以通过startForeground()让Service运行在前台,在前台运行的service必须在通知栏里面提供一个status bar,这样的service在low memory的时候不会被系统杀掉,就像播放音乐的应用在通知栏里面有一栏显示当前歌曲一样。

Service的生命周期如下:



Bound Service主要用于service和别的组件的通信,允许别的组件绑定到service上,发送请求接受返回值来进行通信,当然前提是servcie实现了onBind方法,允许别的组件绑定。

主要有三种方式,

1.继承Binder类,用于同一应用之间的通信

2.Messenger,用于应用间的通信

3.AIDL, 通过先让servcie同一时间内处理多个请求,可直接使用该方法

我的项目用的是第一种,使用方法如下:

public class LocalService extends Service {    // Binder given to clients    private final IBinder mBinder = new LocalBinder();    // Random number generator    private final Random mGenerator = new Random();    /**     * Class used for the client Binder.  Because we know this service always     * runs in the same process as its clients, we don't need to deal with IPC.     */    public class LocalBinder extends Binder {        LocalService getService() {            // Return this instance of LocalService so clients can call public methods            return LocalService.this;        }    }    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    /** method for clients */    public int getRandomNumber() {      return mGenerator.nextInt(100);    }}

上面的例子中,在LocalBinder中提供了一个getService()的方法,该方法提供了一个LocalService的当前对象实例,它可以给客户端用来调用service中的公用方法,比如此时,在客户端中就可以从service重调用getRandomNumber()


Activity的绑定如下:

public class BindingActivity extends Activity {    LocalService mService;    boolean mBound = false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }    @Override    protected void onStart() {        super.onStart();        // Bind to LocalService        Intent intent = new Intent(this, LocalService.class);        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);    }    @Override    protected void onStop() {        super.onStop();        // Unbind from the service        if (mBound) {            unbindService(mConnection);            mBound = false;        }    }    /** Called when a button is clicked (the button in the layout file attaches to      * this method with the android:onClick attribute) */    public void onButtonClick(View v) {        if (mBound) {            // Call a method from the LocalService.            // However, if this call were something that might hang, then this request should            // occur in a separate thread to avoid slowing down the activity performance.            int num = mService.getRandomNumber();            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();        }    }    /** Defines callbacks for service binding, passed to bindService() */    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName className,                IBinder service) {            // We've bound to LocalService, cast the IBinder and get LocalService instance            LocalBinder binder = (LocalBinder) service;            mService = binder.getService();            mBound = true;        }        @Override        public void onServiceDisconnected(ComponentName arg0) {            mBound = false;        }    };}

Activity的客户端在绑定service时,实现了一个ServiceConnection类,该类在client和service建立通信时,会调用起回调函数onServiceConnected()

BoundService的生命周期如下:


0 0
原创粉丝点击