本文最后更新于:2023年4月15日 下午
AIDL简介
AIDL(Android Interface Definition Language, Android 接口定义语言)
用于定义C/S体系结构中Server端可以提供的服务调用接口,框架层提供的Java系统服务接口大多由AIDL语言定义。
Android提供了AIDL工具,可将AIDL文件编译成Java文件。提高服务开发的效率
程序员可以利用AIDL自定义编程接口,在客户端和服务端之间实现进程间通信(IPC)。
在Android平台上,一个进程通常不能访问另外一个进程的内存空间,因此,Android平台将这些跨进程访问的对象分解成操作系统能够识别的简单对象。
并为跨应用访问而特殊编排和整理这些对象。用于编排和整理这些对象的代码编写起来十分冗长,所以Android的AIDL提供了相关工具来自动生成这些代码。
开发人员只需要在AIDL文件中定义Server端可以提供的服务方法,AIDL工具便可将其转化为Java文件。转化后的Java文件包含C/S体系结构的以下内容:
- 服务接口 (IPowerManager)
- 服务在Client端的代理(Proxy)
- 服务存根(Stub)
- Binder类型与IIterface类型的转换接口(asInterface 和 asBinder 方法)
- 服务方法请求码
AIDL意义
AIDL工具建立了基于Binder的C/S体系结构的通用组件;开发者可以专注于开发服务的功能,而不需理会具体的通信结构,提高效率。
应用示例
根据上文我们可以知道,我们创建两个apk,一个作为服务提供方,一个作为AIDL服务调用方。
AIDL服务提供方代码
首先是AIDL服务提供方主要文件目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| main/aidl/ ` ` ` `
main/java ` ` | | `
build/generated/source/aidl/ ` ` ` ` `
PGSQL
|
新建AIDL文件并写好接口
进入服务方的工程,右键新建AIDL文件ITomInterface.aidl
。
文件会默认生成在main/aidl/com/rustfisher/ndkproj
下
1 2 3 4 5 6 7 8 9 10
| package com.rustfisher.ndkproj;
interface ITomInterface { void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String helloAIDL(String name); }
JAVA
|
编写服务方的接口实现代码
在com.rustfisher.tom
包内创建TomService.java
文件;建立内部类TomServiceImpl
实现接口的功能
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
| import com.rustfisher.ndkproj.ITomInterface;
public class TomService extends Service { private static final String TAG = "rustApp";
public class TomServiceImpl extends ITomInterface.Stub {
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override public String helloAIDL(String name) throws RemoteException { Log.d(TAG, name + " requires helloAIDL()"); return "Hello " + name + ", nice to meet you!"; } }
@Nullable @Override public IBinder onBind(Intent intent) { return new TomServiceImpl(); } }
JAVA
|
服务方在AndroidManifest.xml
文件中配置
实现了TomService
类后,对此AIDL服务进行配置;在AndroidManifest.xml
文件中配置
1 2 3 4 5
| <service android:name="com.rustfisher.tom.TomService"> <intent-filter> <action android:name="com.rustfisher.ndkproj.ITomInterface" /> </intent-filter> </service>
XML
|
action里面写上AIDL文件
安装运行此apk到手机上
让服务方运行起来
AIDL调用方代码(客户端)
建立(或进入)AIDL调用方的工程,这里是aidlcaller工程。
主要文件目录
1 2 3 4 5 6 7 8
| java/ ` | | ` | ` ` ` `
ADA
|
有如下3个步骤:
- 1.将AIDL服务端生成的Java文件复制到调用方工程里,尽量保持这个Java文件的路径与服务端的一致,便于识别
- 2.写代码绑定服务,获取AIDL服务对象
- 3.通过AIDL服务对象完成AIDL接口调用
编写调用方MainActivity.java
代码
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 42 43 44 45 46 47 48 49 50 51 52 53
| import com.rustfisher.ndkproj.ITomInterface;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "rustApp"; ITomInterface mTomService; TextView mTv1;
private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mTomService = ITomInterface.Stub.asInterface(service); mTv1.setClickable(true); Log.d(TAG, "[aidlcaller] onServiceConnected"); }
@Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "onServiceDisconnected " + name); } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initAIDLService(); initUI(); }
private void initUI() { mTv1 = (TextView) findViewById(R.id.tv1); mTv1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { String hello = mTomService.helloAIDL("Jerry"); Log.d(TAG, hello); } catch (Exception e) { Log.e(TAG, "mTomService initAIDLService: Fail ", e); e.printStackTrace(); } } }); }
private void initAIDLService() { Intent intent = new Intent("com.rustfisher.ndkproj.ITomInterface"); intent.setPackage("com.rustfisher.ndkproj"); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } }
JAVA
|
测试和效果
点击调用端的View,打出log Hello Jerry, nice to meet you!
服务端apk打印log:Jerry requires helloAIDL()
如果调用失败则抛出 android.os.DeadObjectException
当服务提供方App没有在运行时,调用方去请求服务会失败。
服务端更新后,如果aidl文件没改动,不需要更新生成的Java文件
如果服务端apk被卸载,调用端使用此服务时会出错
参考资料
Android Binder 机制介绍