Android AIDL实现进程间通信

AIDL(Android Interface Definition Language)是Android中为实现IPC(Inter Process Communication,进程间通信)的一种方式,本质是通过Binder实现,Binder是Android中最具特色的、广泛应用的进程间通信框架,具有高性能、高稳定性、安全性强、面向对象简单易用等优点。我们在定义好AIDL文件后,与wsdl类似的ide会帮我们自动生成了Binder类的相关代码,本文记录一个WSDL的简单使用,通过AIDL实现计算两数之和的事例。

1. 实现远程服务(Service)

两个进程通信,即需要一个提供服务的service,和一个调用服务的client。

1.1 创建AIDL File

首先创建一个项目作为service,直接new一个AIDL File,添加一个计算两数之和的方法

interface IMyAidlInterface {
    /**
     * 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);

    int add(int v1, int v2);
}

然后sync一下项目使之生成IMyAidlInterface.java这个文件。

1.2 创建Service

创建一个Service实现远程服务,其中onBind方法会返回一个IBinder类的对象,这个IBinder类的对象就是远程服务的具体业务实现。为了实现这个服务,我们要用到自动生成的子类IMyAidlInterface.Stub,在此来实现我们之前在AIDL文件中定义的add()方法。

package com.example.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }
    class MyBinder extends IMyAidlInterface.Stub {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
        @Override
        public int add(int v1, int v2) throws RemoteException {
            return v1 + v2;
        }
    }
}

在AndroidManifest.xml中为service添加过滤

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

至此,service已完成

2. 实现Client调用服务

创建新项目作为client。

2.1 创建AIDL File

将刚刚service端创建的AIDL文件从aidl层拷贝到main文件夹下,或重新new一个一模一样的,注意包名不可改变

sync一下项目生成IMyAidlInterface.java文件

2.2 调用服务

2.2.1 创建ServiceConnection内部类

为了调用service提供的服务,client需要实现ServiceConnection类来创建服务连接对象,在client端Activity创建一个内部类AdditionServiceConnection,这个类继承ServiceConnection类,并且重写了它的两个方法:onServiceConnected和onServiceDisconnected分别为绑定成功和解绑时的回调方法。该方法接收在service端定义的MyService的实现作为参数,随后被转换为client端自己的AIDL的实现,通过IMyAidlInterface.Stub.asInterface((IBinder) boundService)来获取iMyAidlInterface实例。

   class AdditionServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName name, IBinder boundService) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface((IBinder) boundService);
            Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG).show();
        }

        public void onServiceDisconnected(ComponentName name) {
            iMyAidlInterface = null;
            Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
        }
    }

2.2.2 绑定服务

通过对Intent设置service端的Action和Package参数来绑定服务:

 connection = new AdditionServiceConnection();
     Intent i = new Intent();
     i.setPackage("com.example.aidl");
     i.setAction("com.example.aidl.MyService");
     bindService(i, connection, Context.BIND_AUTO_CREATE);

输入两个整数求和,在模拟器上测试,启动两个app连接成功:

以下为client端页面布局和Activity的完整代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add by AIDL"
        android:textSize="21sp"
        android:layout_marginTop="30dp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/v1"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal">
        </EditText>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="+"
            android:textSize="36sp" />

        <EditText
            android:id="@+id/v2"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal">
        </EditText>

        <Button
            android:id="@+id/bt_sum"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:hint="=" >
        </Button>

        <TextView
            android:id="@+id/result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/result"
            android:textSize="21sp" />
    </LinearLayout>

</LinearLayout>
package com.example.aidl2;

import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.aidl.IMyAidlInterface;

public class MainActivity extends AppCompatActivity {

    private IMyAidlInterface iMyAidlInterface;
    AdditionServiceConnection connection;

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

        Button btSum = findViewById(R.id.bt_sum);
        btSum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TextView result = findViewById(R.id.result);
                EditText value1 = findViewById(R.id.v1);
                EditText value2 = findViewById(R.id.v2);
                int v1, v2, res = 0;
                v1 = Integer.parseInt(value1.getText().toString());
                v2 = Integer.parseInt(value2.getText().toString());
                try {
                    res = iMyAidlInterface.add(v1, v2);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                result.setText(res + "");
            }
        });
        connection = new AdditionServiceConnection();
        Intent i = new Intent();
        i.setPackage("com.example.aidl");
        i.setAction("com.example.aidl.MyService");
        bindService(i, connection, Context.BIND_AUTO_CREATE);
    }

    class AdditionServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName name, IBinder boundService) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface((IBinder) boundService);
            Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG).show();
        }

        public void onServiceDisconnected(ComponentName name) {
            iMyAidlInterface = null;
            Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
        connection = null;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值