淺析 - AIDL簡單例子

尊重每個人的付出,轉載請點這裏 : http://blog.csdn.net/hanj456/article/details/52433718

傳遞基本數據類型

簡單三步

Step 1

準備AIDL文件 ,注意:文件寫完後需要 Sync Project一下!

package cn.test.aidlb;

interface IRemoteService {

    int getResult();

    void setText(String content);
}

Step 2

準備service ,要點:新建service文件後馬上在清單文件中配置一下:
<service android:name=".MyService"
       android:process="com.test.action">
       <intent-filter>
           <action android:name="com.test.action"/>
           <category android:name="android.intent.category.DEFAULT"/>
       </intent-filter>
   </service>

服務端

public class MyService extends Service {
    private static final String TAG = "MyService";

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("service onBind");
        return mBinder;
    }

    private IRemoteService.Stub mBinder = new IRemoteService.Stub() {

        @Override
        public int getResult() throws RemoteException {
            int sum=5*4/2;
            return sum;
        }

        @Override
        public void setText(String content) throws RemoteException {
            Log.i(TAG, content+" 調用B應用的方法");
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("service onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("service onDestroy");
    }
}

Step 3

首先將service端應用中的aidl包複製到activity所在的應用中,在activity中進行綁定服務,注意:android 5.0以後 intent需要設置包名

客戶單

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private IRemoteService mService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * 點擊按鈕後綁定服務
     * @param view
     */
    public void bind(View view){
        Intent intent = new Intent();
        intent.setAction("com.test.action");
        intent.setPackage("cn.test.aidlb");
        bindService(intent,sc, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection sc = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IRemoteService.Stub.asInterface(service);
            try {
                int result = mService.getResult();
                mService.setText("我在A應用 ");
                Log.i(TAG, "onServiceConnected: result="+result);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };


    /**
     * activity銷燬時解綁服務
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (sc!=null){
            unbindService(sc);
        }
    }
}

傳遞對象

服務端簡單6步

Step1

創建對象文件Person.java,實現Parcelable接口

public class Person implements Parcelable{

    private int age;
    private String name;


    protected Person(Parcel in) {
        age = in.readInt();
        name = in.readString();
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

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

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

    public void readFromParcel(Parcel dest) {
        age = dest.readInt();
        name = dest.readString();
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Step2

創建AIDL文件 Person.aidl ,聲明對象爲序列化

package com.xxx.xxxx;

parcelable Person;

注:parcelable第一個字母p爲小寫

Step3

創建AIDL接口文件 IPerson.aidl,聲明傳遞數據需要的方法,這裏需要重點說明的是數據流向的關鍵字聲明
in ,out , inout 三者的用法和區別:簡單點說就是當你的數據需要從Service端設置,Client端獲取時使用out,
反之使用 in ,如果需要雙向傳遞數據就使用 inout.

package com.test.myServer;

import com.test.myServer.Person;

interface IPerson {

    String inPerson(in Person p);
    String outPerson();
    String inoutPerson(inout Person p);
}

Step4

這一步需要在Model下的 gradle 文件中 android 標籤下加上以下內容,否則完成第五步後編譯會報找不到
Person對象的錯誤:

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

Step5

新建一個service文件,要點就是實現返回我們自己定義的AIDL接口

public class AidlService extends Service {

    private MyBinder mBinder;

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


    private class MyBinder extends IPerson.Stub{
        @Override
        public String inPerson(Person p) throws RemoteException {
            String person = "age="+p.getAge()+",name="+p.getName();
            Log.i("test", "inPerson: "+person);
            return person;
        }

        @Override
        public String outPerson() throws RemoteException {
            Person p = new Person();
            p.setAge(22);
            p.setName("Tom");
            return p.toString() ;
        }

        @Override
        public String inoutPerson(Person p) throws RemoteException {
            Log.i("test", "inPerson: "+p.toString());
            return p.toString();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new MyBinder();
    }
}

Step6

在清單文件中聲明創建的service文件,需要注意的是要加上action作爲唯一的意圖標記,最後將服務端創建的aidl文件及Person.java文件複製到客戶端。

<service android:name=".AidlService">
            <intent-filter>
                <action android:name="com.test.myServer.action.AIDL_SERVICE"/>
            </intent-filter>
        </service>

再來看看客戶端,這邊就比較簡單,重點是把服務端需要的文件複製過來之後需要clean一下project,如果在
(客戶端)/build/generated/source/aidl/debug下出現service文件所在的包和aidl文件,那麼恭喜你,下面
基本就沒有什麼難度了。

public class ComplexActivity extends AppCompatActivity{

    private TextView mTv_content;
    private EditText mEt_age;
    private EditText mEt_name;
    private IPerson mIPerson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_complex);
        initView();
        bind();
    }

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIPerson = IPerson.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mIPerson = null;
        }
    };

    private void bind() {
        Intent intent = new Intent();
        intent.setAction("com.test.myServer.action.AIDL_SERVICE2");
        intent.setPackage("com.test.myServer");
        bindService(intent,conn, Service.BIND_AUTO_CREATE);
        Log.i("test", "bind: 綁定服務");
    }

    private void initView() {
        mTv_content = (TextView) findViewById(R.id.tv_content);
        mEt_age = (EditText) findViewById(R.id.et_age);
        mEt_name = (EditText) findViewById(R.id.et_name);
    }

    /**
     * 調用aidl接口中的inPerson方法,該方法聲明的數據流向是 in,
     * 表示由客戶端設置數據,服務端可以接收客戶端傳過來的數據
     * @param v
     */
    public void setInfo(View v){
        String age = mEt_age.getText().toString().trim();
        String name = mEt_name.getText().toString().trim();
        try {
            if (!TextUtils.isEmpty(age)&&!TextUtils.isEmpty(name)){
                mIPerson.inPerson(new Person(Integer.parseInt(age),name));
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    /**
     * 調用aidl接口中的outPerson方法,該方法聲明的數據流向是 out,
     * 表示數據流向是從服務端傳輸到客戶端,所以在服務端中設置數據,
     * 在客戶端中進行顯示數據
     * @param v
     */
    public void showInfo(View v){
        try {
            String content = mIPerson.outPerson();
            mTv_content.setText(content);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }


    /**
     * 調用aidl接口中的inoutPerson方法,該方法聲明的數據流向是 inout,
     * 表示數據是可以雙向流動的,既可以在客戶端設置數據從服務端取數據,
     * 也可以從服務端設置數據,在客戶端取數據
     * @param v
     */
    public void showDoubleInfo(View v){
        String age = mEt_age.getText().toString().trim();
        String name = mEt_name.getText().toString().trim();
        try {
            if (!TextUtils.isEmpty(age)&&!TextUtils.isEmpty(name)){
                mIPerson.inoutPerson(new Person(Integer.parseInt(age),name));
                //String content = mIPerson.inoutPerson(); 
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}
發佈了19 篇原創文章 · 獲贊 18 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章