android跨应用aidl通讯

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wode_dream/article/details/55518535

AIDL定义:可以定义客户端跟服务使用进程间通信(IPC)进行相互通信时都认可的编程接口。

AIDL用途:将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。

AIDL使用环境:允许不同应用的客户端用IPC方式访问服务,并且想要在服务中处理多线程时。

不需要AIDL的情况:[1].使用Binder:不需要执行跨越不同应用的并发IPC,就应该通过实现一个Binder创建接口;[2].使用Messenger类:想执行IPC,但根本不需要处理多线程,则使用Message类来实现接口。

我们把aidl通讯分两部分讲解,第一部分是activity访问其它应用的service,第二部分是service访问activity。之所以这样讲解是因为我在刚接触aidl的时候比较容易混淆。

第一部分:下面的例子是AIDLClientDemo应用通过aidl访问AIDLServiceDemo应用中的service

一、先建立mylibrary module

1AIDLDemo工程下创建一个Library module,然后在src/main下创建aidl文件夹(跟java文件夹同一层级);

2、在aidl文件夹下创建IConnectClientInterface.aidl文件,代码如下:

interface IConnectClientInterface {


    int getServiceValue();
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

建立完这个文件后运行下gradle系统会自动在build/generated/source/aidl/debug/包名/这个目录下生成IConnectClientInterface.java文件。

对于每一个.aidl文件系统都会生成一个基于.aidl文件的IBinder接口(这里是IConnectClientInterface.java)。每个服务根据自己的情况实现IBinder接口。客户端应用绑定到该服务,并调用IBinder中的方法来执行IPC。

二、第二步建立aidlservicedemo module,并且引入library module。

1、创建一个Service文件MyService.java,代码如下:

public class MyService extends Service {

	int value=1234;

    public MyService() {
    }

    private final IConnectClientInterface.Stub iConnectClientBind=new IConnectClientInterface.Stub() {
        @Override
        public int getServiceValue() throws RemoteException {
            return value;
        }

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

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

IConnectClientInterface.Stub是其父接口的抽象实现,用于声明.aidl文件中的所有方法。iConnectClientBindStub类的一个实例(一个Binder),用于定义服务的RPC(远程进程请求)接口。

     扩展Service并实现onBind(),返回一个IBinder实例(这里指iConnectClientBind)。

2、在AndroidManifest.xml中配置如下:

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="zfeng.com.aidldemo.MyService"></action>
    </intent-filter>
</service>

android:exported=“true”表示外部应用可以访问这个Service,这里的action起到过滤的作用。

三、建立aidlclientdemo module并且引入library module。

1、创建一个Activity文件BindingActivity.java

public class BindingOtherServiceActivity extends AppCompatActivity {

    Button btn;
    TextView textView;
    private IConnectClientInterface mService;

    private ServiceConnection mServiceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService=IConnectClientInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService=null;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_binding_other_service);

        textView=(TextView)findViewById(R.id.showAidl);
        btn=(Button)findViewById(R.id.bindServicebtn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent("zfeng.com.aidldemo.MyService");
                intent.setClassName("zfeng.com.aidlservicedemo","zfeng.com.aidlservicedemo.MyService");
                bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
            }
        });

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mService!=null){
                    textView.post(new Runnable() {
                        @Override
                        public void run() {
                            try{
                                textView.setText(mService.getServiceValue()+"value");
                            }catch (Exception e){
                                e.printStackTrace();
                            }

                        }
                    });
                }else{
                    Toast.makeText(BindingOtherService.this, "Service is not available yet!", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

现在,当BindingOtherServiceActivity调用bindService()连接MyService时,Activity的onServiceConnected()回调会接收MyService的onBind()方法返回的mBinder实例。

当客户端在onServiceConnected()回调中收到IBinder时,它必须调用YourServiceInterface.Stub.asInterface(service)以将返回的参数转换成YourServiceInterface类型。

四、运行AIDLClientDemo和AIDLServiceDemo测试。


第二部分:service主动获取另一个appactivity的值。

这个问题刚开始的时候很纠结,因为官方文档的例子中有一个CallBackaidl,所以我一直在纠结是不是Service调用CallBack来获取Activity的信息。但是我在从ActivityService中传递aidl对象(IConnectCallbackInterface)时,传入的都是空值,最后发现了问题所在,我们应该实例化Stub

代码步骤如下(文件所在位置基本与第一部分一致):

1、创建IConnectCallbackInterface.aidl,并且修改IConnectClientInterface.aidl.aidl

interface IConnectCallbackInterface {
    void putValue(int activityValue);
}

interface IConnectClientInterface {

    int getServiceValue();
    void registerConnectCallback(IConnectCallbackInterface cb);
}
2 、在 BindingOtherServiceActivity.java 中实例化 aidl ,并且在IConnectClientInterface.aidl中注册。

private IConnectCallbackInterface.Stub callbackInterface=new IConnectCallbackInterface.Stub() {
    @Override
    public void putValue(final int activityValue) throws RemoteException {
        textView.post(new Runnable() {
            @Override
            public void run() {
                textView.setText(activityValue+" from service");
            }
        });
    }

    @Override
    public IBinder asBinder() {
        return callbackInterface;
    }
};

mService.registerConnectCallback(callbackInterface);

3、在MyService.java中操作

private final IConnectClientInterface.Stub iConnectClientBind=new IConnectClientInterface.Stub() {
    @Override
    public int getServiceValue() throws RemoteException {
        return value;
    }
    @Override
    public void setServiceValue(int activityValue)throws RemoteException{
        value=activityValue;
    }

    @Override
    public void registerConnectCallback(IConnectCallbackInterface cb){
        callbackInterface=cb;
        try{
            callbackInterface.putValue(4567);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
};

4 、大功告成。

参考资料:

https://developer.android.google.cn/guide/components/aidl.html?hl=zh-cn



猜你喜欢

转载自blog.csdn.net/wode_dream/article/details/55518535