Service进程间通信AIDL

AIDL是Android Interface Definition Language的缩写,意思就是安卓接口定义语言。

IPC是Interprocess Communication的缩写,意思就是进程间通信。

类似于其他你使用过的接口定义语言,AIDL允许你使用接口来实现客户端和服务端的进程通信(IPC)。

在Android系统中,一个进程是不能访问另一个进程的内存的,也就是无法数据或方法共用。所以,我们要把对象分解为系统可以识别的原始数据,从而达到数据共通。而这个代码的编写是非常枯燥和麻烦的。所以Android系统中我们使用AIDL来实现!

注意:如果你要使多个客户端访问服务或者要在服务中使用多线程,那么使用AIDL是必要的。如果你不需要在不同的应用之间执行并发的IPC,那么是用Binder的方式就够了。或者你需要实现IPC,但是不需要用到多线程,那么使用Messenger的方式就可以实现进程通信了。不管怎样,在使用AIDL之前,你最好已经明白绑定服务的具体作用和含义!

在你开始设计你的AIDL接口前,注意调用AIDL接口使用的函数。你不应该对调用发生的线程做假设。所发生的不同取决于调用是从本地进程或远程进程中的线程的,例如abc:

a.本地进程中的调用是在同一个线程中执行的。如果这是你的主线程,该线程在AIDL接口中继续执行。如果是另一个线程,那就是在服务中执行你的代码。因此,如果只有本地线程访问服务,你可以完全是用绑定服务的方式来实现就可以了!

b.从一个远程线程池中调用方法到你自己的进程中。您必须为来自未知线程的数据同步做准备,同时可能发生在同一时间发生多个回调。意思就是,AIDL接口的实现必须是线程安全的。

c.当调用远程的数据时,如果远程服务并没有阻塞,它仅仅发送数据并立即返回,接口的实现就将定期收到数据,类似于通过远程服务得到Binder对象!如果只是单独的使用本地数据,就没有关系,数据是同步的。


1.定义一个AIDL接口

a.AS创建一个服务端项目(modle)并新建一个.aidl的文件


AS会创建相应目录并生成一个AIDL文件,在文件中我们写上自己需要的方法,类似于普通接口



b.然后我们需要使用Build菜单的Make Project,这个操作千万不要忘记,用于创建aidl相关的java文件。但是在AS的目录中你是找不到这个java文件的,因为它隐藏项目构建的debug目录中,安装使用的时候才会添加进去,所以你每修改一次aidl,就需要make project一下!


c.创建一个Service服务,实例化aidl并具体实现其中的方法,通过它的Stub()方法得到stub对象(myBinder),最后在service的onBind()方法中返回它就可以与客户端建立联系了。


d.最后,还需要在AndroidManifest.xml中配置service



2.在客户端建立AIDL进行通信

a.我们新建一个项目(modle),并把Service中建立的aidl文件连同包都复制过来


b.少不了的,客户端也需要Make Project

c.在客户端的一个Activity中,绑定远程服务,注意setPackage就是服务端apk文件的包名


d.最后,在建立连接的方法中得到IBinder对象,通过它实例化aidl,就可以调用其方法了

package cq.cake.service.client;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cq.cake.servicetest.IMyAidlInterface;

public class MainActivity extends AppCompatActivity {
    public static boolean mBind = false;
    @Bind(R.id.tv_text)
    TextView tvText;

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

    @OnClick(R.id.btn_bindservice)
    public void doClick(View view) {
        Log.d("TAG", "点击了绑定 ");
        //.首先要绑定服务,这里的Intent参数就是服务端AndroidManifest.xml中配置的action名称
        Intent intent = new Intent("cq.cake.servicetest.MyAIDL_ACTION");
        intent.setPackage("cq.cake.servicetest");
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                int result = iMyAidlInterface.plus(50, 50);
                String upperStr = iMyAidlInterface.toUpperCase("comes from ClientTest");
                tvText.setText("调用远程服务运行方法后" + "\n" + "50+50 =  " + result + "\n"
                        + "comes from ClientTest 转换大写为 " + "\n" + upperStr);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

            mBind = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBind = false;
        }
    };
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("TAG", "onDestroy ");
        if (mBind) {
            unbindService(connection);
            mBind = false;
        }
    }



}

3.实践:安装服务端,安装客户端。服务端就算没有启动,我们也可以通过客户端来调用服务端的方法。并且多个客户端共用此服务的方法!




到此关于AIDL进程间通信就介绍完成了,还有不明白的同学可以去看看官方文档:

https://developer.android.com/guide/components/aidl.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值