零、完整源代码
链接: https://github.com/jx0260/TestGradle
一、创建AIDL文件
// IShopAidlInterface.aidl
package com.example.testgradle;
// Declare any non-default types here with import statements
interface IShopAidlInterface {
String getProductInfo(int productNo);
void buyProduct1(int productNo, String address);
}
二、Make Project 生成Binder工具类
路径为:
生成代码如下(下一篇文章会分析这些生成的代码):
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package com.example.testgradle;
// Declare any non-default types here with import statements
public interface IShopAidlInterface extends android.os.IInterface
{
/** Default implementation for IShopAidlInterface. */
public static class Default implements com.example.testgradle.IShopAidlInterface
{
@Override public java.lang.String getProductInfo(int productNo) throws android.os.RemoteException
{
return null;
}
@Override public void buyProduct1(int productNo, java.lang.String address) 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 com.example.testgradle.IShopAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.example.testgradle.IShopAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.testgradle.IShopAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.testgradle.IShopAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.testgradle.IShopAidlInterface))) {
return ((com.example.testgradle.IShopAidlInterface)iin);
}
return new com.example.testgradle.IShopAidlInterface.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_getProductInfo:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
java.lang.String _result = this.getProductInfo(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_buyProduct1:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
java.lang.String _arg1;
_arg1 = data.readString();
this.buyProduct1(_arg0, _arg1);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.example.testgradle.IShopAidlInterface
{
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;
}
@Override public java.lang.String getProductInfo(int productNo) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(productNo);
boolean _status = mRemote.transact(Stub.TRANSACTION_getProductInfo, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getProductInfo(productNo);
}
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void buyProduct1(int productNo, java.lang.String address) 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.writeInt(productNo);
_data.writeString(address);
boolean _status = mRemote.transact(Stub.TRANSACTION_buyProduct1, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().buyProduct1(productNo, address);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public static com.example.testgradle.IShopAidlInterface sDefaultImpl;
}
static final int TRANSACTION_getProductInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_buyProduct1 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.example.testgradle.IShopAidlInterface 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 com.example.testgradle.IShopAidlInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public java.lang.String getProductInfo(int productNo) throws android.os.RemoteException;
public void buyProduct1(int productNo, java.lang.String address) throws android.os.RemoteException;
}
IShopAidlInterface这个生成的文件里面有 Stub类、Proxy类等,简单理解就是服务端(Stub)、客户端(proxy)它们为我们提供了跨进程通信的能力。为技术上的通信打通路径,唯一缺少的是业务方法的实现
三、编写服务端
3.1 实现服务端 Stub 业务
class Stub implements com.example.testgradle.IShopAidlInterface
AIDL为我们生成的Stub类,实现了 com.example.testgradle.IShopAidlInterface 接口,我们现在就实现他的业务方法:
private IShopAidlInterface.Stub mBinder = new IShopAidlInterface.Stub() {
@Override
public String getProductInfo(int productNo) throws RemoteException {
Log.i(TAG, "SERVER: receive productNo: " + productNo);
return "the productNo is: " + productNo + ", productName is LEGO!";
}
@Override
public void buyProduct1(int productNo, String address) throws RemoteException {
Log.i(TAG, "SERVER: receive productNo: " + productNo + ", address: " +address);
Log.i(TAG, "YOU buy succeed!");
}
};
现在我们就实现好了,简单打印一些消息。有了服务端的Stub类,客户端怎么调用到它呢?
我们通过Android四大组件的Service,将这个服务端的Stub“传到”客户端,再在客户端进行调用:
3.2 定义服务端的Service
public class ShopService extends Service {
private String TAG = "ShopService";
public ShopService() {
}
private IShopAidlInterface.Stub mBinder = new IShopAidlInterface.Stub() {
@Override
public String getProductInfo(int productNo) throws RemoteException {
Log.i(TAG, "SERVER: receive productNo: " + productNo);
return "the productNo is: " + productNo + ", productName is LEGO!";
}
@Override
public void buyProduct1(int productNo, String address) throws RemoteException {
Log.i(TAG, "SERVER: receive productNo: " + productNo + ", address: " +address);
Log.i(TAG, "YOU buy succeed!");
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
我们在 onBind() 方法中,将Stub对象传出去。
manifest 文件配置一下:
<service
android:name=".ShopService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.testgradle.ShopService"/>
</intent-filter>
</service>
(注意 exported=“true”,意味着允许让外部组件启动,我们要做跨进程调用,所以要允许客户端能访问此Service)
四、编写客户端
新建一个Application,创建一个Activity:
在Create() 方法中:
private IShopAidlInterface iShopAidlInterface;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
Intent serviceIntent = new Intent("com.example.testgradle.ShopService");
serviceIntent.setPackage("com.example.testgradle");
bindService(serviceIntent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("ClientActivity", "onServiceConnected() service=" + service);
iShopAidlInterface = IShopAidlInterface.Stub.asInterface(service);
try {
iShopAidlInterface.getProductInfo(1221);
iShopAidlInterface.buyProduct1(9988, "大连市甘井子区");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, BIND_AUTO_CREATE);
findViewById(R.id.btn_getInfo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
iShopAidlInterface.getProductInfo(1221);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.btn_buy).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
iShopAidlInterface.buyProduct1(9988, "大连市西岗区");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
我们通过bindService,绑定到刚才在服务端定义的Service。在onServiceConnected()
回调中,将传过来的 IBinder 对象,使用 Stub.asInterface 转成 IShopAidlInterface 对象。再调用其中的业务方法。
由于我们是两个进程,所以此处的 使用 Stub.asInterface 转出的对象 就是一个 Proxy。
五、点按钮运行
打印日志:
com.example.testgradle I/ShopService: SERVER: receive productNo: 1221
com.example.testgradle I/ShopService: SERVER: receive productNo: 9988, address: 大连市西岗区
com.example.testgradle I/ShopService: YOU buy succeed!
下一篇文章,将详细描述,这中间发生了什么 及AIDL 与 Binder 的关系。