AndroidStudio 使用AIDL
阿新 • • 發佈:2017-07-24
implement 知識庫 fault hub 代碼 知識 show 有一個 什麽
http://blog.csdn.net/ducklikejava/article/details/51559244
Android Studio
中寫的一個AIDL
的小DEMO.- 步驟很繁瑣,本來不準備寫的。但是寫一下是為了記錄,這一下午終於跑通了這玩意。
- 首先,你要有3個
Module
,至少兩個,但是最好是3個
- 一個是你的
AIDL
文件與它的Service
所在的Module
- 一個是你的客戶端
Module
,也就是你真正調用AIDL
的Module
- 最後一個是你的
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