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方法调用
- 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;
}
-
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是什么,再回头看自己以前的理解,想法如下:
- 很基本的原理看完对整体设计是有提升.
- 以后自己的文章,要简如接口设计.