一、概述
本文将讲述基本的aidl使用方法实现进程间通信,后续将讲述如果将自己的写的服务加入到系统服务中,提供给系统应用使用,典型案例应用锁。
二、编写思路
1、服务器端定义aidl以及传递的bean类,然后编写具体aidl实现类,新建服务在onBind方法中返回实现的binder类对象。
2、客户端需要新建服务端定义的aidl以及相关类,建议服务器端把aidl以及相关的类定义在一个包中。客户端要使用时以及拷贝过来。
三、编码具体实现demo
1、服务器端*
1、在main下新建一个aidi文件夹,在新建一个包,然后定义Book.java类,实现Parcelable接口,代码如下
package com.android.topwise.applock;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
public int bookId;
public String bookName;
public Book(int id, String name) {
this.bookId = id;
this.bookName = name;
}
public Book() {
}
protected Book(Parcel in) {
bookId = in.readInt();
bookName = 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 parcel, int i) {
parcel.writeInt(bookId);
parcel.writeString(bookName);
}
}
2、新建aidl接口,我在这里新建的是IBookManager.aidl,其中定义俩个方法,代码如下,记到导入需要使用的实体类,并创建对应的aidl文件,我这里使用Book类,定义Book.aidl。
// IBookManager.aidl
package com.android.topwise.applock;
// Declare any non-default types here with import statements
import com.android.topwise.applock.Book;
interface IBookManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void addBook(in Book book);
List<Book> getBookList();
}
3、Book.aidl代码如下
// Book.aidl
package com.android.topwise.applock;
parcelable Book;
4、服务端还需要写一个服务类,并写一个binder实现类,代码如下
package com.android.topwise.applock;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.ArrayList;
import java.util.List;
public class BookService extends Service {
private List<Book> books = new ArrayList<>();
public BookService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new MyBookManager();
}
private final class MyBookManager extends IBookManager.Stub
{
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void addBook(Book book) throws RemoteException {
books.add(book);
}
@Override
public List<Book> getBookList() throws RemoteException {
return books;
}
}
}
2、客户端
1、直接复制服务器端aidl的包,然后直接去绑定服务器端的服务获取接口对象。代码如下
package com.android.topwise.applock;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
@Bind(R.id.id_tv_show)
TextView idTvShow;
@Bind(R.id.id_btn_add)
Button idBtnAdd;
@Bind(R.id.id_btn_get)
Button idBtnGet;
private IBookManager mIBookManager;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mIBookManager = IBookManager.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Intent intent = new Intent("com.android.topwise.applock.IBookManager");
Intent intentHide = createExplicitFromImplicitIntent(this, intent);
bindService(intentHide, mServiceConnection, Context.BIND_AUTO_CREATE);
}
//此方法可以将返回一个可以隐式启动服务的Intent
public Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
@OnClick({R.id.id_btn_add, R.id.id_btn_get})
public void onClick(View view) {
switch (view.getId()) {
case R.id.id_btn_add:
Book book = new Book(0, "第一行代码");
try {
mIBookManager.addBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.id_btn_get:
try {
List<Book> books = mIBookManager.getBookList();
if (books.size() > 0) {
idTvShow.setText(books.get(0).bookName);
}
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}
四、aidl的基本用法就以上所示,相信很多读者都和我一样,在最开始接触的时候会困惑,为什么要如此麻烦,其实aidl是为了实现进程间多线程的情况,在平时的日常应用开发中很少需要进程间通信,但是在系统开发中就非常重要了,因为binder是android 实现进程间通信特有的方式,SystemServer进程中的服务都是用binder的方式进行通信的,例如ActivityManagerServce等,在app开发中Content.getSystemService(“”)的方法获取到系统服务端的实例就是binder进程间通信,只是这里的进程是SystemServer进程与我们的APP进程进行通信而已。