AIDL在android系统中的作用

2024-06-10 07:32
文章标签 作用 android 系统 aidl

本文主要是介绍AIDL在android系统中的作用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。最近看了下AIDL在Android系统中的用法,在网上看到很多初学的朋友不太明白AIDL的实际作用,android提供了很多进程间通信的组件,像action、broadcast、contentprovide都可以实现进程间的通信,为什么还要用AIDL这个东西呢?

1、为什么要有AIDL?

无论学什么东西,最先得弄明白为什么要有这个东西,不要说存在即是合理,存在肯定合理,但是你还是没有明白。对于AIDL有一些人的浅显概念就是,AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在 AndroidManifest.xml中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了Messager,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:
?
1
Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.
注意:只使用AIDL是必要的,如果你允许客户从不同的应用程序访问服务IPC和想处理多线程服务。如果您不需要执行并发IPC在不同的应用程序中,您应该创建接口通过实现一个活页夹,或者如果你想执行IPC,但不需要处理多线程,实现你的接口使用信使。无论如何,确保你了解实现AIDL之前绑定服务。
第一句最重要,“只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messager,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messager是单线程处理。还是官方文档说的明白,一句话就可以理解为什么要有AIDL。

我在android源码中实现了一个自己写的AIDL例子,用以简单解释下AIDL的作用。

有开发过蓝牙或者WIFI应用的朋友肯定都知道,要去操作它必须先获得一个管理类,比如WIFI的管理类是WifiManager,通过getSystemService(Context.WIFI_SERVICE)就可以得到wifi的管理权限,这个提供了很多的方法可以让用户去操作它,比如打开wifi可以调用setWifiEnabled(true)方法。那这个Manager到底做了什么工作呢?是怎样实现打开wifi的呢?其实这个Manager只是一个管理类,真正干活的另有其人,是一个叫WifiService的系统服务。在Android系统中有很多的Manager,wifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,但是,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个aidl类就是实现Manager和Service通信的桥梁。

下面看我加的一个例子:

首先在android源码中的frameworks/base/core/java/android/os/目录下加入一个IMyTestService.aidl,一般系统的AIDL文件都放在这个目录下。

?
1
2
3
4
5
6
7
8
package android.os;
/** {@hide} */
interface IMyTestService
{
     void open();
     void close();
}

关于AIDL的语言规范我就不多说了,其实和Java写接口差不多(它本来就是一种接口语言)。里面只定义两个简单的方法,open和close。

然后在frameworks/base/Android.mk中添加一句:core/java/android/os/IMyTestService.aidl。android系统的编译目标是通过Android.mk来指定的,在这里加上自定义的aidl文件系统才会把这个文件编译进去,最终生成一个叫IMyTestService.java的文件。这一部分用eclipse可以很直观的看到,在项目添加了aidl文件后eclipse会自动编译此aidl,生成的文件存放在gen目录下。

AIDL添加好了后,在frameworks/base/services/java/com/android/server/目录下添加一个MyTestService.java,继承IMytestService这个aidl。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.android.server;
import android.net.wifi.WifiManager;
import android.content.Context;
import android.os.IMyTestService;
import android.util.Log;
public class MyTestService extends IMyTestService.Stub {
    private static final String TAG = "MyTestService" ;
    private Context mContext;
    private WifiManager mWifiManager;
    public MyTestService(Context context /*,WindowManagerService wm*/ ) {
        super ();
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }
    /* close wifi */
    public void close() {
        mWifiManager.setWifiEnabled( false );
    }
    /* open wifi */
    public void open() {
        mWifiManager.setWifiEnabled( true );
    }
}

实现aidl文件中定义的open和close方法,我这里很简单,open就是去打开wifi,close就去关闭wifi,当然,你也可以实现你自定义的功能,这个没有限制。

然后在frameworks/base/core/java/android/content/Context.java文件中加入一个静态字符串:public static final String MY_TEST_SERVICE ="my_test_service";

最后把这个服务添加到系统服务中去,在frameworks/base/services/java/com/android/server/SystemServer.java中Thread的run方法中添加下面代码:


?
1
2
3
4
5
6
7
try {
                 Slog.i(TAG, "My Test Service" );
                 myService = new MyTestService(context);
                 ServiceManager.addService(Context.MY_TEST_SERVICE, myService);
             } catch (Throwable e) {
                 reportWtf( "starting my test Service" , e);
             }

myService需要在前面声明一下。

SystemService是android系统跑起来之后就会调用的,这里的意思是把MyTestService添加到系统服务中去,并取名字叫Context.MY_TEST_SERVICE,也就是my_test_service。这样看起来是不是很熟悉呢?每个开发人员在开发过程中肯定会调用系统服务的,比如电源管理服务:getSystemService(Context.POWER_SERVICE),这个Service也是在这里添加进去的。android有很多的系统服务,这里就不一一例举了,有兴趣的朋友可以自行看看这个文件。


现在aidl添加了,service也添加了,并且添加进了系统服务,那么还少一个Manager,可以让第三方程序调用的Manager。

在frameworks/base/core/java/android/device/目录下添加MyTestManager.java文件:


?
1
2
3
4
5
6
7
8
9
10
package android.device;
import android.util.Log;
import android.content.Context;
import android.os.RemoteException;
import android.os.IMyTestService;
import android.os.ServiceManager;
public class MyTestManager {
private static final String TAG = "MyTestManager" ;
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private IMyTestService mTestService;
     public MyTestManager() {
         IMyTestService mService = IMyTestService.Stub
                .asInterface(ServiceManager.getService(Context.MY_TEST_SERVICE));
        mTestService = mService;
     }
    /**
      * Return true if open succeed
      * @see #open my Function()
      */
     public boolean openScanner() {
         try {
             mTestService.open();
         } catch (android.os.RemoteException e) {
             return false ;
         }
         return true ;
     }
     /**
      * Return true if close succeed
      * @see #close my Function()
      */
      public boolean closeScanner() {
          try {
              mTestService.close();
          } catch (android.os.RemoteException e) {
               return false ;
          }
          return true ;
     }
}

这个Manager通过aidl的Stub获取了刚才添加的那个系统级别的service,然后在这里去调用这个service的方法,以操作service,这就是aidl的作用。

然后我们可以写一个第三方程序,获取一个MyTestManager,调用这个管理类的openScanner和closeScanner方法去实现自己在service中定义的功能。

AndroidManifest中必须要添加权限,否则报错,没有研究这个权限起的什么作用,有懂得的朋友分享一下吧。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.app.Activity;
import android.device.MyTestManager;
public class MainActivity extends Activity {
     private Button open, close;
     private MyTestManager mTestManager;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         mTestManager = new MyTestManager();
         open = (Button) findViewById(R.id.btn1);
         open.setText( "打开Wifi" );
         close = (Button) findViewById(R.id.btn2);
         close.setText( "关闭Wifi" );
         open.setOnClickListener( new OnClickListener() {
            @Override
             public void onClick(View v) {
                 // TODO Auto-generated method stub
                 mTestManager.openScanner();
             }
        });
         close.setOnClickListener( new OnClickListener() {
            @Override
             public void onClick(View v) {
                // TODO Auto-generated method stub
                mTestManager.closeScanner();
             }
         });
     }
}

这也就实现了Android夸进程通信了。

这里只是一个很简单的例子,以便不理解这一块的朋友管中窥豹,其实AIDL和系统级服务的配合使用远没这么简单,但是大致原理是这样的,比如Android的网络服务,google定义了很多的状态,通过后台的Service不断的监听这些状态的变化去控制网络,又比如电源管理,控制屏幕的亮度等等,复杂的是其中繁多的状态变化。

这篇关于AIDL在android系统中的作用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1047529

相关文章

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断