IPC学习之AIDL小试牛刀

来源:互联网 发布:英语同义词词典 知乎 编辑:程序博客网 时间:2024/05/16 09:40

最近在学习IPC进程间通信,在此记录下AIDL的使用,并附上一个Demo:服务端每隔一分钟添加一本书籍,客户端通过进程间通信,获取当前服务端的书籍列表,并且服务端对外开放添加、删除等操作。

效果展示
终于明白鸿洋所说的App效果图尽力的意思了!Android屏幕截图方法可参考:http://www.jianshu.com/p/9a1825e679b7

服务端:

1、新建一个AIDLServer工程,创建一个Parcelable接口类Book

package com.aa.aidlserver;import android.os.Parcel;import android.os.Parcelable;public class Book implements Parcelable {    public String name;    public String describe;    public Book(String name, String describe) {        this.name = name;        this.describe = describe;    }    protected Book(Parcel in) {        name = in.readString();        describe = 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.writeString(name);        parcel.writeString(describe);    }}

2、创建两个aidl文件:Book.aidl和IBookManager.aidl

// Book.aidlpackage com.aa.aidlserver;parcelable Book;
// IBookManager.aidlpackage com.aa.aidlserver;import com.aa.aidlserver.Book;interface IBookManager {    //获取书本列表    List<Book> getBookList();    //添加书本    void addBook(in Book book);    //删除书本    void deleteBook(in Book book);}

注意:

  1. 其中Book.aidl用来声明Book实现了Parcelable接口
  2. 因为在IBookManager中使用了Book参数,所以无论Book.java是否在同一个包名下,都必须进行一次import

3、创建自定义Service,创建一个IBookManager.Stub对象,即一个Binder对象,重写onBind方法返回这个对象。然后在AndroidManifest中声明此Service,并加入action

package com.aa.aidlserver;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 android.util.Log;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;public class AIDLService 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);        }        @Override        public void deleteBook(Book book) throws RemoteException {            mBookList.remove(0);        }    };    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        if(mBookList.size() == 0) {            mBookList.add(new Book("他们最幸福", "一个屌丝写的书"));            mBookList.add(new Book("晓松奇谈", "矮大紧写的书"));        } else {            addBook();        }        return super.onStartCommand(intent, flags, startId);    }    /**     * 通过定时任务来添加书本信息     */    private void addBook() {        Log.e("TAG", "Adding...");        int len = mBookList.size() + 1;        String name = "图书" + len;        String describe = "这是第" + len + "本书";        Book book = new Book(name, describe);        mBookList.add(book);    }}
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"          package="com.aa.aidlserver">    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>        <service            android:name=".AIDLService"            android:process=":remote">            <intent-filter>                <action android:name="com.aa.aidlserver.AIDLService"/>            </intent-filter>        </service>    </application></manifest>

4、在MainActivity中使用AlarmManager每隔一分钟创建(打开)Service

package com.aa.aidlserver;import android.app.AlarmManager;import android.app.PendingIntent;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);        initAlarmManager();    }    /**     * 初始化定时任务     */    private void initAlarmManager() {        Intent intent = new Intent();        // 设置Intent的Action 属性        intent.setAction("com.aa.aidlserver.AIDLService");        // Android 5.0以上需要设置包名        intent.setPackage("com.aa.aidlserver");        //创建一个PendingIntent对象,包含了startService操作        PendingIntent pi = PendingIntent.getService(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);        long intervalMillis = 60 * 1000;        //创建一个系统级定时器,即使熄屏状态也会每隔一分钟启动一次Service添加书本(注:部分定制系统定时器不准)        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), intervalMillis, pi);    }}

5、在app的build.gradle文件的android节点中添加以下代码,可解决找不到Book类的问题

sourceSets {    main {        manifest.srcFile 'src/main/AndroidManifest.xml'        java.srcDirs = ['src/main/java', 'src/main/aidl']        resources.srcDirs = ['src/main/java', 'src/main/aidl']        aidl.srcDirs = ['src/main/aidl']        res.srcDirs = ['src/main/res']        assets.srcDirs = ['src/main/assets']    }}

至此服务端就开发完毕了,相比之下,客户端的就简单一些。

客户端:

1、新建一个AIDLClient工程,将AIDLServer工程的app\src\main\aidl目录拷贝到AIDLClient工程的app\src\main目录下,不需任何修改(注意这里的包名、文件都与AIDLServer是一致的)

2、服务端每隔一分钟会添加一本书,所以在客户端MainActivity中获取当前服务端书本列表并显示,也可进行添加、删除等操作

package com.aa.aidlclient;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 android.view.View;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.Toast;import com.aa.aidlserver.Book;import com.aa.aidlserver.IBookManager;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private ListView mListView;    private ArrayAdapter<String> mAdapter;    private List<String> mBooks = new ArrayList<>();    private Button btnLoadmore, btnAdd, btnDetele;    private IBookManager mIBookManager;    private ServiceConnection mServiceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            //Service已连接            mIBookManager = IBookManager.Stub.asInterface(iBinder);        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            //Service已断开            mIBookManager = null;        }    };    private void toast(String msg) {        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();        Log.e("AA", "收到Log:" + msg);    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mListView = (ListView) findViewById(R.id.lv_main);        btnLoadmore = (Button) findViewById(R.id.btn_main_loadmore);        btnLoadmore.setOnClickListener(this);        btnAdd = (Button) findViewById(R.id.btn_main_add);        btnAdd.setOnClickListener(this);        btnDetele = (Button) findViewById(R.id.btn_main_delete);        btnDetele.setOnClickListener(this);        bindAIDLService();    }    @Override    protected void onDestroy() {        unbindAIDLService();        super.onDestroy();    }    /**     * 绑定AIDL服务     */    private void bindAIDLService() {        Intent intent = new Intent("com.aa.aidlserver.AIDLService");        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        // Android 5.0以上需要设置包名        intent.setPackage("com.aa.aidlserver");        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);    }    /**     * 解绑AIDL服务     */    private void unbindAIDLService() {        if(mIBookManager != null) {            unbindService(mServiceConnection);        }    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.btn_main_loadmore:                //加载更多                try {                    List<Book> books = mIBookManager.getBookList();                    if(books != null && books.size() > 0) {                        if(mBooks.size() > 0) {                            mBooks.clear();                        }                        //解析数据                        for(Book book : books) {                            mBooks.add("Name:" + book.name + " --- Describe:" + book.describe);                        }                        //填充数据                        mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, mBooks);                        mListView.setAdapter(mAdapter);                    }                } catch (RemoteException e) {                    e.printStackTrace();                }                break;            case R.id.btn_main_add:                //新增图书                int len = mBooks.size() + 1;                String name = "图书" + len;                String describe = "这是第" + len + "本书";                Book book = new Book(name, describe);                try {                    mIBookManager.addBook(book);                    mBooks.add("Name:" + book.name + " --- Describe:" + book.describe);                    mAdapter.notifyDataSetChanged();                } catch (RemoteException e) {                    e.printStackTrace();                }                break;            case R.id.btn_main_delete:                //删除图书                if(mBooks.size() > 0) {                    try {                        Book book1 = mIBookManager.getBookList().get(0);                        mIBookManager.deleteBook(book1);                        mBooks.remove(0);                        mAdapter.notifyDataSetChanged();                    } catch (RemoteException e) {                        e.printStackTrace();                    }                } else {                    toast("已经没有书可以删除了");                }                break;        }    }}

3、客户端也需要在app的build.gradle文件的android节点中添加以下代码,解决找不到Book类的问题

sourceSets {    main {        manifest.srcFile 'src/main/AndroidManifest.xml'        java.srcDirs = ['src/main/java', 'src/main/aidl']        resources.srcDirs = ['src/main/java', 'src/main/aidl']        aidl.srcDirs = ['src/main/aidl']        res.srcDirs = ['src/main/res']        assets.srcDirs = ['src/main/assets']    }}

其实,AIDL说简单也不简单,难也并不难,还是需要根据实际需求来做的。

CSDN源码下载
Github AIDLServer
Github AIDLClient

1 0
原创粉丝点击