Android:AIDL实战详解

这篇具有很好参考价值的文章主要介绍了Android:AIDL实战详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

AIDL:Android Interface Definition Language

AIDL是为了实现进程间通信而设计的Android接口语言

Android进程间通信有多种方式,Binder机制是其中最常见的一种

AIDL的本质就是基于对Binder的运用从而实现进程间通信

这篇博文从实战出发,用一个尽可能精简的Demo,实现两个App(也是两个进程:服务端mainapp、客户端otherapp)通过AIDL的跨进程通信

废话不多说,开撸!

一.创建两个App

按照下列步骤先创建两个App:

(1).新建一个开发文件夹(本Demo中命名为aidl-test)

(2).使用AndroidStudio在aidl-test文件夹下创建第一个Empty Activity的空App:mainapp

android aidl,Android,android

为了后续方便起见

创建完成后,把Studio默认创建的MainActivity.java名字改一下,改成MainAppActivty.java

android aidl,Android,android

(3).创建第二个Empty Activity的空App:otherapp

android aidl,Android,android

android aidl,Android,android android aidl,Android,android

两个空App创建完成了:

android aidl,Android,android

二.在mainapp中创建一个Service

上一节中新建了两个空App:mainappotherapp

现在就先在mainapp中实现一个service

使用方便又快捷的studio创建MainAppService.java

android aidl,Android,android android aidl,Android,android

android aidl,Android,android

可以看到新建的MainAppService会自动实现一个onBind(Intent intent)方法,这个方法后续我会在其中进行代码实现,它需要在其他进程连接到Service时,返回一个继承了android.os.Binder的对象

先在 MainAppActivity MainAppService 中添加一些必要的生命周期函数代码
再在 MainAppService 中添加:
onBind(Intent intent):被客户端绑定时执行
onUnbind(Intent intent):被客户端解绑时执行

com/android/mainapp/MainAppActivity.java

package com.android.mainapp;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class MainAppActivity extends AppCompatActivity {
    private String TAG = "AIDL-MainAppActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v(TAG, "onCreate()");
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "onDestroy()");
    }
}

com/android/mainapp/MainAppService.java 

package com.android.mainapp;

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

public class MainAppService extends Service {
    private String TAG = "AIDL-MainAppService";

    public MainAppService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.v(TAG, "onStart()");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(TAG, "onUnbind()");
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "onDestroy()");
    }
}

三.mainapp中实现AIDL

依然使用方便又快捷的AndroidStudio在mainapp的main目录下创建一个名为IAppAidlInterface.aidl 的AIDL文件

android aidl,Android,android android aidl,Android,android

android aidl,Android,android

AndroidStudio创建 IAppAidlInterface.aidl 会自动实现一个默认的可用于进程间传参通信的void basicTypes(...)函数,其参数是java的几种基础数据类型

除此之外,AIDL还支持多种其他数据类型:byte、short、char、charSequence、 List、 Map等

除了AndroidStudio自动创建的basicTypes(...)函数,我在AIDL文件里面再新增一个setData(..)函数,用于后面跨进程的数据传输,虽然使用AndroidStudio自动生成的basicTypes(...)也是可以的,但是自己创建一个函数会更具有代表性

android aidl,Android,android

在本篇博文最开始就阐述过,AIDL的本质是对Binder的运用,从而实现进程间通信

那么现在Binder在哪呢?

IAppAidlInterface.aidl文件创建之后,build一下工程,AndroidStudio会在build目录下创建一个aidl_source_output_dir文件夹,同时在这个文件夹下创建与IAppAidlInterface.aidl包名、文件名相同的文件夹目录和java文件

android aidl,Android,android

IAppAidlInterface.java文件中通过继承android.os.Binder创建一个抽象的代理类stub,这个stub抽象代理类主要做如下几件事:

  • 通过stub自身实例实现进程内部的通信
  • 通过实现一个内部代理类Porxy用于跨进程通信
  • 重写Binder中的onTransact()函数,实现AIDL接口文件中声明的函数进行数据传输

传输的数据必须是序列化的android.os.Parcel类型数据 

android aidl,Android,android android aidl,Android,android

当然,如果项目需要对AIDL的Binder实现过程进行自定义封装,方便项目中对进程间通信机制进行定制化,那么,完全可以不采用AndroidStudio自动生成的IAppAidlInterface.java只须要按照自己的需要实现IAppAidlInterface.java中对Binder进程间通信的实现过程就行了

因为归根结底,AIDL实现进程间通信的基础就是Binder机制,只要使用Binder实现AIDL进程间通信的目的就可以了

IAppAidlInterface.java就先讨论到这里,这篇博文主要是对AIDL的使用进行研究,其对Binder机制的实现与封装不在此做深入探讨

后续会专门开一篇博文讲解AIDL对Binder机制的内部实现,以及用户如何自定义封装

四.otherapp中也实现AIDL

上一节中,作为服务端的mainapp里创建了一个AIDL文件,客户端的otherapp中也需要实现一份相同的AIDL,要不然客户端就无法引用到了对应的函数和stub等了

很简单,把mainapp中的AIDL文件整个包名目录直接拷贝到otherapp中即可,然后再build一下工程
android aidl,Android,android

接下来,需要添加一些代码,实现客户端otherapp与服务端mainapp的相连

五.mainapp中添加代码

前文中已经展示过,MainAppService会随着MainAppActivity的onCreate()和onDestroy()生命周期startService()和stopService()

mainapp中要添加的代码在MainAppService.java中,需要在MainAppService中做下面一些事情:

  • 使用匿名内部类实现IAppAidlInterface.Stub抽象类,用于实现IAppAidlInterface.aidl中的接口函数和onBinder()时返回匿名内部类实例
    android aidl,Android,android
  • onBinder()中启动一个线程,每1秒轮循接收客户端发送过来的数据
    android aidl,Android,android

      这里提到个题外的知识点,Service中除了onBinder()函数外还有个onRebind()函数

      如果同一客户端每次unBindService()之后再bindService()并且发送的Intent也一样,那么onBind()就只会在服务端第一次被这个客户端连接时才执行,后续重连时都不会再执行了。

     而onRebind()在服务端第一次被连接时不会被执行,但是之后每次重连都会执行,不论Intent是否一样。

    如果想要onBind()在同一客户端连接时都能执行,客户端在每次bindService()时,改变发送Intenttype或其他成员变量就行了

  • 定义一个string变量用于接收客户端传过来的字符串,定义一个boolean变量用于控制线程android aidl,Android,android
  • AndroidMainfest.xml中为MainAppService添加Service标签
    android aidl,Android,android

六.otherapp中添加代码

otherapp里面主要需要做如下几件事:

  • 新建一个Intent,用于连接服务端mainapp
    IntentComponent设置为Sevice的包名和类名
    android aidl,Android,android
  • 新建两个button,用于控制bindService()绑定和unbindService()解绑android aidl,Android,android
  • 重写Service连接和断开的两个基础函数onServiceConnected()onServiceDisconnected()android aidl,Android,android
  • AndroidMainfest.xml中添加查询包名权限,以便otherapp可以查询到mainapp,或者直接指定查询mainapp的包名
    android aidl,Android,android

七.运行、验证 

到此,一个最基础的使用AIDL实现两个App(服务端mainapp、客户端otherapp)之间通信的demo代码就完成了,下面我们来验证一下。

编译、安装apk:

项目build Apk后会生成两个apk,两个都install上

android aidl,Android,android android aidl,Android,android

运行验证:

注:本demo中代码的所有日志TAG都加上了AIDL前缀,方便日志打印验证

先启动一下mainapp,MainAppService不会被启动但是会被注册到系统,因为在mainapp的AndroidMainfest.xml中对MainAppService进行了Service标签添加。

android aidl,Android,android

退出mainapp后,再打开otherapp:

android aidl,Android,android

现在执行几次"Bind Service"和"Unbind Service",就会看到如下日志打印:

android aidl,Android,android

好,通过这个精简Demo,初步实现了两个App通过AIDL的跨进程通信 

八.源代码

接下来逐一展示实现的源码

mainapp源码:

android aidl,Android,android

D:\Codes\aidl-test\app\src\main\aidl\com\android\mainapp\IAppAidlInterface.aidl

// IAppAidlInterface.aidl
package com.android.mainapp;

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

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

    void setStringData(String strData);
}

D:\Codes\aidl-test\app\src\main\java\com\android\mainapp\MainAppActivity.java

package com.android.mainapp;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class MainAppActivity extends AppCompatActivity {
    private String TAG = "AIDL-MainAppActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v(TAG, "onCreate()");
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "onDestroy()");
    }
}

D:\Codes\aidl-test\app\src\main\java\com\android\mainapp\MainAppService.java

package com.android.mainapp;

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

public class MainAppService extends Service {
    private String TAG = "AIDL-MainAppService";

    private String mStrData;
    private boolean mSetServiceRunning = true;

    public MainAppService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(TAG, "onStart()");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.v(TAG, "onStart()");
    }

    IAppAidlInterface.Stub mStub = new IAppAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public void setStringData(String strData) {
            mStrData = strData;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        Log.v(TAG, "onBind()");
        mSetServiceRunning = true;

        new Thread() {
            @Override
            public void run() {
                super.run();
                while (mSetServiceRunning) {
                    try {
                        Thread.sleep(1000);
                        Log.v(TAG, "mStrData:"+mStrData);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        return mStub;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(TAG, "onUnbind()");
        mSetServiceRunning = false;
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "onDestroy()");
    }
}

D:\Codes\aidl-test\app\src\main\AndroidManifest.xml

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

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Mainapp"
        tools:targetApi="31">
        <service
            android:name=".MainAppService"
            android:enabled="true"
            android:exported="true">
        </service>

        <activity
            android:name=".MainAppActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

otherapp源码: 

android aidl,Android,android

D:\Codes\aidl-test\otherapp\src\main\aidl\com\android\mainapp\IAppAidlInterface.aidl

// IAppAidlInterface.aidl
package com.android.mainapp;

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

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

    void setStringData(String strData);
}

D:\Codes\aidl-test\otherapp\src\main\java\com\android\otherapp\OtherAppMainActivity.java

package com.android.otherapp;

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

import com.android.mainapp.IAppAidlInterface;

public class OtherAppMainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
    private String TAG = "AIDL-OtherAppActivity";

    private int mICount = 0;
    private Intent mServiceIntent;
    private IAppAidlInterface mBinder;

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

        mServiceIntent = new Intent();
        mServiceIntent.setComponent(new ComponentName("com.android.mainapp", "com.android.mainapp.MainAppService"));

        findViewById(R.id.btnBindMainAppService).setOnClickListener(this);
        findViewById(R.id.btnUnBindMainAppService).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnBindMainAppService: {
                Log.v(TAG, "onClick():btnBindMainAppService");
                bindService(mServiceIntent, this, Context.BIND_AUTO_CREATE);
            }
            break;

            case R.id.btnUnBindMainAppService: {
                Log.v(TAG, "onClick():btnUnBindMainAppService");
                unbindService(this);
                mBinder = null;
            }
            break;
        }
    }

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        if (mBinder == null) {
            mBinder = IAppAidlInterface.Stub.asInterface(iBinder);
            mICount++;
            Log.v(TAG, "onServiceConnected() 第 " + mICount + " 次");
            try {
                String strData = "第" + mICount + "次连接Service成功!";
                mBinder.setStringData(strData);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.v(TAG, "onServiceDisconnected");
    }
}

D:\Codes\aidl-test\otherapp\src\main\res\layout\activity_other_app_main.xml

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="OtherApp"/>

    <Button
        android:id="@+id/btnBindMainAppService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="Bind  Service" />

    <Button
        android:id="@+id/btnUnBindMainAppService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="UnBind Service" />

</LinearLayout>

D:\Codes\aidl-test\otherapp\src\main\AndroidManifest.xml文章来源地址https://www.toymoban.com/news/detail-715593.html

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

    <!--<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>-->
    <queries>
        <package android:name="com.android.mainapp"/>
    </queries>

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

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

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

到了这里,关于Android:AIDL实战详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android AIDL基本使用

    AIDL是Android多进程通讯方式一种。 如要使用 AIDL 创建绑定服务,请执行以下步骤: 创建 .aidl 文件 此文件定义带有方法签名的编程接口。 实现接口 Android SDK 工具会基于您的  .aidl  文件,使用 Java 编程语言生成接口。此接口拥有一个名为  Stub  的内部抽象类,用于扩展  B

    2024年02月09日
    浏览(37)
  • Android studio 无法创建AIDL文件

    Android studio 创建AIDL文件的时候 提示是灰色的无法创建 处理方法在app下面的build.gradle中的buildFeatures 添加 aidl = true 这个是 kotlin的写法,如果是使用的旧项目修改下格式就行

    2024年01月25日
    浏览(39)
  • Android 使用AIDL传输超大型文件

    最近在写车载Android的第5篇视频教程「AIDL的实践与封装」时,遇到一个有意思的问题,能不能通过AIDL传输超过 1M 以上的文件? 我们先不细究,为什么要用AIDL传递大文件,单纯从技术的角度考虑能不能实现。众所周知,AIDL是一种基于Binder实现的跨进程调用方案,Binder 对传输

    2024年02月10日
    浏览(52)
  • android aidl进程间通信封装通用实现

    接上一篇的分析,今天继续 aidl复杂流程封装-CSDN博客 今天的任务就是将代码梳理下放进来 1 项目gradle配置:    需要将对应的代码放到各自的目录下,这里仅贴下关键内容,细节可以下载代码慢慢看     sourceSets {         main {             manifest.srcFile \\\'src/main/AndroidManife

    2024年02月22日
    浏览(37)
  • Android Binder——APP中AIDL实现(十九)

            AIDL(Android Interface Definition Language)其实就是对 Binder 通信的一个封装,方便在开发中对 Binder 通信的使用,这里我们就从头开始来看一下 AIDL 通信的创建过程。         通过 Android Studio 的 File -New - AIDL 的方式就会生成对应包名的 aidl 文件。即 aidl 文件要与应用

    2024年04月28日
    浏览(28)
  • 深入解析Android AIDL:实现跨进程通信的利器

    Android Interface Definition Language (AIDL) 是一种Android系统中的跨进程通信机制。AIDL允许一个应用程序的组件与另一个应用程序的组件通信,并在两者之间传输数据。 AIDL的主要作用是帮助不同进程间共享数据和服务,让他们能够互相调用。例如,在开发一个多功能的音乐播放器时,

    2024年02月19日
    浏览(43)
  • Android中AIDL的简单使用(Hello world)

    AIDL:Android Interface Definition Language(Android接口定义语言) 作用:跨进程通讯。如A应用调用B应用提供的接口 A应用创建aidl接口,并且创建一个Service来实现这个接口(在onBind方法里面return我们这个接口的实例)。 把A应用创建的aidl文件原封不动的搬至B应用中(注意包名类名都

    2024年02月11日
    浏览(50)
  • android aidl进程间通信封装通用实现-用法说明

    接上一篇:android aidl进程间通信封装通用实现-CSDN博客 该aar包的使用还是比较方便的 一先看客户端 1 初始化 2 发送事件:  就是通过json的形式将参数包裹进来,另一端统一解析  唯一标志位:KEY_CLIENT_REQUEST_AUTHOR 是必须要加的,不然区分不出来是那个客户端 二再看服务端

    2024年02月20日
    浏览(35)
  • Android:AIDL简单介绍+传递简单数据+传递复杂数据

    对于AIDL的学习,这些也只能说是我在学习中的理解,有理解不到位或者错的地方也欢迎指正。 AIDL的目的就是实现进程之间的通信, 尤其是在涉及多进程并发情况下的进程间通信 。可以将aidl理解为两个进程之间的桥梁,并制定规则,使其传输特定数据。 1.AIDL支持的数据类型

    2024年02月21日
    浏览(41)
  • Android Binder常用案例使用分析,跨进程通信aidl

    service组件的binderService获取binder通信。 servicemanager.getService方法获取相关服务。 本质上都是IBinder通信。 客户端:使用intent,启动服务端的service,使用binderservice,在onServiceConnected回调方法中获取服务端的实际binder对象。使用aidl中的接口调用服务端的方法即可。 服务端:定义

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包