AIDL的使用案例

参考《Android开发艺术探索》

我的测试环境是在两个app下,当然也可以在同一个app中的两个进程。

记录这篇文章,是为了不忘记使用aidl,因为在项目中用的比较少。

IPC通信 : AIDL、 Bundle、Message 、 Contentprovider、文件共享,socket。

首先我们先创建客户端的代码。

客户端 :

如果需要传输自定义的对象

自定义对象的传递需要序列化所以要实现 Parcelable 。

public class Book implements Parcelable 

然后需要在和mian中的同级下创建一个aidl的包

其中的包名结构要和java代码的结构一致。

在创建Book类的时候 需要同时创建一个Book的aidl文件(包名一致)(创建的时候可能会让你在aidl名字前加I,没关系,创建后修改就好 。因为aidl文件要和Book 文件名 一致)

同时我也创建了IBooKAidlInterface, 和 IBookListener 类

需要注意的是 当你运用 自定义对象传递的时候 , 你需要import 它, 同时需要加上参数

In、out、inout 中的一个 ,具体选择 要看你的需求( 要好好选择 因为他的开销还是蛮大的)。

同时写了一个监听器来监听数据的变化

Ok,到这里创建了所需要的AIDL文件。

然后可以去Make Project 你的项目。会在build下生成一个文件,就可以用这个文件来操作拉。

然后在 客户端的Activity中去绑定服务(要是bindService~):如果不是在同一个app下 可以这样去bind它:

申请aidl的监听器:

(需要注意的是  在 onAddBooks 中 的动作 其实是在Binder池中的,不是在主线程中的,所以如果需要操作UI的话 需要handler出去)

在获取到binder的时候 我注册了 监听器 和绑定了bind的死亡,为什么这样做呢 , 是为了防止 bind死亡的时候,我们不知道 然后继续去操作导致异常 ,当使用linkToDeath去绑定binder的时候,只要bind死亡了 会通知我们 。

然后实现下面的方法:

实现监听器之后,记得在退出的时候 注销他。

同时还有需要注意的是:

当你调用某个方法的时候,你要特别小心他可能会造成阻塞,因为服务端的代码可能需要比较长的时间来完成,如果你在UI线程中去调用他,会造成ANR 。 所以尽量在子线程中调用。

Ok ,接下来就是服务端了:

首先 要将 客户端的aidl整个结构原封不动的复制过来。同时自定义的对象也要在一个和客户端同样的包名下。

Make 一下  也会生成 和客户端同样的代码。

然后绑定Service后返回binder 对象:

IBinder binder = new IBooKAidlInterface.Stub() {

        @Override
        public void addBook(Book book) throws RemoteException {
         
           lists.add(book);
            onAddBook(book );
        }

        @Override
        public List<Book> getBooks() throws RemoteException {
         
            return lists ;
        }

        @Override
        public void registerListener(IBookListener listener) throws RemoteException {
            callbackList.register(listener);
        }

        @Override
        public void unregisterListener(IBookListener listener) throws RemoteException {
            callbackList.unregister( listener );
        }
    };

在registerListener中 有一个list 去 register他。

这个list 是 ,这个类是特意为aidl的监听使用的

 private RemoteCallbackList<IBookListener> callbackList = new RemoteCallbackList<>();

但是 这个list的调用 需要如下:

 private void onAddBook(Book book){
       int size =  callbackList.beginBroadcast() ;
       for (int i = 0; i< size ; i++){
           try {
               callbackList.getBroadcastItem(i).onAddBooks(book);
           } catch (RemoteException e) {
               e.printStackTrace();
           }
       }
       callbackList.finishBroadcast();
    }

现在只要你在onBind中 返回binder 对象 ,让客户端连接上服务端 就可以进行通信了。

但是 服务端不能谁来连接都运行把。所以我们可以设置权限验证。

首先

要设置 权限:

 

然后在客户端:

 <uses-permission android:name="com.austin.aidlserver" />

在Service中进行验证:

  1. 在onBind中验证
 @Nullable
    @Override
    public IBinder onBind(Intent intent) {

       int i =  checkCallingOrSelfPermission("com.austin.aidlserver");
       if (i  == PackageManager.PERMISSION_DENIED){
           return null ;
       }
        return binder;
    }

    2.在 onTransact中验证:

@Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            // 在这里权限验证
            int check = checkCallingOrSelfPermission("com.austin.aidlserver");
            if(check==PackageManager.PERMISSION_DENIED){
                return false;
            }
            // 包名验证
            String packageName=null;
            String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
            if(packages!=null && packages.length>0){
                packageName = packages[0];
            }
            if(!packageName.startsWith("com.austin")){
                return false;

            }
            return super.onTransact(code, data, reply, flags);
        }

 

Ok  这样就大功告成了~~

其实里面还有很多有意思的原理 可以去探索,这里我都没有写出来,比如为什么要用RemoteCallbackList等,如果感兴趣的话,可以自己去探索一下啦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用程序中使用 AIDL,您需要执行以下步骤: 1. 创建 AIDL 接口文件 AIDL 接口文件定义了客户端和服务端之间的通信接口。在在 Android Studio 的 app 目录下创建一个名为 aidl 的文件夹,然后在该文件夹下创建一个 .aidl 文件。例如,我们可以创建一个名为 IMyAidlInterface.aidl 的文件。 2. 定义 AIDL 接口 在 IMyAidlInterface.aidl 文件中,我们可以定义客户端和服务端之间需要交换的数据类型和方法。例如: ``` // IMyAidlInterface.aidl package com.example.myaidl; // Declare any non-default types here with import statements interface IMyAidlInterface { int add(int a, int b); } ``` 在上面的例子中,我们定义了一个名为 IMyAidlInterface 的接口,该接口包含一个 add(int a, int b) 方法,用于计算两个整数的和。 3. 实现 AIDL 接口 在服务端应用程序中,我们需要实现上述定义的 AIDL 接口。在服务端应用程序的 Java 代码中,我们需要实现 IMyAidlInterface.Stub 类,它是一个抽象类,继承自 Binder 类。在 IMyAidlInterface.Stub 类中,我们需要实现 add(int a, int b) 方法。例如: ``` public class MyAidlService extends Service { private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public int add(int a, int b) throws RemoteException { return a + b; } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 在上面的例子中,我们实现了 add(int a, int b) 方法,该方法计算两个整数的和,并返回结果。 4. 在客户端应用程序中调用 AIDL 接口 在客户端应用程序中,我们需要绑定服务,以获取服务端的实例。然后,我们可以调用服务端的方法。例如: ``` public class MainActivity extends AppCompatActivity { private IMyAidlInterface mIMyAidlInterface; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.myaidl", "com.example.myaidl.MyAidlService")); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); int result = mIMyAidlInterface.add(1, 2); Log.d("MainActivity", "Result: " + result); } } ``` 在上面的例子中,我们绑定服务,以获取服务端的实例。然后,我们调用服务端的 add(int a, int b) 方法,计算两个整数的和,并输出结果。 以上就是使用 AIDL 在不同的应用程序之间进行通信的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值