AIDL——你的应用不孤单

今天聊聊AIDL,Android Interface Definition Language(安卓接口定义语言),即安卓进程间通信。

首先我们知道,狭义来说,一个应用对应一个进程。而如果想跨应用交互,那就涉及到进程间通信,而安卓四大组件都代表一种进程间通信的方式。

但是我们今天说的AIDL,则是通过Service,为什么选择聊Service呢 ?其一 ,因为它的自定义程度最高。其二 ,Service的优先级高。

我们简单理一下思路 。使用AIDL作为进程间通信的方式,那也就是说,我们需要至少两个应用,一个作通信的服务端,一个作通信的客户端。(当然,可以有不止一个客户端,也可以有不止一个服务端)。

那客户端与服务端如何跨进程通信呢 ?这就需要它们有一个共同的通信标准,就是AIDL,姑且理解为一种协议,服务端和客户端各自定义好一摸一样的协议(包括包名/类名/方法名) ,然后服务端提供具体的实现,客户端执行调用。

比如 :客户端通过服务端提供的XX方法 得到了XX结果。

听上去很像接口,有没有?其实个人愚见也是如此,因为接口是一个翻泛概念,你给我提供一个途径,我通过这个途径把参数给你,你处理后把结果给我。符合该模式的,我觉得都可以归为接口。


以下做一个简单的示例,(我们今天不谈IBinder,如果你想更深刻的理解 AIDL,建议还是去认真揣摩揣摩IBinder)

示例的服务端提供一个接口IMyLog ,里面有一个方法sysOut,接受一个String参数,并Log出来。客户端则是去绑定服务端,并调用IMyLog接口的这个方法,传入参数,让其执行。

步骤分为两部份:

第一部分:服务端:

1.首先创建一个文件夹,在其中定义一个AIDL类,如图:

这里写图片描述

注意,这里是AS,所以生成AIDL文件夹的方式不太一样。如果是Eclipse,直接在java路径下生成就好。

2.创建一个Service类:

public class MainService extends Service {

    private IBinder iBinder = new IMyLog.Stub(){

        @Override
        public void sysOut(String content) throws RemoteException {
            Log.i("aidl","service get " + content);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("aidl","service create");
    }
}

第二部分:客户端:
1.首先创建一个文件夹,在其中定义一个AIDL类,如图:

这里写图片描述

注意:这个AIDL类必须和服务端的AIDL一摸一样,包括文件夹路径。

2.创建一个客户端Activity:

public class MainActivity extends AppCompatActivity {

    private  IMyLog iMyLog;

    //ServiceConnection,在绑定成功时返回AIDL的接口IMyLog
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("aidl","conn is success");
            iMyLog = IMyLog.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("aidl","disconn is success");
            iMyLog = null;
        }
    };

    @Override
    protected void onDestroy() {
        Log.i("aidl","on Destroy");
        unbindService(conn);
        super.onDestroy();
    }

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

        doBind();
    }

    //隐式Intent绑定服务端Service,获得ServiceConnection
    private void doBind() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.lebang.myservice","com.lebang.myservice.MainService"));
        bindService(intent,conn, Context.BIND_AUTO_CREATE);
    }

    //Button的点击事件,点击时调用服务端AIDL方法,传入参数“today I ...”
    public void doThing (View view){
        Log.i("aidl","client send message");
        try {
            iMyLog.sysOut(": today I do the aidl");
        } catch (RemoteException e) {
            e.printStackTrace();
            Log.i("aidl","client error");
        }
    }
}

然后启动模拟器,先确保安装上服务端程序,再执行客户端程序。点击Button,会发现,在服务端程序的Log下会打印出:

service get : today I do the aidl
最末,做个简单介绍,如果你发现如上操作会崩溃,原因可能是Manifest文件中未配置可通信。解决方法有两种:
1.在客户端服务端Manifest主标签下配置属性 sharedUserId :
     如: android:sharedUserId="com.lebang"
2.在服务端Service中配置属性:如:
   <service
            android:name=".MainService"
            android:exported="true"/>

抽时间写的,没有整理好语言,谬误之处,欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值