Android基础——AIDL Demo

3,508 阅读2分钟

一、AIDL是什么

AIDL是Android中进程间通信IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写,对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。

二、AIDL使用

2.1 AIDL server端代码编写

目录结构如下图所示:

其中:

  • IMyAidlInterface.aidl表示我们定义的aidl接口
  • User.aidl表示我们传输的自定义类型
  • MainActivity表示主页面
  • MyService表示自定义服务,用来返回IMyAidlInterface.Stub的实例
  • User表示具体我们传输的自定义类型,与User.aidl的区别是,User.aidl只是定义了引用

IMyAidlInterface.aidl

// IMyAidlInterface.aidl
package com.example.aidlserver;

import com.example.aidlserver.User;
// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    String getName();
    User getUserName(String data);
}

User.aidl

// User.aidl
package com.example.aidlserver;

parcelable User;

MyService

package com.example.aidlserver;

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

import androidx.annotation.Nullable;

public class MyService extends Service {
    private static final String TAG = "MyService";
    private static User user;
//    public MyService() {
//    }


    @Override
    public void onCreate() {
        super.onCreate();
        user = new User("zhangsan");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind" +
                "" );

        return new MyBinder();
    }

    static class MyBinder extends IMyAidlInterface.Stub {

        @Override
        public String getName() throws RemoteException {
            return "test";
        }

        @Override
        public User getUserName(String data) throws RemoteException {
            return user;
        }
     }
}

User

package com.example.aidlserver;

import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {
    public User(String name) {
        this.name = name;
    }

    public User(Parcel in) {
        name = in.readString();
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.aidlserver">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyService"
            android:exported="true"
            android:enabled="true">
        </service>
    </application>

</manifest>

2.2 AIDL client端代码编写

client端的目录代码结构如下图所示:
其中IMyAidlInterface.aidl与User.aidl必须保证与server端完全一致,所以将server端的aidl文件夹复制到client端就可以了

User也需要与Server端保持一致,包名也需要一致,所以在com.example下新建一个aidlserver包,在该包下复制server端的User代码

MainActivity代码

package com.example.aidlclient;

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.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.example.aidlserver.IMyAidlInterface;


public class MainActivity extends AppCompatActivity {
    private IMyAidlInterface iMyAidlInterface;

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

        bindService();
    }

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            serviceConnection = null;
        }
    };

    private void bindService() {
        Intent intent = new Intent();
        intent.setClassName("com.example.aidlserver", "com.example.aidlserver.MyService");
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);
    }

    private static final String TAG = "MainActivity";

    public void onClick(View view) {
        try {
            Log.d(TAG, "onClick" +
                    ", iMyAidlInterface = " + iMyAidlInterface.getName() +
                    ", iMyAidlInterface.getUserName(1) = " + iMyAidlInterface.getUserName("1") +
                    "" +
                    "");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

可以在控制台查看打印日志

git代码

参考资料
Android中AIDL的使用详解