Androidservice通过aidl回调客户端daemon

前端时间项目运用到AIDL,关于AIDL客户端以及AIDL服务端网络上没有一个比较完备的Demo.

站在用户的角度思考问题,与客户深入沟通,找到高港网站设计与高港网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都做网站、成都网站建设、企业官网、英文网站、手机端网站、网站推广、国际域名空间、网站空间、企业邮箱。业务覆盖高港地区。

而参考Demo无疑是一个比较快速的学习方法.因此,我写了一个Demo.

供大家参考,也非常欢迎大家对其中写的不好的地方进行指正.

 

好了,首先简述下基本功能:

在AIDL 客户端三个EditText中输入三个值,点击提交按钮,将这三个值传入到AIDL服务端进行处理.

服务端处理后会执行客户端的回调函数:在AIDL客户端界面进行刷新,并显示一个toast.

 

接下来看看代码结构:

Android  service通过aidl  回调客户端 daemon

 

需要注意的是,两个工程中com.harlan.demo.aidl包内部的文件必须保持一致.

 

(1)HarlanInfo.java:这是包中唯一的一个java文件,是一个数据结构,该类实现了Parcelable接口

[java] view plaincopyprint?

  1. package com.harlan.demo.aidl;  

  2.   

  3. import android.os.Parcel;  

  4. import android.os.Parcelable;  

  5.   

  6. /** 

  7.  *  

  8.  * <一句话功能简述> 

  9.  * Parcelable是Android特有的功能,效率比实现Serializable接口高 

  10.  *  

  11.  * @author  Administrator 

  12.  * @version  [版本号, 2012-12-10] 

  13.  * @see  [相关类/方法] 

  14.  * @since  [产品/模块版本] 

  15.  */  

  16. public class HarlanInfo implements Parcelable  

  17. {  

  18.     private String name;  

  19.       

  20.     private int age;  

  21.       

  22.     private String place;  

  23.   

  24.     public String getName()  

  25.     {  

  26.         return name;  

  27.     }  

  28.   

  29.     public void setName(String name)  

  30.     {  

  31.         this.name = name;  

  32.     }  

  33.   

  34.     public int getAge()  

  35.     {  

  36.         return age;  

  37.     }  

  38.   

  39.     public void setAge(int age)  

  40.     {  

  41.         this.age = age;  

  42.     }  

  43.   

  44.     public String getPlace()  

  45.     {  

  46.         return place;  

  47.     }  

  48.   

  49.     public void setPlace(String place)  

  50.     {  

  51.         this.place = place;  

  52.     }  

  53.       

  54.     /** 

  55.      * <默认构造函数> 

  56.      */  

  57.     public HarlanInfo()  

  58.     {  

  59.           

  60.     }  

  61.       

  62.     /** 

  63.      * <默认构造函数> 

  64.      */  

  65.     public HarlanInfo(Parcel in)  

  66.     {  

  67.         //注意顺序  

  68.          name = in.readString();  

  69.         age = in.readInt();  

  70.         place = in.readString();  

  71.     }  

  72.       

  73.     /** 

  74.      * seems meaningless 

  75.      * return 0; 

  76.      */  

  77.     @Override  

  78.     public int describeContents()  

  79.     {  

  80.         return 0;  

  81.     }  

  82.   

  83.     /** 

  84.      * 将对象序列化为一个Parcel对象 

  85.      *  可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面, 

  86.      *  再通过createFromParcel从流里读取对象 

  87.      *  注意:写的顺序和读的顺序必须一致。  

  88.      */  

  89.     @Override  

  90.     public void writeToParcel(Parcel dest, int flags)  

  91.     {  

  92.         dest.writeString(name);  

  93.         dest.writeInt(age);  

  94.         dest.writeString(place);  

  95.     }  

  96.       

  97.     /** 

  98.      * 实例化静态内部对象CREATOR实现接口Parcelable.Creator 

  99.      * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写 

  100.      */  

  101.     public static final Parcelable.Creator CREATOR = new Creator(){  

  102.   

  103.       //将Parcel对象反序列化为HarlanInfo     

  104.         @Override  

  105.         public HarlanInfo createFromParcel(Parcel source)  

  106.         {  

  107.             HarlanInfo hlInfo = new HarlanInfo(source);  

  108.             return hlInfo;  

  109.         }  

  110.   

  111.         @Override  

  112.         public HarlanInfo[] newArray(int size)  

  113.         {  

  114.             return new HarlanInfo[size];  

  115.         }  

  116.           

  117.     };  

  118.       

  119. }  

 

(2)HarlanInfo.aidl :协同HarlanInfo.java文件"作战",缺一不可.

[java] view plaincopyprint?

  1. package com.harlan.demo.aidl;  

  2.   

  3. parcelable HarlanInfo;  

 

(3)ICallBack.aidl:
这是客户端回调方法的接口,在客户端实现其具体方法,在服务端调用执行.

[java] view plaincopyprint?

  1. package com.harlan.demo.aidl;  

  2. interface ICallBack{  

  3.     /** 

  4.     *callback of AIDLClient 

  5.     *handle by server 

  6.     **/  

  7.     void handleByServer(String param);  

  8. }  

 

(4)ExecuteService.aidl:

这是从服务端获取数据方法的接口,在服务端实现其具体方法,在客户端调用执行.

参数info是由用户输入的数据构成的,同时传递的还要客户端回调方法的句柄,从而服务端可以调用客户端的回调方法.

该方法返回一个HarlanInfo的数据类型,客户端获得此数据,在界面上进行相应的显示.

[java] view plaincopyprint?

  1. package com.harlan.demo.aidl;  

  2. import com.harlan.demo.aidl.HarlanInfo;  

  3. import com.harlan.demo.aidl.ICallBack;  

  4. interface ExecuteServiceAIDL  

  5. {  

  6.     /** 

  7.      *get info from server and  

  8.      *Transfer a callback methods handle; 

  9.      *if occur error ,will be return null 

  10.      *对于非基本数据类型和String和CharSequence类型,要加上方向指示 

  11.      *包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。 

  12.      */  

  13.     HarlanInfo getServerHarlanInfo(in HarlanInfo info,ICallBack icallback);  

  14. }  


好了,现在对com.harlan.demo.aidl包已经大致了解,build一下project,发现gen文件夹下面多出来一个包:

Android  service通过aidl  回调客户端 daemon
 包中文件可以随便看看,不看也没事.因为你只要在客户端服务端相应的位置实现对应的接口就可以了.

先来看看服务端,因为服务端相对简单些,不需要界面什么的,只是一个Service.

上代码:

[java] view plaincopyprint?

  1. package com.harlan.demo.service;  

  2.   

  3. import android.app.Service;  

  4. import android.content.Intent;  

  5. import android.os.IBinder;  

  6. import android.os.RemoteException;  

  7. import android.util.Log;  

  8.   

  9. import com.harlan.demo.aidl.ExecuteServiceAIDL;  

  10. import com.harlan.demo.aidl.HarlanInfo;  

  11. import com.harlan.demo.aidl.ICallBack;  

  12.   

  13. public class AIDLService extends Service  

  14. {  

  15.     public static final String TAG = "AIDLService";  

  16.       

  17.     private ICallBack mCallBack;  

  18.       

  19.     /** 

  20.      * 绑定服务 

  21.      */  

  22.     @Override  

  23.     public IBinder onBind(Intent intent)  

  24.     {  

  25.         // TODO Auto-generated method stub  

  26.         return mBinder;  

  27.     }  

  28.       

  29.     /** 

  30.      * 创建服务 

  31.      */  

  32.     @Override  

  33.     public void onCreate()  

  34.     {  

  35.         super.onCreate();  

  36.     }  

  37.   

  38.     /** 

  39.      * 销毁服务 

  40.      */  

  41.     @Override  

  42.     public void onDestroy()  

  43.     {  

  44.         super.onDestroy();  

  45.     }  

  46.   

  47.     /** 

  48.      * 启动服务 

  49.      */  

  50.     @Override  

  51.     public void onStart(Intent intent, int startId)  

  52.     {  

  53.         super.onStart(intent, startId);  

  54.     }  

  55.   

  56.     /** 

  57.      * 解绑服务 

  58.      */  

  59.     @Override  

  60.     public boolean onUnbind(Intent intent)  

  61.     {  

  62.         mCallBack = null;  

  63.         return super.onUnbind(intent);  

  64.     }  

  65.       

  66.     ExecuteServiceAIDL.Stub mBinder = new ExecuteServiceAIDL.Stub()  

  67.     {  

  68.        //这里实现了getServiceHarlanInfo接口  

  69.         @Override  

  70.         public HarlanInfo getServerHarlanInfo(HarlanInfo info, ICallBack icallback)  

  71.             throws RemoteException  

  72.         {  

  73.             Log.d(TAG,"getServerHarlanInfo");  

  74.             mCallBack = icallback;  

  75.             mCallBack.handleByServer("The msg is from server");  

  76.             HarlanInfo newInfo = new HarlanInfo();  

  77.             newInfo.setName(info.getName().toLowerCase());  

  78.             newInfo.setAge(info.getAge() + 10);  

  79.             newInfo.setPlace("Home");  

  80.             return newInfo;  

  81.         }  

  82.     };  

  83.       

  84. }  

一目了然,服务端主要的功能就是实现了aidl中的getServerHarlanInfo(HarlanInfo info, ICallBack icallback)接口.返回了一个mBinder供客户端调用.

写好了服务,还得在Manifest文件里面配置一下:

[java] view plaincopyprint?

  1.            android:name=".AIDLService">  

  2.              

  3.                  

  4.              

  5. lt;/service>  

 

服务端写好了,就来客户端的了.客户端主要是一个activity,界面相对简单,如图所示:

Android  service通过aidl  回调客户端 daemon

界面布局相对简单,就不贴代码了.

 

下面贴ClientActivity的代码:

[java] view plaincopyprint?

  1. package com.harlan.demo.activity;  

  2.   

  3. import android.app.Activity;  

  4. import android.content.ComponentName;  

  5. import android.content.Intent;  

  6. import android.content.ServiceConnection;  

  7. import android.os.Bundle;  

  8. import android.os.IBinder;  

  9. import android.os.RemoteException;  

  10. import android.util.Log;  

  11. import android.view.View;  

  12. import android.widget.Button;  

  13. import android.widget.EditText;  

  14. import android.widget.Toast;  

  15.   

  16. import com.harlan.demo.aidl.ExecuteServiceAIDL;  

  17. import com.harlan.demo.aidl.HarlanInfo;  

  18. import com.harlan.demo.aidl.ICallBack;  

  19.   

  20. public class ClientActivity extends Activity  

  21. {  

  22.     public static final String TAG = "ClientActivity";  

  23.       

  24.     private static final String BIND_ACTION = "com.harlan.demo.aidl.service";  

  25.       

  26.     private EditText mEditTextName;  

  27.       

  28.     private EditText mEditTextAge;  

  29.       

  30.     private EditText mEditTextPlace;  

  31.       

  32.     private Button mButtonCommit;  

  33.       

  34.     private ExecuteServiceAIDL executeService;  

  35.       

  36.     @Override  

  37.     protected void onCreate(Bundle savedInstanceState)  

  38.     {  

  39.         super.onCreate(savedInstanceState);  

  40.         setContentView(R.layout.activity_client);  

  41.         getView();  

  42.     //用户点击提交按钮,将数据传至服务端进行处理    

  43.          mButtonCommit.setOnClickListener(new View.OnClickListener()  

  44.         {  

  45.               

  46.             @Override  

  47.             public void onClick(View v)  

  48.             {  

  49.         //绑定服务  

  50.                 getServiceConnect();               

  51.             }  

  52.         });  

  53.     }  

  54.           

  55.     private void getView()  

  56.     {  

  57.         mEditTextName = (EditText)findViewById(R.id.editText_name);  

  58.         mEditTextAge = (EditText)findViewById(R.id.editText_age);  

  59.         mEditTextPlace = (EditText)findViewById(R.id.editText_place);  

  60.         mButtonCommit = (Button)findViewById(R.id.button_commit);  

  61.     }  

  62.       

  63.     private void getServiceConnect()  

  64.     {  

  65.         Intent it = new Intent();  

  66.         it.setAction(BIND_ACTION);  

  67.         startService(it);  

  68.         bindService(it, mserviceConnection, BIND_AUTO_CREATE);  

  69.     }  

  70.       

  71.     ServiceConnection mserviceConnection = new ServiceConnection()  

  72.     {  

  73.           

  74.         @Override  

  75.         public void onServiceDisconnected(ComponentName name)  

  76.         {  

  77.             Log.d(TAG, "onServiceDisconnected");             

  78.         }  

  79.           

  80.         @Override  

  81.         public void onServiceConnected(ComponentName name, IBinder service)  

  82.         {  

  83.             Log.d(TAG, "onServiceConnected");  

  84.             //获取服务端传过来的IBinder对象,通过该对象调用服务端的方法  

  85.               executeService = ExecuteServiceAIDL.Stub.asInterface(service);  

  86.             if (executeService != null)  

  87.             {  

  88.                 handlerInfo();  

  89.             }  

  90.         }  

  91.     };  

  92.       

  93.     private void handlerInfo()  

  94.     {  

  95.         String mName;  

  96.         int mAge;  

  97.         String mPlace;  

  98.         if (mEditTextName.getText().toString().equals(""))  

  99.         {  

  100.             mEditTextName.setText("Harlan");  

  101.             mName = "Harlan";  

  102.         }  

  103.         else  

  104.         {  

  105.             mName = mEditTextName.getText().toString();  

  106.         }  

  107.         if (mEditTextAge.getText().toString().equals(""))  

  108.         {  

  109.             mAge = 22;  

  110.         }  

  111.         else  

  112.         {  

  113.             mAge = Integer.parseInt(mEditTextAge.getText().toString());  

  114.         }  

  115.         if (mEditTextPlace.getText().toString().equals(""))  

  116.         {  

  117.             mPlace = "Nanjing";  

  118.         }  

  119.         else  

  120.         {  

  121.             mPlace = mEditTextPlace.getText().toString();  

  122.         }  

  123.         HarlanInfo mInfo = new HarlanInfo();  

  124.         mInfo.setName(mName);  

  125.         mInfo.setAge(mAge);  

  126.         mInfo.setPlace(mPlace);  

  127.         try  

  128.         {  

  129.             HarlanInfo serverInfo = new HarlanInfo();  

  130.        //调用服务端的方法  

  131.               serverInfo = executeService.getServerHarlanInfo(mInfo, mCallBack);  

  132.             //更新界面  

  133.               mEditTextName.setText(serverInfo.getName());  

  134.             mEditTextAge.setText(String.valueOf(serverInfo.getAge()));  

  135.             mEditTextPlace.setText(serverInfo.getPlace());  

  136.             unbindService(mserviceConnection);  

  137.         }  

  138.         catch (RemoteException e)  

  139.         {  

  140.             e.printStackTrace();  

  141.         }  

  142.     }  

  143.     ICallBack.Stub mCallBack = new ICallBack.Stub()  

  144.     {  

  145.        //客户端回调方法的具体实现  

  146.         @Override  

  147.         public void handleByServer(String param)  

  148.             throws RemoteException  

  149.         {  

  150.             Toast.makeText(getApplicationContext(), param, Toast.LENGTH_LONG).show();            

  151.         }  

  152.     };  

  153.      

  154. }  

服务端调用客户端回调方法,在界面上显示一个toast.客户端根据服务端传回来的数据,刷新界面. 

最后运行结果如图所示:

Android  service通过aidl  回调客户端 daemon

 

 

具体的Demo已经上传至CSDN,下载地址:http://download.csdn.net/detail/singleton1900/4928804


本文名称:Androidservice通过aidl回调客户端daemon
网页网址:http://scyanting.com/article/jeioep.html