Android(安卓)Service使用方法
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 ofIBinder
and is what your service must return from theonBind()
callback method. Once the client receives theIBinder
, 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();@Overridepublic 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() {@Overridepublic void onServiceDisconnected(ComponentName name) {mBound = false;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {LocalBinder localBinder = (LocalBinder) service;localService = localBinder.getLocalService();mBound = true;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);}@Overrideprotected void onStop() {super.onStop();if(mBound){unbindService(mConnection);mBound = false;}}@Overrideprotected 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;@Overridepublic void onCreate() {super.onCreate();HandlerThread mHandlerThread = new HandlerThread("mHandlerThread",Process.THREAD_PRIORITY_BACKGROUND);mHandlerThread.start();handlerLooper = mHandlerThread.getLooper();mServiceMessager = new Messenger(new IncomingHander(handlerLooper));}@Overridepublic IBinder onBind(Intent intent) {return mServiceMessager.getBinder();}class IncomingHander extends Handler {public IncomingHander(Looper looper) {super(looper);}@Overridepublic 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() {@Overridepublic void onServiceDisconnected(ComponentName name) {mMessenger = null;mBound = false;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mMessenger = new Messenger(service);mBound = true;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);}@Overrideprotected 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();}}@Overrideprotected void onStop() {super.onStop();unbindService(conn);mBound = false;}}
三、通过AIDL进行多线程,跨进程通信。这个步骤相对麻烦,也没完全弄懂,以后补上
以上内容纯属个人学习笔记,技术有限,希望不会误导其他人
更多相关文章
- Android类参考---Fragment(四)
- Android(安卓)SurfaceFlinger中的工作线程:threadLoop()
- [置顶] android fragment hidenChanged方法分析
- android Button实现点击事件的三种方法
- Android开发工具GenyMotion安装和使用方法
- android scrollview嵌套scrollview,gridview,listview的方法和深
- 【Android源码】Intent 源码分析
- Android视图加载流程(5)之View的详细绘制流程Layout
- Android(安卓)数据传递-通过Intent传递数据