https://developer.android.google.cn/guide/components/aidl.html
后者是AIDL的说明和使用。
什么情况使用AIDL类型的service?
https://developer.android.google.cn/guide/components/aidl.html中有使用建议,只有允许不同应用的client需要IPC访问service,并且想要在service中处理多线程时,才有必要使用AIDL。
如何定义及使用AIDL?
1. 创建 .aidl文件
比如,定义IRemoteService.aidl,在文件中定义接口。
//IRemoteService.aidl
package com.ali.yunos.androiddemo_n.services;
// Declare any non-default types here withimport statements
interface IRemoteService {
/** Request the process ID of this service */
int getPid();
/**
* Demonstrates some basic types thatyou can use as parameters
* and return values in AIDL.
*/
void basicTypes(intanInt, longaLong, booleanaBoolean, floataFloat,
double aDouble,String aString);
}
2. 实现接口
Android studio会自动生成AIDL对应的java文件,
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file:D:\\workspace\\AndroidStudioWorkspace\\AndroidDemo_N\\app\\src\\main\\aidl\\com\\ali\\yunos\\androiddemo_n\\services\\IRemoteService.aidl
*/
package com.ali.yunos.androiddemo_n.services;
// Declare any non-default types here withimport statements
public interface IRemoteServiceextends android.os.IInterface
{
/** Local-sideIPC implementation stub class. */
public staticabstract class Stubextends android.os.Binderimplements com.ali.yunos.androiddemo_n.services.IRemoteService
{
private static final java.lang.StringDESCRIPTOR ="com.ali.yunos.androiddemo_n.services.IRemoteService";
/** Constructthe stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this,DESCRIPTOR);
}
/**
* Cast an IBinder object into ancom.ali.yunos.androiddemo_n.services.IRemoteService interface,
* generating a proxy if needed.
*/
public static com.ali.yunos.androiddemo_n.services.IRemoteServiceasInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iininstanceof com.ali.yunos.androiddemo_n.services.IRemoteService))){
return ((com.ali.yunos.androiddemo_n.services.IRemoteService)iin);
}
return new com.ali.yunos.androiddemo_n.services.IRemoteService.Stub.Proxy(obj);
}
@Override publicandroid.os.IBinder asBinder()
{
return this;
}
@Override public booleanonTransact(intcode, android.os.Parcel data,android.os.Parcel reply, intflags) throwsandroid.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getPid:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getPid();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_basicTypes:
{
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();
return true;
}
}
return super.onTransact(code,data, reply, flags);
}
private static class Proxyimplements com.ali.yunos.androiddemo_n.services.IRemoteService
{
private android.os.IBindermRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override publicandroid.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.StringgetInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public intgetPid() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply =android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getPid,_data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* Demonstrates some basic types thatyou can use as parameters
* and return values in AIDL.
*/
@Override public voidbasicTypes(intanInt, longaLong, booleanaBoolean, floataFloat, doubleaDouble, java.lang.String aString) throwsandroid.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply =android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes,_data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getPid= (android.os.IBinder.FIRST_CALL_TRANSACTION+ 0);
static final int TRANSACTION_basicTypes=(android.os.IBinder.FIRST_CALL_TRANSACTION+ 1);
}
public int getPid()throws android.os.RemoteException;
/**
* Demonstrates some basic types thatyou can use as parameters
* and return values in AIDL.
*/
public void basicTypes(intanInt, longaLong, booleanaBoolean, floataFloat, doubleaDouble, java.lang.String aString) throwsandroid.os.RemoteException;
}
然后实现接口,
private final IRemoteService.StubmBinder= new IRemoteService.Stub(){
@Override
public int getPid()throws RemoteException {
// return 0;
return Process.myPid();
}
@Override
public void basicTypes(intanInt, longaLong, booleanaBoolean, floataFloat, doubleaDouble, String aString) throwsRemoteException {
Log.d(TAG,"basicTypes");
}
};
3. public出去,这个重新定义一个文件,比如RemoteService.
public classRemoteService extendsService {
private final static StringTAG ="RemoteService";
public RemoteService() {
}
@Override
public IBinderonBind(Intent intent) {
// TODO: Return the communication channel tothe service.
// throw newUnsupportedOperationException("Not yet implemented");
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
private final IRemoteService.StubmBinder = new IRemoteService.Stub(){
@Override
public int getPid()throws RemoteException {
// return 0;
return Process.myPid();
}
@Override
public void basicTypes(intanInt, longaLong, booleanaBoolean, floataFloat, doubleaDouble, String aString) throwsRemoteException {
Log.d(TAG,"basicTypes");
}
};
}
client端:
public classMainActivity extendsAppCompatActivity {
private static final StringTAG ="MainActivity";
ImageView mImg= null;
Button mButton= null;
boolean mBound =false;
IRemoteService mService= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG,"onCreate Thread Id = " + Process.myTid());
super.onCreate(savedInstanceState);
LinearLayout mLayout = newLinearLayout(this);
mLayout.setOrientation(LinearLayout.VERTICAL);
mLayout.setLayoutParams(newLinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
mLayout.setBackgroundColor(Color.CYAN);
setContentView(mLayout);
mImg =new ImageView(this);
mImg.setLayoutParams(newLinearLayout.LayoutParams(400,400));
mImg.setBackgroundColor(Color.RED);
mLayout.addView(mImg);
Button button = mButton= new Button(this);
button.setText("click me");
button.setLayoutParams(newLinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT
));
mLayout.addView(button);
button.setOnClickListener(newView.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"click button");
if (mBound) {
try {
int pid =mService.getPid();
Log.d(TAG,"service pid = " + pid);
} catch(RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = newIntent(this,RemoteService.class);
bindService(intent,mServiceConn ,Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mServiceConn);
mBound =false;
}
}
ServiceConnection mServiceConn =new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name,IBinder service) {
Log.d(TAG,"onServiceConnected");
mService = IRemoteService.Stub.asInterface(service);
mBound =true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"onServiceDisconnected");
mBound =false;
}
};
}
点击button的日志打印:
07-06 06:27:49.836: D/MainActivity(3944): onCreate Thread Id = 3944
07-06 06:27:51.060: D/MainActivity(3944): onServiceConnected
07-06 06:28:28.141: D/MainActivity(3944): click button
07-06 06:28:28.142: D/MainActivity(3944): service pid = 3967
可以看出,已经调用了service的接口,Done!