Learn from the example Binder mechanism

Binder Android is a means to achieve inter-process communication (IPC) is, in every Android application runs in its own process number, each application you want to work are required to provide service support systems, information transfer between them is based on Binder achieve. Just because Android Binder layers to encapsulate the common development tasks of the reach of Binder-level interface, Binder did show a little mysterious. This article from the Service Component As a starting point, with examples demonstrate how Binder cross-process communication.

How to Use Binder

Binder belong to the CS structure, the client and server belong to different processes. I believe we first use the time to write is learning Binder Service component Hello World program.

// Service
public class CalculateService extends Service {

    private final IBinder mBinder = new CalculateBinder();

    public class CalculateBinder extends Binder {
        public CalculateService getService() {
            return CalculateService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public int add(int a, int b) {
        return a + b;
    }
}

// Client
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "HelloBinder";

    private CalculateService mService;
    private boolean mBound = false;

    ...

    public void clickAction(View view) {
        if (mBound) {
            Log.d(TAG, "add: " + mService.add(1, 2));
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent i = new Intent(this, CalculateService.class);
        bindService(i, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
        mBound = false;
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ((CalculateService.CalculateBinder) service).getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            mBound = false;
        }
    };
}

// Manifest
<service android:name=".services.CalculateService" />

If these CalculateService into cross-process Service .aidl only need to add a file to add, modify the above code into the type of part ok. In Android Studio project right to display the menu, select AIDL item, the following documents

// ICalculateService.aidl
package com.iyh.simpleclient;
interface ICalculateService {
    int add(int a, int b);
}

Other code is replaced by the following

// service
public class CalculateService extends Service {

    // 删除 CalculateBinder 类,并使用以下方式获取 binder
    private ICalculateService.Stub binder = new ICalculateService.Stub() {
        @Override
        public int add(int a, int b) throws RemoteException {
            return CalculateService.this.add(a, b);
        }
    };
    ... 隐藏部分与之前程序相同 ...
}

// client
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "HelloBinder";

    private ICalculateService mService; // 此处 Service 就为 ICalculateService

    ... 隐藏部分与之前程序相同 ...

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ICalculateService.Stub.asInterface(service); // 类型转换使用 Stub 提供的方法
            mBound = true;
        }
        ... 隐藏部分与之前程序相同 ...
    };
}

// Manifest
<service android:name=".services.CalculateService"
        android:process=":other"/>

After the cross-process can be found, the code seems simpler than before. This is because AIDL, Android Studio automatically generates ICalculateService.java according to ICalculateService.aidl, this java class use Binder encapsulates the process of interaction, so that the caller does not need to be concerned about the implementation. The following diagram describes operation procedure ICalculateService.java

IDL-model

FIG located CalculateService process A, process A calls in add(1, 2)time, ICalculateService.Stub.asInterface()the method based on IBinder.queryLocalInterface(descriptor)doing different processing is acquired CalculateService. There is a local method name can know that it is a local query service, that service the same process as the caller and Service are in the process A, so you can get to ICalculateService instance, direct return an object method call is completed.

If the service representative can not obtain the current process is not ICalculateService objects, such as process B from the calling add(3, 4)method, then returns to the caller Proxy class, the use of such cross-process call completion, call process is shown in dotted line, call transact(...)method calculation data (3 and 4) passed to the server, the server will complete the calculation results by the onTransact(...)method returns. transact and onTransact by sequence data are completed, they are implemented as follows

// transact
public int add(int a, int b) throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    int _result;
    try {
        // DESCRIPTOR 为 ICalculateService 全限定类名
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeInt(a);
        _data.writeInt(b);
        mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
        _reply.readException();
        _result = _reply.readInt();
    } finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

// onTransact
@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 TRANSACTION_add: {
            data.enforceInterface(descriptor);
            int _arg0;
            _arg0 = data.readInt();
            int _arg1;
            _arg1 = data.readInt();
            // 此处 add 方法调用 CalculateService 中的 add 方法完成计算
            int _result = this.add(_arg0, _arg1);
            reply.writeNoException();
            reply.writeInt(_result);
            return true;
        }
        ...
    }
}

These are the top API interface Binder mechanism, the following will explain the principles underlying implementation of Binder.

The underlying principle Binder

Published 11 original articles · won praise 0 · Views 4373

Guess you like

Origin blog.csdn.net/weixin_46221133/article/details/104117477