Service 包括bound Service和unbound Service.首先我们先讨论unBound Service使用方法。详细内容可参考官方dev guide
创建一个Service 有两种方式,一是继承IntentService,或者继承Service。
一,unbound service(未绑定activity,service执行完任务后要自己停止,stopself 或者stopservice)
1、IntentSerivce
IntentService 是Service的一个子类,操作上是单线程的。当Intent Start 这个IntentService时,IntentService会自动执行onHandleIntent(Intent intent)里面的方法。IntentService对于每一个请求会创建一个工作线程进行处理,处理完成
后结束工作。对于不要求多线程,同步的程序,IntentService使用起来比较方便。把dev guide里面的例子拿过来。
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) { } } } } }
IntentService实际上是在Service上面添加了消息循环,Intent和IntentService的生命周期一致,所以每次处理请求是都会new 一个Thread进行处理工作,可以查看源码,参考博客地址http://android.blog.51cto.com/268543/528166,上面源码分析的很详细。
2、Service,如要程序要求同步,多线程,可以选择继承Service,这里需要自己手动写消息循环。Handler,loop。之参考dev guide 上面的例子,这个例子与上面的IntentService效果一致,一次只能助理一个请求。
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(); } }
二、bound service
当Service 和activity绑定之后,直到所有的activity结束绑定后,service才结束,一个service可以被多个activity绑定,具体声明周期参考官网Dev Guide。
bound service启动时通过其他Application(activity)调用 bindservice()方法启动,结束是用unbindSerivce();
在service中实现onbind(IBundler)方法,返回一个IBundler。通过IBundler与Activity进行信息交互IPC。这里需要定义一个接口用来传递Service中的方法和信息。原文如下:
To create a bound service, the first thing you must do is define the interface that specifies how a client can communicate with the service. This interface between the service and a client must be an implementation of IBinder
and is what your service must return from the onBind()
callback method. Once the client receives the IBinder
, it can begin interacting with the service through that interface.
1、继承binder。在service类中写一个继承自binder的内部类,在此内部类中写一个获得该Service实例的公共方法,这样Activity绑定Service的时候可以拿到这个binder,进一步拿到Service的实例,调用Service的各种方法。注意,这种消息方式只在同一个应用内使用,如果Service是其他Application调用的,需要后面的方法。
参考DEV GUIDE 上面的例子如下
import java.util.Random; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class LocalService extends Service{ private LocalBinder mBinder = new LocalBinder(); private Random mGenerator = new Random(); @Override public IBinder onBind(Intent intent) { return mBinder; } public class LocalBinder extends Binder { public LocalService getLocalService() { return LocalService.this; } } public int getRandomNum() { return mGenerator.nextInt(); } }
import com.android.service.LocalService.LocalBinder; 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.widget.Button; public class LocalActivity extends Activity{ private LocalService localService; boolean mBound = false; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mBound = false; } @Override public void onServiceConnected(ComponentName name, IBinder service) { LocalBinder localBinder = (LocalBinder) service; localService = localBinder.getLocalService(); mBound = true; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStop() { super.onStop(); if(mBound) { unbindService(mConnection); mBound = false; } } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this,LocalService.class); bindService(intent, mConnection , Context.BIND_AUTO_CREATE); } //点击button,onclick属性在xml中配置 public void click(View v) { Button button = (Button) v; button.setText(String.valueOf(localService.getRandomNum())); } }
2、使用Messenger。通过Messenger发送消息到服务端。主要分为以下几个步骤
1)在Service子类中创建一个Handler子类的(内部类的方式),写好handlmessage方法
2)用Handler的子类创建一个Messenger
3)返回Messenger.getBinder();获得bundler,在onbind();方法中返回给Activity
4)在Activity中获得Binder,用这个binder构造一个Messenger,使用这个Messenger 发送message
注意如果处理响应容易死掉的任务,如获取网络数据,Hander用一个Looper构造,创建一个Handler线程处理任务,
HandlerThread.start(). HandlerThread.getLooper(); 这个Looper用来创建Handler
下面上代码,同样是参考DEV GUIDE 感觉本来做笔记,怎么写成一个翻译了- -!
import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.Process; import android.widget.Toast; public class MyMessager extends Service { Looper handlerLooper; static final int MSG_SAY_HELLO = 1; @Override public void onCreate() { super.onCreate(); HandlerThread mHandlerThread = new HandlerThread("mHandlerThread", Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); handlerLooper = mHandlerThread.getLooper(); mServiceMessager = new Messenger(new IncomingHander(handlerLooper)); } @Override public IBinder onBind(Intent intent) { return mServiceMessager.getBinder(); } class IncomingHander extends Handler { public IncomingHander(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "hello", Toast.LENGTH_SHORT).show(); System.out.println("hello runs"); break; default: super.handleMessage(msg); } } } Messenger mServiceMessager; }
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.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.view.View; import android.widget.Button; public class ActivityMessenger extends Activity{ private Messenger mMessenger; private boolean mBound; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mMessenger = null; mBound = false; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessenger = new Messenger(service); mBound = true; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); Intent i = new Intent(this,MyMessager.class); bindService(i, conn , Context.BIND_AUTO_CREATE); } public void click(View v) { Message msg = Message.obtain(null, MyMessager.MSG_SAY_HELLO, 0, 0); try { mMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onStop() { super.onStop(); unbindService(conn); mBound = false; } }
三、通过AIDL进行多线程,跨进程通信。这个步骤相对麻烦,也没完全弄懂,以后补上
以上内容纯属个人学习笔记,技术有限,希望不会误导其他人