首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

android aidl iBinder懂得

2012-09-04 
android aidl iBinder理解在android中有一个程序员大量使用的操作,就是bindservice,通过一个service可以实

android aidl iBinder理解

在android中有一个程序员大量使用的操作,就是bindservice,通过一个service可以实现代码的复用以及解耦,所以对这个bindservice的理解的深度直接影响了一个开发人员对于android系统开发的整体的掌握情况。vRD平坦软件园
vRD平坦软件园
??? 好啦,废话不多说,首先我们来看一个我开发过程中遇到的例子。vRD平坦软件园
vRD平坦软件园
??? 在开发中我们常常要用到这们一种情况,我们的UI逻辑和为UI逻辑提供服务的一些算法的是需要解耦的。这样,当我们UI和算法各自独立发生变化的时候,只要接口没有改变,对于UI的开发人员和算法的开发人员来将,就可以不去考虑,这个对与开发的好处,我想不用多说了。vRD平坦软件园
vRD平坦软件园
??? Android的Service是基于IBinder的, IBinder其实就是windows上的com,这个以后我会有详细的文章来解释。vRD平坦软件园
vRD平坦软件园
??? 要使用service首先要通过AndroidMainifest.xml注册,这样在安装你的包的时候,系统就会识别出你所编写的serice,这样就可以提供给别的应用使用了。vRD平坦软件园
vRD平坦软件园
??? 一个典型service的AndroidMainifest.xml如下:vRD平坦软件园
vRD平坦软件园
?????????? <service android:name="your_service_name"vRD平坦软件园
??????????????? android:exported="true"vRD平坦软件园
??????????????? android:process="your_service_process_name">vRD平坦软件园
??????????????? <intent-filter>vRD平坦软件园
??????????????????? <action android:name="intent_string_to_start_your_service" />vRD平坦软件园
??????????????????? <category android:name="android.intent.category.DEFAULT" />vRD平坦软件园
??????????????? </intent-filter>vRD平坦软件园
??????????? </service>vRD平坦软件园
vRD平坦软件园
??? 这个service域要放在xml文件的application域中,其中android:name的意思是你的service的名字,可以是你想要的任意的字符串。android:process是当这个service被你的调用启动起来以后在系统中进程的名字。如果这个域没有写,那么默认的启动的是local的service,就是将service放到本地进程的主线程中,如何你之定了一个进程的名字,那么系统就会启动一个独立的进程作为你的服务,在shell中,通过ps就可以看到这个进程的名字。action android:name的意思是说那个Intent会启动这个service。vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?? 在添加了xml文件以后,就是正式的开写java的代码了。vRD平坦软件园
vRD平坦软件园
?? 首先,要创建一个aidl文件,熟悉windows上com的同志,看到这个名字都会会心的一笑,因为这个和windows上的midl是一样的,估计就是一帮搞windows的人被google挖走了。android和根据这个aidl自动的声称一个infterface的文件做为service的接口文件。vRD平坦软件园
vRD平坦软件园
?? 这里我提供一个例子:vRD平坦软件园
vRD平坦软件园
?? package com.motorola.inputmethod.base;vRD平坦软件园
vRD平坦软件园
?? interface IYourAidl {vRD平坦软件园
????? int A(int i, in int[] j, out int[] k );vRD平坦软件园
????? int B(int i, in int[] j, out int[] k );vRD平坦软件园
? }vRD平坦软件园
vRD平坦软件园
? 在这里我们要注意的是你所定义的接口的变量的类型,android为一个他所默认的类型提供了相应的parcel服务类。如果你的参数的类型是一些 java的基本类型,或是string, arrayd等,是没有问题的,当如果参数是你自己定义的class类型,那么你就要写一个自己的parcel类了,这个以后我们还会说。还有就是,大家看如果A中的参数是int这些简单的类型的,那么没问题,如果是像int[]这样的类型的话,那么你要在类型的情面加上in 或是 out来告诉系统这个是一个输入还是输出参数。vRD平坦软件园
vRD平坦软件园
?? 在写完aidl文件以后我们在添加一个对应与aidl文件的Android.mk文件。如下:vRD平坦软件园
vRD平坦软件园
?? LOCAL_PATH:= $(call my-dir)vRD平坦软件园
?? include $(CLEAR_VARS)vRD平坦软件园
vRD平坦软件园
???? LOCAL_SRC_FILES := /vRD平坦软件园
?????????? path_to_your_aidl_file/your_test.aidlvRD平坦软件园
?????? ?vRD平坦软件园
???? LOCAL_MODULE := com.android.youraidlvRD平坦软件园
vRD平坦软件园
???? include $(BUILD_STATIC_JAVA_LIBRARY)vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?OK,在搞定aidl以后,我们开始实现一个使用这个aidl的service,其实一个service可以还有任何一个对象,不一定要含有aidl的,这里我们只是使用了aidl作为service的一个对象,其实service是service,aidl是aidl,这个希望大家能够理解。vRD平坦软件园
vRD平坦软件园
? 一个service如下:vRD平坦软件园
vRD平坦软件园
? import android.app.Service;vRD平坦软件园
vRD平坦软件园
? import path_to_your_aidl_file.IYourAidl;vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
? public class your_service_name extends Service {vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
????? public void onCreate() {vRD平坦软件园
??????? super.onCreate();vRD平坦软件园
vRD平坦软件园
??????? log.d("service onCreate")vRD平坦软件园
vRD平坦软件园
????? }vRD平坦软件园
vRD平坦软件园
?vRD平坦软件园
vRD平坦软件园
????? public void onDestroy() {vRD平坦软件园
vRD平坦软件园
??????? super.onDestroy();vRD平坦软件园
vRD平坦软件园
??????? log.d("service onDestroy")vRD平坦软件园
vRD平坦软件园
????? }vRD平坦软件园
vRD平坦软件园
??? ?vRD平坦软件园
vRD平坦软件园
????? private final IYourAidl.Stub mBinder = new IYourAidl.Stub(){vRD平坦软件园
vRD平坦软件园
???????? public int A(int i, in int[] j, out int[] k ){vRD平坦软件园
vRD平坦软件园
??????????? log.d("aidl implimention do something in A");vRD平坦软件园
vRD平坦软件园
???????? }vRD平坦软件园
vRD平坦软件园
???????? public int B(int i, in int[] j, out int[] k ){vRD平坦软件园
vRD平坦软件园
?????????? log.d("aidl implimention do something in B");vRD平坦软件园
vRD平坦软件园
???????? }vRD平坦软件园
vRD平坦软件园
????? }vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
????? public IBinder onBind(Intent intent) {vRD平坦软件园
??????? return mBinder;vRD平坦软件园
????? }vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?? }vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?? 在你实现的service中,首先要保证你的service的名字和AndroidMainifest.xml中的android:name的名字是一样的。然后,在你的service中要实现onCreate和onDestroy两个接口,onBind操作返回的是一个IBinder的子类,在这里我们返回的是aidl的一个实现。在你启动一个service的时候,service首先调用onCreate然后调用onBind返回service本地的一个对象。vRD平坦软件园
vRD平坦软件园
?? 在service中,引为aidl是一个抽象类,所以我们要提供一分基于该接口的实现。vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?? 好了,现在service这边就准备好了,当你的service被安装到系统以后,一个客户端就可启动他了。 启动代码如下:vRD平坦软件园
vRD平坦软件园
?? import android.content.ServiceConnection;vRD平坦软件园
vRD平坦软件园
?? import path_to_your_aidl_file.IYourAidl;vRD平坦软件园
vRD平坦软件园
?? import your_service_name;vRD平坦软件园
?? .............vRD平坦软件园
vRD平坦软件园
? vRD平坦软件园
vRD平坦软件园
?????????? private IYourAidl mAidl;vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?????????? private class YourServiceConnection implements ServiceConnection {vRD平坦软件园
????????? ?vRD平坦软件园
??????????? public void onServiceConnected(ComponentName name, IBinder service) {vRD平坦软件园
??????????????? mAidl = IYourAidl.Stub.asInterface(service);vRD平坦软件园
??????????? }vRD平坦软件园
? ?vRD平坦软件园
??????????? public void onServiceDisconnected(ComponentName name) {}vRD平坦软件园
??????? }vRD平坦软件园
? ?vRD平坦软件园
????? private YourServiceConnection mServiceConnection;vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
????? public? boolean startService(){vRD平坦软件园
????????? if (null == mAidl) {vRD平坦软件园
????????????? Intent serviceIntent = new Intent("intent_string_to_start_your_service");vRD平坦软件园
vRD平坦软件园
????????????? if (null == mServiceConnection) {vRD平坦软件园
????????????????? mServiceConnection =vRD平坦软件园
????????????????????? new YourServiceConnection();vRD平坦软件园
????????????? }vRD平坦软件园
vRD平坦软件园
????????????? // Bind servicevRD平坦软件园
????????????? if (bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE)) {vRD平坦软件园
????????????????? return true;vRD平坦软件园
????????????? } else {vRD平坦软件园
????????????????? return false;vRD平坦软件园
????????????? }vRD平坦软件园
????????? }vRD平坦软件园
????????? return true;vRD平坦软件园
????? }vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
????? 当客户端调用startService的时候,最忠会调用bindService, 他的第一个参数是一个intent就是和xml文件相同的Intent名字的一个intent。第二个参数是一个ServiceConnection对象,作为回调函数, Context.BIND_AUTO_CREATE表示的是自动绑定。vRD平坦软件园
vRD平坦软件园
????? 在用户调用bindservice以后,系统会检查是否有符合Intent的service,如果有的话就创建了,如果没有的话,就创建一个新的 service,并调用service的onCreate接口。同时如果制定了ServiceConnection对象和 BIND_AUTO_CREATE参数,那么就会调用service的onBind接口,onBind接口返回的IBinder对象传个 ServiceConnection的onServiceConnected的第二个参数,在onServiceConnected中通过mAidl = IYourAidl.Stub.asInterface(service);将远程的一个变量和本地的一个变量绑定。从而实现了RPC调用,这样,用户进程就是可以像使用本地变量一样通过PRC调用远程的操作了。BindService操作是一个异步的操作,所以什么时候能调用 onServiceConnected是不一定的,如果在用户进程中bindservice以后直接使用mAidl而没有判断的话,很可能会有错误。vRD平坦软件园
vRD平坦软件园
??? 同时如果通过mAidl调用远程操作的话,需要将操作包含在????????????? ?vRD平坦软件园
vRD平坦软件园
?????????????? try{vRD平坦软件园
??????????????????? mAidl.A(.....)vRD平坦软件园
??????????????? }vRD平坦软件园
??????????????? catch(RemoteException e) {vRD平坦软件园
??????????????????? Log.e("error", e.getMessage());vRD平坦软件园
??????????????? }vRD平坦软件园
vRD平坦软件园
???? 中vRD平坦软件园
vRD平坦软件园
vRD平坦软件园
?? 以上是我对service使用的一个例子,其实在Service背后支持着他的是IBinder的IPC机制,这个我会专门用文章来讲。

热点排行