為了說的深入淺出一點,我們先從AIDL的作用和使用說起,然后再開始介紹一些概念和工作原理。
AIDL用來做什么
AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫,對于小白來說,AIDL的作用是讓你可以在自己的APP里綁定一個其他APP的service,這樣你的APP可以和其他APP交互。
AIDL的使用
在android studio 2.0里面使用AIDL,因為是兩個APP交互么,所以當然要兩個APP啦,我們在第一個工程目錄右鍵
輸入名稱后,sutido就幫我們創建了一個AIDL文件。
// IMyAidlInterface.aidl
package cc.abto.demo;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* 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);
}
上面就是studio幫我生成的aidl文件。basicTypes這個方法可以無視,看注解知道這個方法只是告訴你在AIDL中你可以使用的基本類型(int, long, boolean, float, double, String),因為這里是要跨進程通訊的,所以不是隨便你自己定義的一個類型就可以在AIDL使用的,這些后面會說。我們在AIDL文件中定義一個我們要提供給第二個APP使用的接口。
interface IMyAidlInterface {
String getName();
}
定義好之后,就可以sync project一下,然后新建一個service。在service里面創建一個內部類,繼承你剛才創建的AIDL的名稱里的Stub類,并實現接口方法,在onBind返回內部類的實例。
public class MyService extends Service
{
public MyService()
{
}
@Override
public IBinder onBind(Intent intent)
{
return new MyBinder();
}
class MyBinder extends IMyAidlInterface.Stub
{
@Override
public String getName() throws RemoteException
{
return "test";
}
}
}
接下來,將我們的AIDL文件拷貝到第二個項目,然后sync project一下工程。
這邊的包名要跟第一個項目的一樣哦,這之后在Activity中綁定服務。
public class MainActivity extends AppCompatActivity
{
private IMyAidlInterface iMyAidlInterface;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent("cc.abto.server"), new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
}
}, BIND_AUTO_CREATE);
}
public void onClick(View view)
{
try
{
Toast.makeText(MainActivity.this, iMyAidlInterface.getName(), Toast.LENGTH_SHORT).show();
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
}
這邊我們通過隱式意圖來綁定service,在onServiceConnected方法中通過IMyAidlInterface.Stub.asInterface(service)獲取iMyAidlInterface對象,然后在onClick中調用iMyAidlInterface.getName()。
自定義類型
如果我要在AIDL中使用自定義的類型,要怎么做呢。首先我們的自定義類型要實現Parcelable接口,下面的代碼中創建了一個User類并實現Parcelable接口。這邊就不對Parcelable進行介紹了,不熟悉的童鞋自行查找資料,總之我們這邊可以借助studio的Show Intention Action(也就是Eclipse中的Quick Fix,默認是alt+enter鍵)幫我們快速實現Parcelable接口。
接下新建一個aidl文件,名稱為我們自定義類型的名稱,這邊是User.aidl。在User.aidl申明我們的自定義類型和它的完整包名,注意這邊parcelable是小寫的,不是Parcelable接口,一個自定類型需要一個這樣同名的AIDL文件。
package cc.abto.demo;
parcelable User;
然后再在我們的AIDL接口中導入我們的AIDL類型。
然后定義接口方法,sync project后就可以在service中做具體實現了。
public class MyService extends Service
{
//...
@Override
public IBinder onBind(Intent intent)
{
return new MyBinder();
}
class MyBinder extends IMyAidlInterface.Stub
{
//...
@Override
public User getUserName() throws RemoteException
{
return new User("wswf");
}
}
}
最后將我們的AIDL文件和自定義類型的java一并拷貝到第二個項目,注意包名都要一樣哦
然后就可以在Activity中使用該自定義類型的AIDL接口了
public class MainActivity extends AppCompatActivity
{
//...
public void onClick(View view)
{
try
{
Toast.makeText(MainActivity.this, iMyAidlInterface.getUserName().getName(), Toast.LENGTH_SHORT).show();
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
}
效果圖就不貼了哈,通過這種方式我們就可以讓兩個APP之間進行交互了。
最后
為什么APP間的進程交互這么麻煩,是因為它們屬于不同的進程,之間的交互涉及到進程間的通訊。而AIDL只是Android中眾多進程間通訊方式中的一種方式,那么AIDL到底是什么鬼,它是如何工作的,Android的IPC機制又是怎樣的呢。我將在下一篇文章Android中AIDL的工作原理中介紹。