2019-02-13 AIDL 在 studio 中簡單使用

通過使用AIDL在兩個(gè)應(yīng)用間實(shí)現(xiàn)通信

一、創(chuàng)建 service 端

新建一個(gè) service project 在對應(yīng)路徑下右鍵 -> new -> AIDL -> AIDL File 系統(tǒng)會幫我們自動生成 AIDL 路徑和對應(yīng)的 AIDL 文件


WechatIMG396.jpeg

生成完成后對應(yīng)的目錄如下:


WechatIMG397.jpeg

編寫 IUserCalcAIDL.aidl 文件
//這里只是簡單的獲取用戶名和密碼
interface IUserCalcAIDL {
     String getUserName();

     String getPassWord();
}

在 java 目錄下新建一個(gè) service

public class UserService extends Service {
    //如果此時(shí)沒有這個(gè)類,重新構(gòu)建一下項(xiàng)目
    private final IUserCalcAIDL.Stub mBind = new IUserCalcAIDL.Stub() {

        @Override
        public String getUserName() throws RemoteException {
            return "mao_kk";
        }

        @Override
        public String getPassWord() throws RemoteException {
            return "1234567890";
        }

    };

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

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

繼續(xù)在 AndroidManifest.xml 中配置 service

    <service
            android:name=".UserService"
            //設(shè)置外部可以訪問
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                //配置 action 5.0以后不能使用隱式方式訪問,所以要設(shè)置
                <action android:name="com.androidtv.aidlservice.AIDLService" />
            </intent-filter>
        </service>

到這里 service 端的配置完成,此時(shí)的目錄結(jié)構(gòu)為:


WechatIMG398.jpeg

運(yùn)行該項(xiàng)目,等待

二、創(chuàng)建 client 端

新建一個(gè) client project 在對應(yīng)的路徑下將 service 端下的 aidl 文件夾拷貝過來,此時(shí)項(xiàng)目結(jié)構(gòu)為:


WechatIMG399.jpeg

注意,如果手動編寫 aidl 文件夾,需要包名和 service 端的相對應(yīng),下面來編寫 MainActivity ,MainActivity中只有幾個(gè)按鈕,bindService 、獲取用戶名、獲取密碼,布局簡單,就不貼 xml 代碼了

    private IUserCalcAIDL mIUserCalcAIDL;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("TAG", "onServiceConnected: ---->");
            mIUserCalcAIDL = IUserCalcAIDL.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("TAG", "onServiceDisconnected: ----->");
            mIUserCalcAIDL = null;
        }
    };

    private void bindAIDLService() {
        //5.0 之后不能隱式啟動
        Intent intent = new Intent();
        intent.setAction("com.androidtv.aidlservice.AIDLService");
        intent.setPackage("com.androidtv.aidlservice");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void getPassWord() {
        if (mIUserCalcAIDL != null) {
            try {
                //獲取密碼 這里得到的就是 1234567890
                String passWord = mIUserCalcAIDL.getPassWord();
                Toast.makeText(this, passWord, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "服務(wù)未連接", Toast.LENGTH_SHORT).show();
        }
    }

    private void getUserName() {
        if (mIUserCalcAIDL != null) {
            try {
                //獲取用戶名 這里的到的就是 mao_kk
                String passWord = mIUserCalcAIDL.getUserName();
                Toast.makeText(this, passWord, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "服務(wù)未連接", Toast.LENGTH_SHORT).show();
        }
    }

到這里,一個(gè)簡單的 AIDL 就結(jié)束了,需要注意的是,如果需要使用自定義的數(shù)據(jù)類型需要進(jìn)行配置

三、自定義數(shù)據(jù)類型

在 service 端中 java 目錄下新增需要的自定義類型,注意:該類型是需要實(shí)現(xiàn) Parcelable 接口

    //自定義 Book 類型,里面包含一個(gè) bookName 字段
    public class Book implements Parcelable {

    private String bookName;

    protected Book() {

    }

    protected Book(Parcel in) {
        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 dest, int flags) {
        dest.writeString(bookName);
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
}

在 aidl 目錄下新增 Book.aidl 文件,定義自定義類型

    // IUserCalcAIDL.aidl
package com.androidtv.aidlservice;

// 定義 Book 
parcelable Book;

重新編寫 IUserCalcAIDL.aidl 文件

    package com.androidtv.aidlservice;

// import 導(dǎo)入自定義類型
import com.androidtv.aidlservice.Book;

interface IUserCalcAIDL {
   
   String getUserName();

   String getPassWord();
   //獲取 books 列表
   List<Book> getBooks();
   //往 books 列表中增加數(shù)據(jù) 
   //注意 需要在類型前加 in 
   void addBook(in Book book);
}

重新編譯項(xiàng)目,修改 UserService 內(nèi)容

    public class UserService extends Service {
    List<Book> mBookList = new ArrayList<>();
    //多了兩個(gè)實(shí)現(xiàn)方法
    private final IUserCalcAIDL.Stub mBind = new IUserCalcAIDL.Stub() {

        @Override
        public String getUserName() throws RemoteException {
            return "mao_kk";
        }

        @Override
        public String getPassWord() throws RemoteException {
            return "1234567890";
        }

        @Override
        public List<Book> getBooks() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }

    };

    @Override
    public void onCreate() {
        super.onCreate();
        //默認(rèn)增加一個(gè)book
        Book book = new Book();
        book.setBookName("語文");
        mBookList.add(book);
    }

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

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

此時(shí) service 端的結(jié)構(gòu)為


WechatIMG403.jpeg

service 端的修改完成,接下來修改 client 端,將 service 端下的aidl 文件夾重新拷貝一份到 client 端 中,同時(shí)將自定義的數(shù)據(jù)類型也拷貝過去,注意:自定義類型的包名需要和 service 端的相對應(yīng),完成后 client 端的項(xiàng)目結(jié)構(gòu)為:


WechatIMG400.jpeg

在 MainActivity 中可以有對應(yīng)操作代碼

    private void addBookList() {
        if (mIUserCalcAIDL != null) {
            try {
                Book book = new Book();
                book.setBookName("數(shù)學(xué)");
                mIUserCalcAIDL.addBook(book);
                List<Book> books = mIUserCalcAIDL.getBooks();
                for (Book book1 : books) {
                    Log.e("TAG", "addBookList: --->" + book1.getBookName());
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "服務(wù)未連接", Toast.LENGTH_SHORT).show();
        }
    }

    private void getBookList() {
        if (mIUserCalcAIDL != null) {
            try {
                List<Book> books = mIUserCalcAIDL.getBooks();
                for (Book book : books) {
                    Log.e("TAG", "getBookList: ----->" + book.getBookName());
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "服務(wù)未連接", Toast.LENGTH_SHORT).show();
        }
    }

到此結(jié)束

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容