【Android开发艺术】读懂AIDL系列文章(一)

【Android开发艺术】读懂AIDL系列文章(一)

一、先上Github源码地址:Aidl

二、写一个简单的Aidl使用:

1、Aidl的应用场景:

进程间通信或者不同App间通信(此处写为服务端servelapp和客户端clientapp)

举例:服务端用来提供数据,客户端从服务端查询数据和新增数据。

1.1、服务端

写一个activity用来启动service(其实这一步可以省略)。

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void click(View view){
        startService(new Intent(this, BookManagerService.class));
    }
}
写BookManagerService服务端

public class BookManagerService extends Service {
   private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
   private Binder mBinder = new IBookManager.Stub(){
       @Override
       public List<Book> getBookList() throws RemoteException {
           return mBookList;
       }
       @Override
       public void addBook(Book book) throws RemoteException {
           mBookList.add(book);
       }
   };
   public BookManagerService() {
   }
   @Override
   public void onCreate() {
       super.onCreate();
       mBookList.add(new Book(1,"Android"));
       mBookList.add(new Book(2,"Ios"));
   }
   @Override
   public IBinder onBind(Intent intent) {
       // TODO: Return the communication channel to the service.
       return mBinder;
   }
其中

1、第二行CopyOnWriteArrayList:多线程访问用来在AIDL中处理线程同步;

2、第3-12行:service返回的mBinder通过AIDL接口IBookManager的Stub方法获得一个Binder对象。

private Binder mBinder = new IBookManager.Stub(){
       @Override
       public List<Book> getBookList() throws RemoteException {
           return mBookList;
       }
       @Override
       public void addBook(Book book) throws RemoteException {
           mBookList.add(book);
       }
   };

此处用到了aidl生成的Binder类。实际上是通过自动生成的Binder类IBookManager.java来实现进程间通信。(也就是我们可以绕开aidl自己手工实现Binder进程间通信,只不过aidl让这个过程变成了透明,变得非常简单)。

注释:如何新建一个IBookManager.aidl

新建的aidl接口如下格式:

package haibo.com.servelapp;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * 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);
}
修改成我们需要的aidl接口后如下:

// IBookManager.aidl
package haibo.com.servelapp;

// Declare any non-default types here with import statements
import haibo.com.servelapp.Book;

interface IBookManager {

    List<Book> getBookList();

    void addBook(in Book book);
}
其中Book需要手动导入import,即使在同一个包中。另外,除了基本数据类型外,其他类型,需要加上in out inout其中之一,表示输入输出类型参数。

import haibo.com.servelapp.Book;

此处的Book并不是Book.java而是Book.aidl接口,因为aidl接口中只能访问aidl接口。如下:

// Book.aidl
package haibo.com.servelapp;

// Declare any non-default types here with import statements
parcelable Book;
此处再引用Book的序列化对象如下:
Book类需要是实现Android序列化接口的类,因为aidl通信的对象是一个序列化和反序列化的过程。

package haibo.com.servelapp;

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

/**
 * Created by user on 2018/1/26.
 */

public class Book implements Parcelable {
    private int id;
    private String name;

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

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

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

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

    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 String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
最后需要注意的两点,也是容易忽略的两点,如果需要让其他进程访问当前服务端的service,需要在manifest中设置访问action

<service
            android:name=".service.BookManagerService"
            android:enabled="true"
            android:exported="true"
            >
            <intent-filter>
                <action android:name="haibo.com.servelapp.service.BookManagerService" />
            </intent-filter>
        </service>
此处有一个坑,Android Studio中构建aidl对象的时候会发现找不到Book类。需要在gradle文件中配置如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "haibo.com.servelapp"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            java.srcDirs = ['src/main/java', 'src/main/aidl']
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}
其中此处为需要配置的地方

sourceSets {
        main {
            java.srcDirs = ['src/main/java', 'src/main/aidl']
        }
    }

1.2、客户端:

客户端需要完全复制服务端的aidl包。完全复制,完全复制,完全复制,重要的事情说三遍!不要改包名,不要改任何东西。

客户端代码比较简单,直接上代码:

public class MainActivity extends Activity {
    private TextView textView;
    private EditText edit_query;
    private IBookManager bookManager;
    private static int count = 0;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            bookManager = IBookManager.Stub.asInterface(service);
            try {
                List<Book> list = bookManager.getBookList();
                count = list.size();
                textView.setText("getBookList结果是:list.toString());
                Log.e("MainActivity",list.toString());

            } 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);
        textView = (TextView) findViewById(R.id.booklist);
        edit_query = (EditText) findViewById(R.id.edit_query);
        //初始化启动service
        Intent intent = new Intent("haibo.com.servelapp.service.BookManagerService");
        bindService(intent,connection, Context.BIND_AUTO_CREATE);
    }

    public void addBook(View view) throws RemoteException {
        //添加一本书并展示
        String str = edit_query.getText().toString();
        if (!TextUtils.isEmpty(str)){
            coun;
            bookManager.addBook(new Book(count,str));
        }
        List<Book> newlist = bookManager.getBookList();
        textView.setText("新getBookList结果是:newlist.toString());
        Log.e("MainActivity",newlist.toString());
    }
}
第34,35行,通过bindService建立连接

//初始化启动service
        Intent intent = new Intent("haibo.com.servelapp.service.BookManagerService");
        bindService(intent,connection, Context.BIND_AUTO_CREATE);
第9行,在连接中获取aidl接口IBookManager

bookManager = IBookManager.Stub.asInterface(service);
至此,就完成了第一版本的aidl进程间通信代码,实现了客户端访问服务端的书籍数据,并向服务端添加书籍。

此处代码在github中第一次提交(添加书籍和查询书籍列表)的代码可见。

 本文完,

 AIDL未完待续。

















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值