您可以在 ADL 接口中定义 String 常量和 int 字符串常量。例如:const int VERSION = 1;。
使用 @nullable 注释可空参数或返回类型。
以下是 .aidl 文件示例:
/**
* Example of defining an interface for calling on to a remote service
* (running in another process).
*/
interface IRemoteService {
/**
* Often you want to allow a service to call back to its clients.
* This shows how to do so, by registering a callback interface with
* the service.
*/
void registerCallback(IRemoteServiceCallback cb);
/**
* Remove a previously registered callback interface.
*/
void unregisterCallback(IRemoteServiceCallback cb);
}
public interface IRemoteService extends android.os.IInterface
{
/** Default implementation for IRemoteService. */
public static class Default implements cn.malinkang.servicesamples.IRemoteService
{
/**
* Often you want to allow a service to call back to its clients.
* This shows how to do so, by registering a callback interface with
* the service.
*/
@Override public void registerCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException
{
}
/**
* Remove a previously registered callback interface.
*/
@Override public void unregisterCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException
{
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements cn.malinkang.servicesamples.IRemoteService
{
private static final java.lang.String DESCRIPTOR = "cn.malinkang.servicesamples.IRemoteService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an cn.malinkang.servicesamples.IRemoteService interface,
* generating a proxy if needed.
*/
//onServiceConnected调用 传入onServiceConnected返回的Binder
public static cn.malinkang.servicesamples.IRemoteService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//查询
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//同一个进程
if (((iin!=null)&&(iin instanceof cn.malinkang.servicesamples.IRemoteService))) {
return ((cn.malinkang.servicesamples.IRemoteService)iin);
}
//不同进程
return new cn.malinkang.servicesamples.IRemoteService.Stub.Proxy(obj);
}
//返回当前对象
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_registerCallback:
{
data.enforceInterface(descriptor);
cn.malinkang.servicesamples.IRemoteServiceCallback _arg0;
_arg0 = cn.malinkang.servicesamples.IRemoteServiceCallback.Stub.asInterface(data.readStrongBinder());
this.registerCallback(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unregisterCallback:
{
data.enforceInterface(descriptor);
cn.malinkang.servicesamples.IRemoteServiceCallback _arg0;
_arg0 = cn.malinkang.servicesamples.IRemoteServiceCallback.Stub.asInterface(data.readStrongBinder());
this.unregisterCallback(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements cn.malinkang.servicesamples.IRemoteService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Often you want to allow a service to call back to its clients.
* This shows how to do so, by registering a callback interface with
* the service.
*/
@Override public void registerCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_registerCallback, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().registerCallback(cb);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
/**
* Remove a previously registered callback interface.
*/
@Override public void unregisterCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_unregisterCallback, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().unregisterCallback(cb);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public static cn.malinkang.servicesamples.IRemoteService sDefaultImpl;
}
static final int TRANSACTION_registerCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_unregisterCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(cn.malinkang.servicesamples.IRemoteService impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static cn.malinkang.servicesamples.IRemoteService getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
/**
* Often you want to allow a service to call back to its clients.
* This shows how to do so, by registering a callback interface with
* the service.
*/
public void registerCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException;
/**
* Remove a previously registered callback interface.
*/
public void unregisterCallback(cn.malinkang.servicesamples.IRemoteServiceCallback cb) throws android.os.RemoteException;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public void registerCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.register(cb);
}
public void unregisterCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.unregister(cb);
}
};
默认情况下,RPC 调用是同步调用。如果您知道服务完成请求的时间不止几毫秒,则不应从 Activity 的主线程调用该服务,因为这可能会使应用挂起(Android 可能会显示“Application is Not Responding”对话框)— 通常,您应从客户端内的单独线程调用服务。
您引发的任何异常都不会回传给调用方。
3. 向客户端公开接口
public class RemoteService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
// Return the interface
return binder;
}
private final IRemoteService.Stub binder = new IRemoteService.Stub() {
public int getPid(){
return Process.myPid();
}
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString) {
// Does nothing
}
};
}
IRemoteService iRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Following the example above for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service
iRemoteService = IRemoteService.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
iRemoteService = null;
}
};
如果您使用的是自定义编译进程,_请勿_在您的构建中添加 .aidl 文件。此 .aidl 文件与 C 语言中的头文件类似,并未经过编译。
AIDL 会在其生成的代码中使用这些方法和字段,以对您的对象进行编组和解编。
例如,下方的 Rect.aidl 文件可创建 Parcelable 类型的 Rect 类:
package android.graphics;
// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;
import android.os.Parcel;
import android.os.Parcelable;
public final class Rect implements Parcelable {
public int left;
public int top;
public int right;
public int bottom;
public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {
public Rect createFromParcel(Parcel in) {
return new Rect(in);
}
public Rect[] newArray(int size) {
return new Rect[size];
}
};
public Rect() {
}
private Rect(Parcel in) {
readFromParcel(in);
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(left);
out.writeInt(top);
out.writeInt(right);
out.writeInt(bottom);
}
public void readFromParcel(Parcel in) {
left = in.readInt();
top = in.readInt();
right = in.readInt();
bottom = in.readInt();
}
public int describeContents() {
return 0;
}
}
带软件包参数(包含 Parcelable 类型)的方法
如果您有 .aidl 文件:
// IRectInsideBundle.aidl
package com.example.android;
/** Example service interface */
interface IRectInsideBundle {
/** Rect parcelable is stored in the bundle with key "rect" */
void saveRect(in Bundle bundle);
}
如下方实现所示,在读取 Rect 之前,ClassLoader 已在 Bundle 中完成显式设置
private final IRectInsideBundle.Stub binder = new IRectInsideBundle.Stub() {
public void saveRect(Bundle bundle){
bundle.setClassLoader(getClass().getClassLoader());
Rect rect = bundle.getParcelable("rect");
process(rect); // Do more with the parcelable.
}
};