Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> IPC學習之AIDL

IPC學習之AIDL

編輯:關於Android編程

最近在學習IPC進程間通信,在此記錄下AIDL的使用,並附上一個Demo:服務端每隔一分鐘添加一本書籍,客戶端通過進程間通信,獲取當前服務端的書籍列表,並且服務端對外開放添加、刪除等操作。

服務端:

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 CREATOR = new Creator() {
        @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.aidl
package com.aa.aidlserver;
parcelable Book;
// IBookManager.aidl
package com.aa.aidlserver;
import com.aa.aidlserver.Book;

interface IBookManager {
    //獲取書本列表
    List getBookList();
    //添加書本
    void addBook(in Book book);
    //刪除書本
    void deleteBook(in Book book);
}

注意:

其中Book.aidl用來聲明Book實現了Parcelable接口 因為在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 mBookList = new CopyOnWriteArrayList<>();


    private Binder mBinder = new IBookManager.Stub() {

        @Override
        public List 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);
    }
}



    
        
            
                
                
            
        

        
            
                
            
        
    

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 mAdapter;
    private List 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 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說簡單也不簡單,難也並不難,還是需要根據實際需求來做的。

Github AIDLServer
Github AIDLClient

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved