Chinaunix首页 | 论坛 | 博客
  • 博客访问: 408911
  • 博文数量: 121
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1393
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-11 12:17
个人简介

www.vibexie.com vibexie@qq.com

文章分类

全部博文(121)

文章存档

2015年(55)

2014年(66)

我的朋友

分类: Android平台

2015-04-12 13:56:28

对与学习Service,Service基础的东西很好理解。无非就是startService启动Service或者IntentService,需要注意Service默认是在UI线程中执行,若需要在Service中执行intensive work,必须自己new一条线程
而对于intentService,自己会自动new一条线程,所以我们一旦使用intentService,就可以不用自己new线程了。关于intentService与Service如和选择,官方的api是说多任务就选择Service。

Service的重难点还是在bindService绑定服务上。
下面重点分析
bindService.
1.
bindService基础
2.使用Messenger的IPC
3.使用AIDL的IPC
4.使用Transact的IPC

笔记

  1. OK,学习Android从官方demo开始,一切皆在demo中

  2. /************************************************************************************************************************************/
  3. 对binderService的理解

  4. 下面是Service的demo

  5. public class LocalService extends Service {
  6.     /**
  7.      * Binder given to clients
  8.      * LocalBinder也就是Binder对象上转型为IBinder接口
  9.      */
  10.     private final IBinder mBinder = new LocalBinder();

  11.     /**
  12.      * Random number generator
  13.      * 这个就不解释了
  14.      */
  15.     private final Random mGenerator = new Random();

  16.     /**
  17.      * Class used for the client Binder. Because we know this service always
  18.      * runs in the same process as its clients, we don't need to deal with IPC.
  19.      * 重要的是这是一个内部类,显然,内部类可以访问外围类的成员与方法。
  20.      * 而Binder是实现了IBinder接口的一个类。
  21.      * IBinder又是onBind方法返回给Service的一个接口。其它组件如Activity与Service就是通过IBinder接口进行通信的。
  22.      * 所以通过onBind方法返回一个IBinder给Service,通过LocalBinder对象的getService()方法将IBinder返回给Activity
  23.      * 这样就形成这样的通信方式:Service-IBinder-Activity
  24.      */
  25.     public class LocalBinder extends Binder {
  26.         LocalService getService() {
  27.             // Return this instance of LocalService so clients can call public methods
  28.             return LocalService.this;
  29.         }
  30.     }

  31.     /**
  32.      * 将Service与Activity通信的接口返回给Service
  33.      * @param intent
  34.      * @return
  35.      */
  36.     @Override
  37.     public IBinder onBind(Intent intent) {
  38.         return mBinder;
  39.     }

  40.     /**
  41.      * 一个自定义的Service的方法,供内部类LocalBinder对象调用
  42.      * method for clients
  43.      * @return
  44.      */
  45.     public int getRandomNumber() {
  46.         return mGenerator.nextInt(100);
  47.     }
  48. }


  49. 下面是Activity的demo

  50. public class BindingActivity extends Activity {
  51.     /**
  52.      * Service中一个内部类的对象,通过此对此对象课返回与Service通信的IBinder
  53.      */
  54.     LocalService mService;

  55.     /**
  56.      * 标记是否绑定Service
  57.      */
  58.     boolean mBound = false;

  59.     @Override
  60.     protected void onCreate(Bundle savedInstanceState) {
  61.         super.onCreate(savedInstanceState);
  62.         setContentView(R.layout.main);
  63.     }

  64.     @Override
  65.     protected void onStart() {
  66.         super.onStart();
  67.         /**
  68.          * Bind to LocalService
  69.          */
  70.         Intent intent = new Intent(this, LocalService.class);
  71.         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  72.     }

  73.     @Override
  74.     protected void onStop() {
  75.         super.onStop();
  76.         /**
  77.          * Unbind from the service
  78.          * 必须记得解绑
  79.          */
  80.         if (mBound) {
  81.             unbindService(mConnection);
  82.             mBound = false;
  83.         }
  84.     }

  85.     /** Called when a button is clicked (the button in the layout file attaches to
  86.      * this method with the android:onClick attribute)
  87.      * 通过Service的内部类LocalBinder对象调用Service的方法,“简称通信”,哈哈!
  88.      */
  89.     public void onButtonClick(View v) {
  90.         if (mBound) {
  91.             // Call a method from the LocalService.
  92.             // However, if this call were something that might hang, then this request should
  93.             // occur in a separate thread to avoid slowing down the activity performance.
  94.             int num = mService.getRandomNumber();
  95.             Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
  96.         }
  97.     }

  98.     /**
  99.      * Defines callbacks for service binding, passed to bindService()
  100.      * ServiceConnection对象mConnection是binderService的第二个参数
  101.      */
  102.     private ServiceConnection mConnection = new ServiceConnection() {

  103.         /**
  104.          * 绑定service时回调
  105.          * @param className
  106.          * @param service
  107.          */
  108.         @Override
  109.         public void onServiceConnected(ComponentName className,
  110.                                        IBinder service) {
  111.             /**
  112.              * We've bound to LocalService, cast the IBinder and get LocalService instance
  113.              * 获取IBinder建立与service的通信,这里说的IBinder不要误解,getService返回LocalBinder对象
  114.              * 而LocalBinder继承Binder
  115.              * 而Binder实现IBinder接口
  116.              */
  117.             LocalBinder binder = (LocalBinder) service;
  118.             mService = binder.getService();
  119.             mBound = true;
  120.         }

  121.         /**
  122.          * 解绑service时回调
  123.          * @param arg0
  124.          */
  125.         @Override
  126.         public void onServiceDisconnected(ComponentName arg0) {
  127.             mBound = false;
  128.         }
  129.     };
  130. }


  131. /************************************************************************************************************************************/

  132. 对Messenger(信使)的理解

  133. 正如上面对bindService的理解中,客户端是通过调用service的方法的方式进行通行的,而对于使用Messenger后,就不用回调method了。
  134. 实现进程集间的通信,可以用Messenger和AIDL,如果使用上面的对bindService的理解的demo似乎只是通过调用service的方法是实现单向的通行
  135. 如果我们的业务背景是,在同一个App中,实现进程间的通信,我们使用Messenger。如果在不同的App间的service进程间通信,我们使用AIDL

  136. 下面是使用Messenger的service Demo

  137. public class MessengerService extends Service {
  138.     /** Command to the service to display a message */
  139.     static final int MSG_SAY_HELLO = 1;

  140.     /**
  141.      * Handler of incoming messages from clients.
  142.      */
  143.     class IncomingHandler extends Handler {
  144.         @Override
  145.         public void handleMessage(Message msg) {
  146.             switch (msg.what) {
  147.                 case MSG_SAY_HELLO:
  148.                     Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
  149.                     break;
  150.                 default:
  151.                     super.handleMessage(msg);
  152.             }
  153.         }
  154.     }

  155.     /**
  156.      * Target we publish for clients to send messages to IncomingHandler.
  157.      */
  158.     final Messenger mMessenger = new Messenger(new IncomingHandler());

  159.     /**
  160.      * When binding to the service, we return an interface to our messenger
  161.      * for sending messages to the service.
  162.      * 这段代码难以理解的是mMessenger.getBinder();
  163.      * 我们看看源码,Messenger类的代码很少,但是封装死了,不能深入看看
  164.      * public IBinder getBinder() {
  165.      * return mTarget.asBinder();
  166.      * }
  167.      * 而mTarget又是private final IMessenger mTarget;我们无法看到IMessenger源码
  168.      *
  169.      */
  170.     @Override
  171.     public IBinder onBind(Intent intent) {
  172.         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
  173.         return mMessenger.getBinder();
  174.     }
  175. }


  176. 下面是service的Demo

  177. public class ActivityMessenger extends Activity {
  178.     /** Messenger for communicating with the service. */
  179.     Messenger mService = null;

  180.     /** Flag indicating whether we have called bind on the service. */
  181.     boolean mBound;

  182.     /**
  183.      * Class for interacting with the main interface of the service.
  184.      */
  185.     private ServiceConnection mConnection = new ServiceConnection() {
  186.         public void onServiceConnected(ComponentName className, IBinder service) {
  187.             // This is called when the connection with the service has been
  188.             // established, giving us the object we can use to
  189.             // interact with the service. We are communicating with the
  190.             // service using a Messenger, so here we get a client-side
  191.             // representation of that from the raw IBinder object.
  192.             mService = new Messenger(service);
  193.             mBound = true;
  194.         }

  195.         public void onServiceDisconnected(ComponentName className) {
  196.             // This is called when the connection with the service has been
  197.             // unexpectedly disconnected -- that is, its process crashed.
  198.             mService = null;
  199.             mBound = false;
  200.         }
  201.     };

  202.     public void sayHello(View v) {
  203.         if (!mBound) return;
  204.         // Create and send a message to the service, using a supported 'what' value
  205.         Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
  206.         try {
  207.             mService.send(msg);
  208.         } catch (RemoteException e) {
  209.             e.printStackTrace();
  210.         }
  211.     }

  212.     @Override
  213.     protected void onCreate(Bundle savedInstanceState) {
  214.         super.onCreate(savedInstanceState);
  215.         setContentView(R.layout.main);
  216.     }

  217.     @Override
  218.     protected void onStart() {
  219.         super.onStart();
  220.         // Bind to the service
  221.         bindService(new Intent(this, MessengerService.class), mConnection,
  222.                 Context.BIND_AUTO_CREATE);
  223.     }

  224.     @Override
  225.     protected void onStop() {
  226.         super.onStop();
  227.         // Unbind from the service
  228.         if (mBound) {
  229.             unbindService(mConnection);
  230.             mBound = false;
  231.         }
  232.     }
  233. }

  234. 由于官方的demo只是把Activity的消息发送到service,并每有说明如何从service发送到Activity。下面把demo修改下为一个小的app demo便于理解
  235. 布局文件就不给出了
  236. /**
  237.  * MainActivity.java
  238.  */
  239. package com.vibexie.servicemessenger;

  240. import android.content.ComponentName;
  241. import android.content.Context;
  242. import android.content.Intent;
  243. import android.content.ServiceConnection;
  244. import android.os.Handler;
  245. import android.os.IBinder;
  246. import android.os.Message;
  247. import android.os.Messenger;
  248. import android.os.RemoteException;
  249. import android.support.v7.app.ActionBarActivity;
  250. import android.os.Bundle;
  251. import android.view.Menu;
  252. import android.view.MenuItem;
  253. import android.view.View;
  254. import android.widget.Button;
  255. import android.widget.EditText;


  256. public class MainActivity extends ActionBarActivity {
  257.     private Button button;
  258.     private EditText editText;

  259.     /**
  260.      * Messenger for communicating with the service.
  261.      * 负责向service发送Message
  262.      */
  263.     Messenger mService = null;

  264.     /** Flag indicating whether we have called bind on the service. */
  265.     boolean mBound;

  266.     /**
  267.      * 理解为客户端的Messenger,负责接收Service返回的Message
  268.      */
  269.     private Messenger clientMessenger=new Messenger(new Handler(){
  270.         @Override
  271.         public void handleMessage(Message msg) {
  272.             super.handleMessage(msg);
  273.             editText.setText(msg.obj.toString());
  274.         }
  275.     });

  276.     /**
  277.      * Class for interacting with the main interface of the service.
  278.      * 理解了bindService,这里就好理解了,不赘述
  279.      */
  280.     private ServiceConnection mConnection = new ServiceConnection() {
  281.         public void onServiceConnected(ComponentName className, IBinder service) {
  282.             /**
  283.              * This is called when the connection with the service has been
  284.              *established, giving us the object we can use to
  285.              *interact with the service. We are communicating with the
  286.              *service using a Messenger, so here we get a client-side
  287.              *representation of that from the raw IBinder object.
  288.              *绑定Service接收消息的Messenger,以向service发送Message
  289.              */
  290.             mService = new Messenger(service);
  291.             mBound = true;
  292.         }

  293.         public void onServiceDisconnected(ComponentName className) {
  294.             /**
  295.              *This is called when the connection with the service has been
  296.              *unexpectedly disconnected -- that is, its process crashed.
  297.              * 解绑时回调
  298.              */
  299.             mService = null;
  300.             mBound = false;
  301.         }
  302.     };

  303.     @Override
  304.     protected void onCreate(Bundle savedInstanceState) {
  305.         super.onCreate(savedInstanceState);
  306.         setContentView(R.layout.activity_main);

  307.         button=(Button)this.findViewById(R.id.button);
  308.         editText=(EditText)this.findViewById(R.id.editText);

  309.         button.setOnClickListener(new View.OnClickListener() {
  310.             @Override
  311.             public void onClick(View v) {
  312.                 if (!mBound) return;
  313.                 /**
  314.                  * Create and send a message to the service, using a supported 'what' value
  315.                  * 一看到Message就要联系到Handler,我们写Messsge完全可以不按这样的方式写
  316.                  * 这里的obtain为public static Message obtain(Handler h, int what, int arg1, int arg2);很好理解吧
  317.                  */
  318.                 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);

  319.                 /**
  320.                  * 设定msg消息将要返回到我们定义的客户端clientMessenger,这里将clientMessenger携带发送给service
  321.                  */
  322.                 msg.replyTo=clientMessenger;

  323.                 try {
  324.                     /**
  325.                      * 将Message发送给Service
  326.                      */
  327.                     mService.send(msg);
  328.                 } catch (RemoteException e) {
  329.                     e.printStackTrace();
  330.                 }
  331.             }
  332.         });
  333.     }

  334.     @Override
  335.     protected void onStart() {
  336.         super.onStart();
  337.         // Bind to the service
  338.         bindService(new Intent(this, MessengerService.class), mConnection,
  339.                 Context.BIND_AUTO_CREATE);
  340.     }

  341.     @Override
  342.     protected void onStop() {
  343.         super.onStop();
  344.         // Unbind from the service
  345.         if (mBound) {
  346.             unbindService(mConnection);
  347.             mBound = false;
  348.         }
  349.     }
  350. }

  351. /**
  352.  * MessengerService.java
  353.  */
  354. package com.vibexie.servicemessenger;

  355. import android.app.Service;
  356. import android.content.Intent;
  357. import android.os.Handler;
  358. import android.os.IBinder;
  359. import android.os.Message;
  360. import android.os.Messenger;
  361. import android.os.RemoteException;
  362. import android.widget.Toast;

  363. public class MessengerService extends Service {
  364.     /** Command to the service to display a message */
  365.     static final int MSG_SAY_HELLO = 11;

  366.     /**
  367.      * 对应Activity的clientMessenger
  368.      */
  369.     private Messenger replyMessenger=null;

  370.     /**
  371.      * Handler of incoming messages from clients.
  372.      */
  373.     class IncomingHandler extends Handler {
  374.         @Override
  375.         public void handleMessage(Message msg) {
  376.             switch (msg.what) {
  377.                 case MSG_SAY_HELLO:
  378.                     Toast.makeText(getApplicationContext(), "Service接收到11", Toast.LENGTH_SHORT).show();

  379.                     /**
  380.                      * 这里是回传Message给Activity的关键
  381.                      * 首先从消息池中obtain,再包装消息发送个Activity
  382.                      */
  383.                     Message replyMessage=Message.obtain();
  384.                     replyMessage.obj="我接收到你的消息!";
  385.                     /**
  386.                      * 注意是msg调用replyTo方法,将replyMessager对应到客户端的clientMessenger
  387.                      */
  388.                     replyMessenger=msg.replyTo;
  389.                     try {
  390.                         replyMessenger.send(replyMessage);
  391.                     } catch (RemoteException e) {
  392.                         e.printStackTrace();
  393.                     }

  394.                     break;
  395.                 default:
  396.                     super.handleMessage(msg);
  397.             }
  398.         }
  399.     }

  400.     /**
  401.      * Target we publish for clients to send messages to IncomingHandler.
  402.      */
  403.     final Messenger mMessenger = new Messenger(new IncomingHandler());

  404.     /**
  405.      * When binding to the service, we return an interface to our messenger
  406.      * for sending messages to the service.
  407.      */
  408.     @Override
  409.     public IBinder onBind(Intent intent) {
  410.         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
  411.         return mMessenger.getBinder();
  412.     }
  413. }

  414. 总结一下:
  415. 客户端和Service之间进行Message的交互大概是这样的模型
  416.                客户端 Service
  417.      clientMessenger*         * mMessenger
  418.                       *   *
  419.                         *
  420.                       *    *
  421.             mService*         *replyMessenger

  422. /************************************************************************************************************************************/

  423. 对AIDL的理解
  424. 在不同App间访问service即不同App进程间通信,我们就使用AIDL。这个相对用的少,因为很少需要与其它App进行交互
  425. 对AIDl的理解因为需要在一个demo中认识,所以笔记在下一篇

阅读(1368) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~