什么是AIDL?
AIDL:它是一種android內部進程通信接口的描述語言,通過它我們可以定義進程間的通信接口。
為什么會出現AIDL?
AIDL是處理多線程,多CLIENT并發訪問的跨進程通訊技術。
Messager也可以跨進程通訊,但它是單線程的。
廣播也可以跨進程通訊,但是它不能長時間建立聯系,再OnReicever()中不能執行耗時工作,會造成ANR,而AIDL因為綁定了Service所以可以執行耗時的工作。
Handler是負責進程里不同線程之間的通信。
contentProvider只是將接口暴露出去給其他進程調用。數據不是實時的。
AIDL的使用
在android studio里面使用AIDL,因為是兩個進程間交互么,所以需要兩個APP,我們在第一個工程目錄右鍵新建一個AIDL文件。
輸入名稱后,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();
}
定義好之后,就可以sycn 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文件拷貝到第二個項目,然后sycn 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中使用自定義類型
如果我要在AIDL中使用自定義的類型,要怎么做呢。首先我們的自定義類型要實現Parcelable接口,下面的代碼中創建了一個User類并實現Parcelable接口。這邊就不對Parcelable進行介紹了,不熟悉的童鞋自行查找資料。
接下新建一個aidl文件,名稱為我們自定義類型的名稱,這邊是User.aidl。在User.aidl申明我們的自定義類型和它的完整包名,注意這邊parcelable是小寫的,不是Parcelable接口,一個自定類型需要一個這樣同名的AIDL文件。
package cc.abto.demo;
parcelable User;
然后再在我們的AIDL接口中導入我們的AIDL類型。
然后定義接口方法,sycn 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();
}
}
}
參考文章:
Android中AIDL的使用詳解 http://www.lxweimin.com/p/d1fac6ccee98
徹底明確Android中AIDL及其使用 http://www.cnblogs.com/tlnshuju/p/6791204.html