Android 进程间通信——AIDL

AIDL(Android Interface Definition Language)——进程间通信的一种机制。它允许您定义客户端和服务端通过使用进程间通信(IPC)进行通信的编程接口。在Android上,一个进程无法正常访问另一个进程的内存。所以说,他们需要将他们的对象分解成操作系统能够理解的原语,并且把这些对象放在你的边界上。编写这些代码非常繁琐,所以Android使用AIDL来处理它。

Demo下载地址http://www.demodashi.com/demo/12321.html

1 使用AIDL的必要条件

  • 只有当你需要来自不同应用的客户端通过IPC(进程间通信)通信来访问你的服务时,并且想在服务里处理多线程的业务,这时就需要使用AIDL。
  • 如果你不需要同时对几个应用进程IPC操作,你最好通过实现Binder接口来创建你的接口。
  • 如果你仍需要执行IPC操作,但不需要处理多线程,使用Messenger来实现接口即可。

2 AIDL的使用

使用Java编程语言语法在.aidl文件中定义您的AIDL接口,然后将其保存在承载服务的应用程序和任何其他绑定到该服务的应用程序的源代码(在src /目录中)。
当应用程序构建包含.aidl文件时,Android SDK工具将生成一个基于.aidl文件的IBinder接口,并将其保存在项目的gen /目录中。 该服务必须适当地实现IBinder接口。 然后,客户端应用程序可以绑定到服务并从IBinder调用方法来执行IPC。

使用AIDL 创建绑定的服务,具体步骤:

  1. 创建.aidl文件
    这个文件用方法签名来定义编程接口。
  2. 实现接口
    Android SDK工具根据你的.aidl文件以Java编程语言生成一个接口 。这个接口有一个名为Stub的内部抽象类,它继承了Binder并实现了AIDL接口中的方法。你必须继承这个 Stub类并实现这些方法。
  3. 将接口公开给客户端
    实现一个服务并重写onBind() 来返回你的Stub类的实现。
2.1 创建.aidl文件

AIDL使用简单的语法,可以用一个或多个方法(可以接收参数和返回值)来声明接口。参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。
必须使用Java编程语言构建.aidl文件。 每个.aidl文件都必须定义一个接口,并且只需要接口声明和方法签名。

默认情况下,AIDL支持以下数据类型:

  • Java编程语言中的所有基本类型(如int,long,char,boolean等)
  • String
  • CharSequence
  • List
    List中的所有元素都必须是支持的数据类型之一,或者是您声明的其他AIDL生成的接口或可接受的元素之一。 列表可以选择性地用作“通用”类(例如List )。 对方收到的实际具体类始终是一个ArrayList,尽管生成的方法是使用List接口。
  • Map
    Map中的所有元素都必须是此列表中受支持的数据类型之一,或者是您声明的其他AIDL生成的接口或可接受元素之一。 通用映射(如Map <String,Integer>形式的映射)不被支持。对方接收的实际具体类总是一个HashMap,尽管该方法是使用Map接口生成的。

对于上面没有列出的每种附加类型,即使它们在与接口相同的包中定义,也必须包含一条import语句。

在定义服务接口时,注意:

  • 方法可以采用零个或多个参数,并返回一个值或void。
  • 所有非原始参数都需要一个指向数据的方向标签。in,out或者inout(见下面的例子)。基本数据默认是in的,不能以其他方式。
    警告:您应该将方向限制在真正需要的地方,因为编组参数非常昂贵。
  • 包含在.aidl文件中的所有代码注释都包含在生成的IBinder接口中(导入和包装语句之前的注释除外)。
  • 只支持方法; 您不能在AIDL中公开静态字段。

如下是一个.aidl 例子。IRemoteService.aidl

package com.zpengyong.aidl;

interface IRemoteService {
   
    void sendMessage(in String str);

    boolean play();

    boolean pause();

    boolean stop();
}

只需将.aidl文件保存在项目src/目录中,SDK工具会在项目gen/目录中生成IBinder接口文件。生成的文件名与.aidl文件名相匹配,但带有.java扩展名(例如IRemoteService.aidl结果IRemoteService.java)。

2.2 实现接口

IRemoteService.java接口文件包含一个名为Stub的类 ,它继承了Binder ,实现了IRemoteService接口,并声明.aidl文件中的所有方法。
Stub还定义了一些辅助方法,最值得注意的是asInterface(),它接受一个IBinder(通常是传递给客户端的onServiceConnected()回调方法中的参数),并返回stub接口的一个实例。

要实现从.aidl生成的接口,请继承生成的Binder接口(例如IRemoteService.Stub),并实现从.aidl文件继承的方法。
下面是示例:

private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){  
    public void sendMessage(String str){
        Log.i(TAG,"message str:"+str +",thread:"+Thread.currentThread());
        Message msg = new Message();
        msg.what = MSG_RECEIVE_MESSAGE;
        msg.obj = str;
        mHandler.sendMessage(msg);
    }

    public boolean play(){
        mService.play();
        return true;
    }

    public boolean pause(){
        mService.pause();
        return true;
    }

    public boolean stop(){
        mService.stop();
        return true;
    }
};

现在mBinder是Stub类的一个实例(一个Binder),它定义了服务的RPC接口。 在下一步中,这个实例被暴露给客户,以便他们可以与服务交互。

在实现AIDL接口时,您应该注意一些规则

  • 传入的调用并不保证在主线程中执行,所以需要从头开始考虑多线程,并将服务正确地构建为线程安全的。
  • 默认情况下,RPC调用是同步的。如果您知道该服务需要超过几毫秒才能完成请求,则不应该从活动的主线程调用该服务,因为它可能会挂起应用程序(Android可能会显示“应用程序不响应”对话框,应该通常从客户端的一个单独的线程调用它们。
  • 抛出的任何异常都将被发回给调用者。
2.3 将接口公开给客户端

为了暴露你的服务的接口,扩展Service并实现onBind()返回实现生成的Stub的类的实例。 这里是一个示例服务,将IRemoteService示例接口公开给客户端。

public class 
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的AIDLAndroid Interface Definition Language)是一种用于进程通信的机制,它允许在不同进程中的组件之进行通信AIDL是一个基于接口的编程语言,它定义了一组方法,这些方法可以被其他进程中的组件调用。 AIDL的使用步骤如下: 1.定义AIDL接口:定义接口和方法,并在方法中指定参数和返回值类型。 2.实现AIDL接口:实现AIDL接口中定义的方法。 3.注册AIDL服务:在AndroidManifest.xml文件中注册服务。 4.使用AIDL服务:获取AIDL对象并调用方法。 下面是一个简单的例子,演示如何使用AIDL进行进程通信。 1.定义AIDL接口 ``` interface IMyAidlInterface { void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); } ``` 2.实现AIDL接口 ``` public class MyAidlService extends Service { private static final String TAG = "MyAidlService"; private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Log.d(TAG, "basicTypes: " + anInt + ", " + aLong + ", " + aBoolean + ", " + aFloat + ", " + aDouble + ", " + aString); } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 3.注册AIDL服务 在AndroidManifest.xml文件中添加以下代码: ``` <service android:name=".MyAidlService" android:exported="true"> <intent-filter> <action android:name="com.example.MyAidlService" /> </intent-filter> </service> ``` 4.使用AIDL服务 ``` public class MainActivity extends AppCompatActivity { private IMyAidlInterface mService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(); intent.setAction("com.example.MyAidlService"); intent.setPackage("com.example"); bindService(intent, mConnection, BIND_AUTO_CREATE); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mService = IMyAidlInterface.Stub.asInterface(iBinder); try { mService.basicTypes(1, 2L, true, 3.0f, 4.0, "Hello, AIDL!"); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { mService = null; } }; } ``` 在上面的代码中,我们首先创建一个Intent对象,指定要绑定的服务的包名和类名。然后调用bindService()方法绑定服务,并在onServiceConnected()方法中获取AIDL对象,调用basicTypes()方法向服务传递参数。最后,在onServiceDisconnected()方法中释放AIDL对象。 以上就是使用AIDL进行进程通信的基本步骤。需要注意的是,在使用AIDL时,必须确保服务已经启动,并且在AndroidManifest.xml文件中注册了服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值