AIDL基础体验

AIDL基础体验

  • 基础理论
  • 运行效果
  • 核心代码
  • 完整代码
  • 注意事项

第一章 基础理论

第01节 原理图

在这里插入图片描述

第02节 简述说明

1. 什么是 AIDL?
		AIDL 是 Android Interface Definition Language, 即Android接口定义语言。
		
2. AIDL有什么作用?
		AIDL 可以实现跨进程的服务调用。
		也就是 进程A当中,可以访问到进程B当中 暴露出来的内容信息。

3. 两个进程介绍:
		A. 对外暴露数据的是 服务端进程
		B. 访问暴露时间的是 客户端进程

4. 进程交互过程说明:
		A. 服务端进程, 定义统一的接口 AIDL, 再定义 Service 在定义的 Service 当中需要绑定 binder 对象。
		B. 服务端进程, 需要在清单文件当中,指定 action 
		C. 客户端进程, 定义统一的接口 AIDL, 再绑定 Service 在绑定的过程当中,指定 Intent 的action和package。
		D. 客户端进程, 需要在绑定Service 之后, 再去采用 binder的代理对象去调用共享的 AIDL 方法

第二章 运行效果

第01节 效果图

在这里插入图片描述

第02节 简述说明

左图说明

概述说明:
	左图是 Server 服务端进程的代码实现, 主要是 服务端进程的操作,提供 AIDL 

主要的操作步骤:
	1、需要先定义 AIDL 文件信息
	2、编译AIDL文件,在菜单栏当中,找到 Build 选择 Make Project 会产生 AIDL的接口文件
	3、接口文件所在的位置: build/generated/aidl_source_output_dir/debug/out/...
	4、需要定义 Service 其中在 onBind 方法当中返回 iBuilder 的对象
	5、需要在 Service 里面, 定义方法返回 iBuilder 的对象,主要是通过 AIDL 返回的结果
	6、不要忘记了在服务端进程的清单文件当中, 定义 Service 的 action 以便于客户端进程进行远程访问

右图说明

概述说明:
	右图是 Client 客户端进程的代码实现, 主要是客户端进程的操作,访问服务端的 AIDL 
	
主要的操作步骤:
	1、在客户端进程当中, 需要定义 AIDL 文件, 注意该文件的包路径, 必须和服务端的 AIDL 的包路径完全相同
	2、编译AIDL文件,在菜单栏当中,找到 Build 选择 Make Project 会产生 AIDL的接口文件
	3、在 MainActivity 当中初始化基础控件和点击事件等。 findViewById 和 setOnClickListener 操作
	4、在 MainActivity 当中绑定服务端的操作 ServiceConnection 需要重写两个方法 绑定和解绑
	5、在 MainActivity 当中点击绑定服务按钮的点击事件当中, 需要绑定服务, 采用意图 Intent 设置 action 和 bindService 方法
	6、在 MainActivity 当中的 onDestroy 方法当中, 需要解绑服务, 调用 unbindService 方法

第三章 核心代码

第01节 服务端进程操作

步骤01:定义AIDL文件

位置介绍

在这里插入图片描述

案例代码

HelloAIDL.aidl 当中的写法

// HelloAIDL.aidl
package hello.svip.server;

// Declare any non-default types here with import statements

interface HelloAIDL {

    //计算 num1+num2
    int add(int num1,int num2);
}

步骤02:编译AIDL

位置介绍

在这里插入图片描述

案例代码

以下代码是自动生成的,主要存在于 build/generated/aidl_source_output_dir/debug/out

下面是部分代码展示:

public interface HelloAIDL extends android.os.IInterface
{
  /** Default implementation for HelloAIDL. */
  public static class Default implements hello.svip.server.HelloAIDL
  {
    //计算 num1+num2

    @Override public int add(int num1, int num2) throws android.os.RemoteException
    {
      return 0;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements hello.svip.server.HelloAIDL
  {
    private static final java.lang.String DESCRIPTOR = "hello.svip.server.HelloAIDL";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }

//备注:后面代码省略,这部分内容是自动生成的代码

步骤03:创建Service

位置介绍

在 java 代码当中,创建一个 HelloService 的代码实现

案例代码

Java 代码的写法

package hello.svip.server;
//定义服务 Service
public class HelloService extends Service {
 
  	public static final String TAG = "chc";
    
  	@Nullable
    @Override
    public IBinder onBind(Intent intent) { 
        return null;
    }
}

清单文件当中,指定 Service 这里的 action 可以随意指定,提供给客户端进程进行访问得到。

<!--    绑定服务    -->
<service
    android:name=".HelloService">
    <intent-filter>
        <action android:name="this.is.server.action.for.adil" />
    </intent-filter>
</service>

步骤04:修改Service

在 service 里面定义一个 获取到 iBinder 对象的匿名内部类

/***
 * 在 AndroidStudio 当中.采用的是 Builder --> Make Project
 *
 * 等待编译完毕之后,会产生一个 HelloAIDL的接口文件.
 *
 * 产生的文件具体在: build/generated/aidl_source_output_dir/debug/out/...
 */
private IBinder iBinder = new HelloAIDL.Stub() {
    @Override
    public int add(int num1, int num2) throws RemoteException {
        Log.i(TAG, "add: 收到来自于客户端的请求:" + num1 + "+" + num2);
        //具体的操作,实现两者相加的过程。
        return num1 + num2;
    }
};

修改 onBind 方法的返回值,返回的是 iBinder 的对象

@Nullable
@Override
public IBinder onBind(Intent intent) {
    //返回的是下面产生的AIDL的实现类对象
    return iBinder;
}

第02节 客户端进程操作

步骤01:定义AIDL文件

位置介绍

在这里插入图片描述

案例代码

HelloAIDL.aidl 当中的写法

// HelloAIDL.aidl
package hello.svip.server;

// Declare any non-default types here with import statements

interface HelloAIDL {

    //计算 num1+num2
    int add(int num1,int num2);
}

步骤02:编译AIDL

位置介绍

在这里插入图片描述

案例代码

以下代码是自动生成的,主要存在于 build/generated/aidl_source_output_dir/debug/out

下面是部分代码展示:

public interface HelloAIDL extends android.os.IInterface
{
  /** Default implementation for HelloAIDL. */
  public static class Default implements hello.svip.server.HelloAIDL
  {
    //计算 num1+num2

    @Override public int add(int num1, int num2) throws android.os.RemoteException
    {
      return 0;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements hello.svip.server.HelloAIDL
  {
    private static final java.lang.String DESCRIPTOR = "hello.svip.server.HelloAIDL";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }

//备注:后面代码省略,这部分内容是自动生成的代码

步骤03:创建Activity

位置介绍

在 java 代码当中,设置布局文件,输入框等按钮点击事件等。

在这里插入图片描述

准备 Java 代码的信息

package hello.svip.client;

public class MainActivity extends AppCompatActivity {

    private EditText etNum01, etNum02;
    private Button btn_bind, btn_call;
    private TextView tvShow;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.etNum01 = this.findViewById(R.id.et_num01);
        this.etNum02 = this.findViewById(R.id.et_num02);
        this.btn_bind = this.findViewById(R.id.btn_bind);
        this.btn_call = this.findViewById(R.id.btn_call);
        this.tvShow = this.findViewById(R.id.tv_show);

        //绑定服务
        this.btn_bind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
              
            }
        });

        //点击访问
        this.btn_call.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "点击访问", Toast.LENGTH_LONG).show();
            }
        });
    }
}

第04节:修改Activity

定义 AIDL的绑定匿名内部类

//定义AIDL
private HelloAIDL aidl;

//客户端的服务绑定
private ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //绑定服务
        aidl = HelloAIDL.Stub.asInterface(service);
        Log.i(TAG, "onServiceConnected: --aidl->" + aidl);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        //解绑服务,设置为null
        aidl = null;
    }
};

定义绑定服务操作方法

/***
 * 绑定服务
 */
public void bindService() {
    Intent intent = new Intent();
    //绑定服务
    intent.setPackage("hello.svip.server");
    intent.setAction("this.is.server.action.for.adil");
    //绑定的时候服务自动创建
    bindService(intent, conn, BIND_AUTO_CREATE);
}

定义销毁服务的方法,重写 Activity 的 onDestroy

@Override
protected void onDestroy() {
    super.onDestroy();
    //解绑服务
    if (conn != null) {
        unbindService(conn);
    }
}

修改按钮的点击事件处理方式

//绑定服务
this.btn_bind.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        bindService();
        Toast.makeText(MainActivity.this, "绑定服务 aidl ---> " + aidl, Toast.LENGTH_LONG).show();
    }
});

//点击访问
this.btn_call.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "点击访问", Toast.LENGTH_LONG).show();
        try {
            int num1 = Integer.parseInt(etNum01.getText().toString().trim());
            int num2 = Integer.parseInt(etNum02.getText().toString().trim());
            //执行远程的加法操作
            int result = aidl.add(num1, num2);
            //执行结果
            tvShow.setText("最终结果:" + result);
            //日志展示结果
            Log.i(TAG, "onClick: 最终结果是:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

第四章 完整代码

第01节 AIDL文件

// HelloAIDL.aidl
package hello.svip.server;

// Declare any non-default types here with import statements

interface HelloAIDL {

    //计算 num1+num2
    int add(int num1,int num2);
}

第02节 服务清单文件

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

    <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/Theme.MyDemo">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--    绑定服务    -->
        <service
            android:name=".HelloService">
            <intent-filter>
                <action android:name="this.is.server.action.for.adil" />
            </intent-filter>
        </service>
    </application>

</manifest>

第03节 服务端Service

package hello.svip.server;

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

import androidx.annotation.Nullable;


//定义服务 Service
public class HelloService extends Service {

    public static final String TAG = "chc";

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回的是下面产生的AIDL的实现类对象
        return iBinder;
    }

    /***
     * 在 AndroidStudio 当中.采用的是 Builder --> Make Project
     *
     * 等待编译完毕之后,会产生一个 HelloAIDL的接口文件.
     *
     * 产生的文件具体在: build/generated/aidl_source_output_dir/debug/out/...
     */
    private IBinder iBinder = new HelloAIDL.Stub() {
        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.i(TAG, "add: 收到来自于客户端的请求:" + num1 + "+" + num2);
            //具体的操作,实现两者相加的过程。
            return num1 + num2;
        }
    };
}

第04节 客户端Activity

package hello.svip.client;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import hello.svip.server.HelloAIDL;


public class MainActivity extends AppCompatActivity {

    private EditText etNum01, etNum02;
    private Button btn_bind, btn_call;
    private TextView tvShow;
    private static final String TAG = "chc";
    //定义AIDL
    private HelloAIDL aidl;

    //客户端的服务绑定
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定服务
            aidl = HelloAIDL.Stub.asInterface(service);
            Log.i(TAG, "onServiceConnected: --aidl->" + aidl);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //解绑服务,设置为null
            aidl = null;
        }
    };


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

        this.etNum01 = this.findViewById(R.id.et_num01);
        this.etNum02 = this.findViewById(R.id.et_num02);
        this.btn_bind = this.findViewById(R.id.btn_bind);
        this.btn_call = this.findViewById(R.id.btn_call);
        this.tvShow = this.findViewById(R.id.tv_show);

        //绑定服务
        this.btn_bind.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                bindService();
                Toast.makeText(MainActivity.this, "绑定服务 aidl ---> " + aidl, Toast.LENGTH_LONG).show();
            }
        });

        //点击访问
        this.btn_call.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "点击访问", Toast.LENGTH_LONG).show();
                try {
                    int num1 = Integer.parseInt(etNum01.getText().toString().trim());
                    int num2 = Integer.parseInt(etNum02.getText().toString().trim());
                    //执行远程的加法操作
                    int result = aidl.add(num1, num2);
                    //执行结果
                    tvShow.setText("最终结果:" + result);
                    //日志展示结果
                    Log.i(TAG, "onClick: 最终结果是:" + result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /***
     * 绑定服务
     */
    public void bindService() {
        Intent intent = new Intent();
        //绑定服务
        intent.setPackage("hello.svip.server");
        intent.setAction("this.is.server.action.for.adil");
        //绑定的时候服务自动创建
        bindService(intent, conn, BIND_AUTO_CREATE);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解绑服务
        if (conn != null) {
            unbindService(conn);
        }
    }
}

第五章 注意事项

第01节 包名称相同

1、说明

服务端进程的 AIDL 所在的包名称是  hello.svip.server
客户端进程的 AIDL 所在的包名称是  hello.svip.server

两者的 AIDL 所在的包名称是相同的

2、截图

在这里插入图片描述

第02节 编译版本问题

1、说明

我们采用的是编译版本是 Android 29 
如果采用的是 Android 31 会导致 binder 对象为 null 出现 NullPointerException 空指针异常的情况。

2、截图

在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>