1. 程式人生 > >AndroidStudio 使用AIDL

AndroidStudio 使用AIDL

implement 知識庫 fault hub 代碼 知識 show 有一個 什麽

http://blog.csdn.net/ducklikejava/article/details/51559244

  • Android Studio中寫的一個AIDL的小DEMO.
  • 步驟很繁瑣,本來不準備寫的。但是寫一下是為了記錄,這一下午終於跑通了這玩意。
  • 首先,你要有3個 Module,至少兩個,但是最好是3個
    • 一個是你的AIDL文件與它的Service所在的Module
    • 一個是你的客戶端Module,也就是你真正調用AIDLModule
    • 最後一個是你的AIDL需要使用的Parcelable對象存放的Module.如果你要傳遞的只是基本的數據類型,那麽這一項可以不要。如果你直接將該對象創建在你的調用AIDL
      Module中,這一項也可以不要。
    • 為什麽我說要3個Module呢?
      • 因為:第三個Module是作為第一個和第二個的共同依賴存在的。這樣,兩邊都可以使用其中的 對象。
  • 然後,你得先有一個Service,這個Service就是你的AIDL的具體實現。你的AIDL想要什麽功能,完全取決於你的service怎麽寫了。

    • package com.pythoncat.aidl_libiary;
      
      import android.app.Service;
      import android.content.Intent;
      
      public class HelloService extends Service {
          public HelloService() {
          }
          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
  • 好了,你的Service已經有了。但是目前還沒有什麽意義。為了將這個AIDL做得有意思一點,我們假設你是要通過AIDL傳遞復雜的數據,比如Student這樣類似的一個java bean
  • 既然這樣,那麽,我們就需要一個Student類了,註意:必須實現Parcelable,不如就不能AIDL了。差不多這個類就長這樣:
    package com.pythoncat.core.model;

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

    /**
     * Created by pythonCat on 2016/6/1.
     */
    public class Student implements Parcelable {

        public String name;
        public int age;
        public int sex;

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

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

        public Student() {
        }

        protected Student(Parcel in) {
            this.name = in.readString();
            this.age = in.readInt();
            this.sex = in.readInt();
        }

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

            @Override
            public Student[] newArray(int size) {
                return new Student[size];
            }
        };
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

  • 好了,你的Student已經準備好了,現在就是真的要定義一下AIDL文件了。因為這個Student是要通過AIDL去傳遞的,所以這個Student也要成為一個AIDL.

這句話聽起來比較費解,是因為我表達的不夠好。其實說白了,就是要多創建一個名為Student.aidl的文件,這個文件差不多這樣:
    // Student.aidl
    package com.pythoncat.core.model;
    parcelable Student;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

註意了:這個文件所在目錄,必須是在一個aidl目錄下,創建一個和Student.Java同包名的包。比如,我的Student.java是在package com.pythoncat.core.model;中,那麽,我就要在AIDL所在Module中,創建一個aidl目錄,然後在該目錄下創建一個package,package名字就是package com.pythoncat.core.model。最後,在該package下,創建一個Student.aidl文件,裏面就寫上面3句話就好了。

  • 到這裏,Java bean算是真的準備好了,顯示開始寫你的需要被外界調用的AIDL了。這個文件位置隨便寫,你就在java目錄下創建一個.aidl文件好了。文件名假設是IHelloInterface,文件假設是這樣的:

```
// IHelloInterface.aidl
package com.pythoncat.aidl_libiary;

import com.pythoncat.core.model.Student;
// Declare any non-default types here with import statements

interface IHelloInterface {
    /**
     * 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);

    String hello();

    Student getOne();
}
```

註意一下,上面有一個import com.pythoncat.core.model.Student;就是剛才的那個Student.aidl的導入。、

    • ok,到了這裏。已經完成了一小半了。然後是,build -> make project (ctrl+F9)一下。讓android studio幫你一把。
    • build -> make project (ctrl+F9)之後,你會看到你的IHelloInterface .aidl自動跑到aidl目錄裏面去了。不過這個都不是我關心的。
    • 現在,我們完善我們的HelloService:

      package com.pythoncat.aidl_libiary;
      
      import android.app.Service;
      import android.content.Intent;
      import android.os.IBinder;
      import android.os.RemoteException;
      import android.support.annotation.Nullable;
      
      import com.pythoncat.core.model.Student;
      
      /**
       * <action android:name="com.pythoncat.aidl_libiary.HelloService"/>
       * <hr/>
       * package="com.pythoncat.aidl_libiary"
       */
      public class HelloService extends Service {
          public HelloService() {
          }
      
          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
              return new MyBinder();
          }
      
          class MyBinder extends IHelloInterface.Stub {
      
              @Override
              public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
      
              }
      
              @Override
              public String hello() throws RemoteException {
                  return "Just Hello World";
              }
      
              @Override
              public Student getOne() throws RemoteException {
                  return new Student();
              }
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
    • 發現沒有,現在我們的Service,AIDL,Model已經關聯起來了,接下來就是調用者的事情了。
    • ** 既然是調用者的事情了,那我們就搞一個Activity去調用試試吧。
    • 在調用處,其實和平常的綁定服務幾乎沒有任何的差別,都是通過ServiceConnection去獲取接口的引用,然後就可以調用接口裏面的方法了。[接口的實現,已經在我們的HelloService裏面搞定了]。
    • 調用就一個Activity裏面一個按鈕的點擊事件 ,布局文件就不寫了,沒什麽意義。那麽調用者差不多這樣的:

      package com.pythoncat.helloaidl;
      
      import android.content.ComponentName;
      import android.content.Context;
      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.view.View;
      
      import com.apkfuns.logutils.LogUtils;
      import com.github.johnpersano.supertoasts.SuperToast;
      import com.pythoncat.aidl_libiary.IHelloInterface;
      import com.pythoncat.core.model.Student;
      
      public class MainActivity extends AppCompatActivity {
      
          private IHelloInterface iService;
          private ServiceConnection conn = new ServiceConnection() {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  iService = IHelloInterface.Stub.asInterface(service);
                  try {
                      final String hello = iService.hello();
                      LogUtils.e("hello::::::::" + hello);
                      final Student one = iService.getOne();
                      LogUtils.e(one);
                      runOnUiThread(new Runnable() {
                          @Override
                          public void run() {
                              SuperToast.cancelAllSuperToasts();
                              SuperToast.create(getApplicationContext(), hello, SuperToast.Duration.MEDIUM).show();
                          }
                      });
                  } catch (RemoteException e) {
                      e.printStackTrace();
                  }
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  iService = null;
                  LogUtils.e("iService::::::::" + iService);
              }
          };
          private boolean bindService;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
          }
      
          @Override
          protected void onStart() {
              super.onStart();
              final Intent in = new Intent();
              in.setClassName(this, "com.pythoncat.aidl_libiary.HelloService");
              in.setPackage("com.pythoncat.aidl_libiary");
              in.setAction("com.pythoncat.aidl_libiary.HelloService");
              bindService = bindService(in, conn, Context.BIND_AUTO_CREATE);
              LogUtils.e("bindService=" + bindService);
          }
      
          @Override
          protected void onStop() {
              super.onStop();
              if (conn != null) {
                  unbindService(conn);
              }
          }
      
          public void clickButton(View v) {
              LogUtils.e("bindService=" + bindService);
              LogUtils.e(iService);
              if (iService == null) {
                  SuperToast.cancelAllSuperToasts();
                  SuperToast.create(getApplicationContext(), iService + "", SuperToast.Duration.MEDIUM).show();
              } else {
                  SuperToast.cancelAllSuperToasts();
                  try {
                      SuperToast.create(getApplicationContext(), iService.hello(), SuperToast.Duration.MEDIUM).show();
                  } catch (RemoteException e) {
                      e.printStackTrace();
                  }
              }
      
          }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
    • 這樣,其實就已經完成了一個AIDL的調用的整個過程。
    • 另外,一旦項目跑不通,多弄幾次build -> make project (ctrl+F9)的操作,還是跑不通,就是代碼有問題了。

      不過,我必須坦白的是,我的調用者的Module還是引用了AIDL所在Module。因為我不引用就不能成功綁定遠程服務。這個問題應該是可以解決的,以後解決了,再記錄到這邊來。

    • 項目戳我,戳我啊~…~
    • 真的彩蛋後續更新FINAL

AndroidStudio 使用AIDL