background

In my work, I often encounter the need for inter-process communication, but every time I realize it through AIDL, I feel that the steps are very tedious. Therefore, I designed and open source this IPC library in my spare time. The design idea is based on Retrofit’s approach of generating implementation classes through dynamic proxies, which perfectly combines AIDL with Retrofit’s features.

It’s a new way for you to play it, and in three minutes, you’ll love this open source library as much as I did

Project address: github.com/codezjx/And…

Introduction to the

AndLinker is an IPC (inter-process communication) library for Android. It combines AIDL and Retrofit features and works seamlessly with RxJava and RxJava2 Call Adapters. The design of the project and part of the code references the great Retrofit project.

configuration

Add the JCenter () repository to the project root directory in build.gradle

allprojects {
    repositories {
        jcenter()
    }
}Copy the code

Add the following dependencies to your App’s build.gradle

Dependencies {implementation 'com. Codezjx. Library: andlinker: 0.7.0'}Copy the code

features

  • Replace the AIDL interface with a plain Java interface
  • Generate an IPC implementation of the remote service interface like Retrofit
  • Supported Call Adapters:Call.RxJava Observable.RxJava2 Observable & Flowable
  • Remote service callback mechanism is supported
  • All data types of AIDL are supported
  • Support for all AIDL data oriented tags:in.out.inout
  • Support the AIDLonewayThe keyword

Quick start

Modify and implement the remote service interface IRemoteService with the @className and @MethodName annotations

@ClassName("com.example.andlinker.IRemoteService") public interface IRemoteService { @MethodName("getPid") int getPid();  @MethodName("basicTypes") void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); } private final IRemoteService mRemoteService = new IRemoteService() { @Override public int getPid() { return android.os.Process.myPid(); } @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does something } };Copy the code

In the server App, create the AndLinkerBinder object and register the interface implementation above. It is then returned in the onBind() method and exposed to the client

private AndLinkerBinder mLinkerBinder; public class RemoteService extends Service { @Override public void onCreate() { super.onCreate(); mLinkerBinder = AndLinkerBinder.Factory.newBinder(); mLinkerBinder.registerObject(mRemoteService); } @Override public IBinder onBind(Intent intent) { return mLinkerBinder; }}Copy the code

In the client App, an AndLinker object is created through Builder and an IPC implementation of the IRemoteService remote interface is generated through the create() method

public class BindingActivity extends Activity { private AndLinker mLinker; private IRemoteService mRemoteService; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLinker = new AndLinker.Builder(this) .packageName("com.example.andlinker") .action("com.example.andlinker.REMOTE_SERVICE_ACTION") .build(); mLinker.bind(); mRemoteService = mLinker.create(IRemoteService.class); } @Override protected void onDestroy() { super.onDestroy(); mLinker.unbind(); }}Copy the code

With everything in place, all methods in the mRemoteService object are now IPC methods and can be called directly

int pid = mRemoteService.getPid(); MRemoteService. BasicTypes (1, 2 l, true, 3.0 f, 4.0 d, "STR");Copy the code

Supported data types

AndLinker supports all AIDL data types: – All primitive types in the Java language (e.g. Int, long, char, Boolean, Etc.) – String – CharSequence – Parcelable – List (all elements in List must be data types supported in this List) – Map (all elements in Map must be data types supported in this List)

Use the advanced

Call Adapters

In the client App, you can copy and modify the return value of the remote service interface wrapper method

@ClassName("com.example.andlinker.IRemoteService")
public interface IRemoteService {

    @MethodName("getPid")
    Observable<Integer> getPid();

    @MethodName("basicTypes")
    Call<Void> basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 
        double aDouble, String aString);
}Copy the code

Register the corresponding Call Adapter Factory in Andlinker. Builder. The rest of the steps are basically the same as Retrofit

new AndLinker.Builder(this)
        ...
        .addCallAdapterFactory(OriginalCallAdapterFactory.create()) // Basic
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  // RxJava2
        .build();Copy the code

Handles remote service interface callbacks

Modify the remote service callback interface IRemoteCallback with @className and @MethodName annotations

@ClassName("com.example.andlinker.IRemoteCallback") public interface IRemoteCallback { @MethodName("onValueChange") void  onValueChange(int value); }Copy the code

The @callback annotation is used to decorate the Callback parameter in the remote method

@MethodName("registerCallback")
void registerCallback(@Callback IRemoteCallback callback);Copy the code

In the client App, implementing the remote service callback interface IRemoteCallback defined above and registering with AndLinker is as simple as that

private final IRemoteCallback mRemoteCallback = new IRemoteCallback() { @Override public void onValueChange(int value) {  // Invoke when server side callback } }; mLinker.registerObject(mRemoteCallback);Copy the code

Specify the data orientation tag

You can specify @in, @out, or @inout annotations for remote method parameters, which mark the direction of data In the underlying Binder, as used In AIDL

@MethodName("directionalParamMethod")
void directionalParamMethod(@In KeyEvent event, @Out int[] arr, @Inout Rect rect);Copy the code

Note: – All non-primitive types must specify a data orientation tag: @in, @out, or @inout to mark the direction of the data. The primitive type defaults to @in, and no other value can be specified. – Parcelable arguments modified with @out or @inout must implement the SuperParcelable interface, otherwise you must manually add this method public void readFromParcel(Parcel in).

use@OneWayannotations

You can use the @oneway annotation on remote methods, which modifies the behavior of remote method calls. When used, the remote method call does not block; it simply sends the data and returns it immediately, as used in AIDL

@MethodName("onewayMethod")
@OneWay
void onewayMethod(String msg);Copy the code

feedback

Welcome to raise issues and PRs!

License

Copyright 2018 codezjx <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copy the code