AIDL探究

AIDL机制:

参考鸿阳博客:http://blog.csdn.net/lmj623565791/article/details/38461079.

Binder能干什么?

Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架.

Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。

服务器端接口:实际上是Binder类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务器端代码。

Binder驱动:该对象也为Binder类的实例,客户端通过该对象访问远程服务。

客户端接口:获得Binder驱动,调用其transact()发送消息至服务器
如果大家对上述不了解,没关系,下面会通过例子来更好的说明,实践是检验真理的唯一标准嘛

AIDL文件自动生成

androidstudio自动生成 new --> aidlfile

interface IPushAidl {
/**
 * 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 startNotify();

void stopNotify();

}

其中 #basicTypes是自带有,上面注释是说:示范一些基本类型,在AIDL中你能用他们作为参数与返回值.具体作用不知.
自己定义了startNotify与stopNotify方法.

编译后生成一个IPushAidl.java文件

public interface IPushAidl extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements cn.lunkr.example.android.testmultiprocessreacte.aidl.IPushAidl
}

里边有一个内部类Stub继承Binder并且实现IPushAidl的方法

Service的代码:

public class PushService extends Service {
private NotificationManager mNm;
private final static int NOTIFY_ID = 1;
private MyBinder mBinder = new MyBinder();
private final static String TAG = PushService.class.getSimpleName();

@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind");
    return mBinder;
}

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand");
    return super.onStartCommand(intent, flags, startId);
}

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

public final void startNotification() {
    Log.d(TAG, "startNotification");
    Notification.Builder builder = new Notification.Builder(this);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, MainActivity.class), 0);
    builder.setContentIntent(contentIntent);
    builder.setSmallIcon(R.mipmap.ic_launcher);
    builder.setTicker("Foreground Service Start");
    builder.setContentTitle("Foreground Service");
    builder.setContentText("Make this service run in the foreground.");
    Notification notification;
    if (Build.VERSION.SDK_INT >= 16) {
        notification = builder.build();
    } else {
        notification = builder.getNotification();
    }
    mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNm.notify(NOTIFY_ID, notification);//first parameter not < 0
}

public final void stopNotification() {
    Log.d(TAG, "stopNotification");
    mNm.cancel(NOTIFY_ID);
}

class MyBinder extends IPushAidl.Stub {
    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

    }

    @Override
    public void startNotify() {
        startNotification();
    }

    @Override
    public void stopNotify() {
        stopNotification();
    }
}
}

绑定service用的activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private Button startService, stopService, bindService, unbindService, startNotify, stopNotify;

private IPushAidl myBinder;

private ServiceConnection connection = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {
        myBinder = null;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        myBinder = IPushAidl.Stub.asInterface(service);
    }

};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startService = (Button) findViewById(R.id.start_service);
    stopService = (Button) findViewById(R.id.stop_service);
    bindService = (Button) findViewById(R.id.bind_service);
    unbindService = (Button) findViewById(R.id.unbind_service);
    startNotify = (Button) findViewById(R.id.start_notify);
    stopNotify = (Button) findViewById(R.id.stop_notify);
    startService.setOnClickListener(this);
    stopService.setOnClickListener(this);
    bindService.setOnClickListener(this);
    unbindService.setOnClickListener(this);
    startNotify.setOnClickListener(this);
    stopNotify.setOnClickListener(this);

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.start_service:
            Intent startIntent = new Intent(this, PushService.class);
            startService(startIntent);
            break;
        case R.id.stop_service:
            Intent stopIntent = new Intent(this, PushService.class);
            stopService(stopIntent);
            break;
        case R.id.bind_service:
            Intent bindIntent = new Intent(this, PushService.class);
            bindService(bindIntent, connection, BIND_AUTO_CREATE);
            break;
        case R.id.unbind_service:
            unbindService(connection);
            break;
        case R.id.start_notify:
            if (myBinder != null) {
                try {
                    myBinder.startNotify();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            break;
        case R.id.stop_notify:
            if (myBinder != null) {
                try {
                    myBinder.stopNotify();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            break;
        default:
            break;
    }
}
}

原理探究:

service 里边定义了内部类MyBinder继承IPushAidl.Stub,实现startNotify()与stopNotify().

系统会维护一个IPushAidl的代理类IPushAidlProxy(里边的方法与IPushAidl一致)

MainActivity在绑定Service的时候,将返回一个IBinder(猜测为代理类)

{
myBinder = IPushAidl.Stub.asInterface(service);
public static cn.lunkr.example.android.testmultiprocessreacte.aidl.IPushAidl asInterface(android.os.IBinder      obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof cn.lunkr.example.android.testmultiprocessreacte.aidl.IPushAidl))) {
return ((cn.lunkr.example.android.testmultiprocessreacte.aidl.IPushAidl)iin);
}
return new cn.lunkr.example.android.testmultiprocessreacte.aidl.IPushAidl.Stub.Proxy(obj);
}

然后MainActivity通过调用startNotify与stopNotify

(其实有代理类通过mRemote调用service的Stub中的onTransact()执行相应的方法

mRemote.transact(Stub.TRANSACTION_startNotify, _data, _reply, 0)

代理类中的参数传递的实现:

_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);

Stub参数的读取:

data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
//reply.writeInt(_result);调用result的返回
private android.os.IBinder mRemote;

到此,我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Binder驱动(mRemote),即服务端与客户端连接的桥梁。

不生成Aidl实现多进程Service方法调用

  1. PushService内部类gistcode

内部类:

class MyBinder extends Binder {
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        switch (code) {
            case 1://startNotify
                data.enforceInterface(DESCRIPTOR);
                startNotification();
                reply.writeNoException();
                return true;
            case 2://stopNotify
                data.enforceInterface(DESCRIPTOR);
                stopNotification();
                reply.writeNoException();
                return true;
        }
        return super.onTransact(code, data, reply, flags);
    }

}

private MyBinder mBinder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind");
    return mBinder;
}
  1. MainActivity中gistcode:

     private ServiceConnection connection = new ServiceConnection() {
     @Override
     public void onServiceDisconnected(ComponentName name) {
         myBinder = null;
     }
    
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         myBinder = service;
     }
     };
    
     @Override
     public void onClick(View v) {
     switch (v.getId()) {
         case R.id.start_service:
             Intent startIntent = new Intent(this, PushService2.class);
             startService(startIntent);
             break;
         case R.id.stop_service:
             Intent stopIntent = new Intent(this, PushService2.class);
             stopService(stopIntent);
             break;
         case R.id.bind_service:
             Intent bindIntent = new Intent(this, PushService2.class);
             bindService(bindIntent, connection, BIND_AUTO_CREATE);
             break;
         case R.id.unbind_service:
             unbindService(connection);
             break;
         case R.id.start_notify:
             if (myBinder != null) {
                 bindMethod(1);
             }
             break;
         case R.id.stop_notify:
             if (myBinder != null) {
                 bindMethod(2);
             }
             break;
     }
     }
    
     public void bindMethod(int id) {
     if (myBinder == null) {
         return;
     }
     android.os.Parcel _data = android.os.Parcel.obtain();
     android.os.Parcel _reply = android.os.Parcel.obtain();
     try {
         _data.writeInterfaceToken("PushService2");
         myBinder.transact(id, _data, _reply, 0);
     } catch (RemoteException e) {
         e.printStackTrace();
     } finally {
         _data.recycle();
         _reply.recycle();
     }
     }
    

补充:

传递参数_data.writeXxx(xxx),_data.readXxx(xxx);

看了网上关于AIDL的一些博客,从原理来解释AIDL是什么,再回头看自己以前的理解,想法如下:

  1. 很基本的原理看完对整体设计是有提升.
  2. 以后自己的文章,要简如接口设计.

demo:

https://github.com/xwpeng/TestAidl.git

你可能感兴趣的:(AIDL探究)