Android Service简介

本文的主要内容来源于ServicesBound 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的生命周期如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值