Android's AIDL cross-process communication - IPC mechanism (2)

This article mainly records the implementation process of AIDL under Android Studio

1. Server implementation

1. Create the Book class
Book class is in the root directory corresponding to the package name (here the package name is com.example.lgf.aidl), otherwise there will be problems. The Book class is used in AIDL, so to implement the Parcelable interface, the code is as follows:

package com.example.lgf.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {
    public int index;
    public String name;

    public Book(int index, String name) {
        this.index = index;
        this.name = name;
    }

    protected Book(Parcel in) {
        index = in.readInt();
        name = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(index);
        dest.writeString(name);
    }
}

2. Create the IBookManager.aidl file
In Project mode, right-click any file in the module, then select New–>AIDL–>AIDL File, as shown below:
write picture description here
Then, enter the AIDL file name in the pop-up dialog box, where IBookManager is used as the For example, as shown in the figure below After
write picture description here
entering the file name, the aidl directory will be generated under main and the corresponding package name and AIDL file will be generated, as shown in the figure below
write picture description here
Modify the IBookManager.aidl file, remove the default method, and add the addBook method and the getBookList method. The code is as follows:

// IBookManager.aidl
package com.example.lgf.aidl;

// Declare any non-default types here with import statements
import com.example.lgf.aidl.Book; // 1

interface IBookManager { 
   void addBook(in Book book); // 2
   List<Book> getBookList();
}

It should be noted that in the above code comments, mark 1: indicates that the class used needs to be imported, because the Book class is used here; mark 2: In addition to the basic data type, other types of parameters must be marked with the direction (in, out or inout, in represents input parameters, out represents output parameters, and inout represents input and output).
3. Create Book.aidl file

If a custom Parcelable object is used in the AIDL file, an AIDL file with the same name must be created

Because the custom Parcelable object Book is used in the IBookManager.aidl file, it is necessary to create a Book.aidl file with the same name as Book, right-click in the package where IBookManager.aidl is located, select New->File, and enter Book in the pop-up dialog box. aidl, then add the following code:

package com.example.lgf.aidl;
parcelable Book; 

Each class in AIDL that implements the Parcelable interface needs to create a corresponding AIDL file in the way of the above code, and declare that class as parcelable.
4. Compile the project
After executing the above operations, compile the project, and then generate the corresponding class under the corresponding module's build/generated/source/aidl/debug/package name , as shown below:
write picture description here
5. The remote server implements the
creation of a Binder object and onBind Return it, this object inherits from IBookManager.Stub and implements its internal AIDL methods.

package com.example.lgf.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class BookManagerService extends Service {
    private List<Book> bookList = new ArrayList<>();
    private Binder binder = new IBookManager.Stub() {
        @Override
        public void addBook(Book book) throws RemoteException {
            bookList.add(book);
        }

        @Override
        public List<Book> getBookList() throws RemoteException {
            return bookList;
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        bookList.add(new Book(1, "JAVA"));
        bookList.add(new Book(2, "Android"));
    }

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

6. Register Service
and add the following code in AndroidManifest.xml

<service android:name=".BookManagerService" android:exported="true"/>

Since then, the remote server is doing a good job.

Second, the client implementation

The implementation of whether the client belongs to the same application according to multiple processes is slightly different.
1. Different processes
of the same application If they are different processes of the same application, you need to add the android:process attribute to the service registration of the server, as follows:

<service android:name=".BookManagerService" android:process=":remote"/>

At this point, in the same module, the client implementation code is as follows:

package com.example.lgf.aidl;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private IBookManager iBookManager;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iBookManager = IBookManager.Stub.asInterface(service);
            try {
                iBookManager.addBook(new Book(3, "Kotlin"));
                List<Book> bookList = iBookManager.getBookList();
                Log.d("MainActivity", "book size-->" + bookList.size());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent(this, BookManagerService.class), serviceConnection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

2. Different applications
If it is a different application, you need to copy the server's aidl file and related Parcelable classes to the client, and the package name should be the same, as shown below:
write picture description here
Then compile the project, and then it will be in the module's The corresponding classes are generated under build/generated/source/aidl/debug/package name , as before.
The final implementation code of the client is as follows:

package com.example.lgf.myapplication;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.example.lgf.aidl.Book;
import com.example.lgf.aidl.IBookManager;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private IBookManager iBookManager;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iBookManager = IBookManager.Stub.asInterface(service);
            try {
                iBookManager.addBook(new Book(3, "Python"));
                List<Book> bookList = iBookManager.getBookList();
                Log.d("MainActivity", "book size-->" + bookList.size());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Intent.ACTION_MAIN); // 1
        ComponentName componentName = new ComponentName("com.example.lgf.aidl", "com.example.lgf.aidl.BookManagerService"); // 2
        intent.setComponent(componentName); // 3
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

It should be noted here that in the code comments, annotation 1: Intent.ACTION_MAIN is used for the intent; annotation 2: In the ComponentName constructor parameters, the first is the package name of the server, and the second is the service of the server to be bound. Name; Note 3: To start other application components, you need to call the setComponent method, because Android 5.0 and later do not need to start implicitly.
In addition, the MainActivity of the server needs to modify the startup method of the service, and change it to the following:

package com.example.lgf.aidl;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent service = new Intent(this, BookManagerService.class);
        startService(service);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Intent service = new Intent(this, BookManagerService.class);
        stopService(service);
    }
}

Before running the client, run the server app. Since then, the AIDL communication of different applications has been completed.

Attached:

Example code: [email protected]: the develop branch of Geroff/AIDLTest.git, v1 in the tag is the AIDL of the same application and multiple processes, and v2 is the AIDL of different applications

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325764815&siteId=291194637