Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android-aidl 從懵逼開始

android-aidl 從懵逼開始

編輯:關於Android編程

什麼是aidl?aidl 能干什麼?怎麼用 aidl?實現一個最簡單的aidl

以上4個問題,前面兩個我不打算展開,我相信,關於這兩個問題的說明和解答,已經有無數的大神詳細的講解過了。關於後面的兩個問題,是我一直關心的問題。到剛才,我解決了第四個問題,但是第三個的話,我相信,得繼續深入才能更好的回答。

好了,現在就開始第四個問題的實現。

簡單說明一下,最簡單的aidl實現,不需要多個app,也不需要多個module。只要一個service,一個activity,一個.aidl文件。但是,我不打算一開始就去實現最簡單的aidl模型,我准備先寫一個最簡單的bindService,作為過渡。一來,溫習一下基礎知識,二來,這個本身就是最簡單的aidl的前奏,必不可少。

那麼,如何實現呢?還是從代碼下手吧。

我先創建兩個activity和一個service.activity為什麼是兩個?其實可以是一個,但是個人習慣,第一個總是作為入口,不做任何的真正邏輯,僅僅是作為目錄和指引的作用。第二個是和服務對應的。也就是服務的調用者。清單文件如下:
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">


android:name=".service.NormalService"
android:enabled="true"
android:exported="true"/>

android:theme="@style/AppTheme.NoActionbar"
android:name=".activity.NormalActivity">
簡單明了,我也沒有任何的解釋了。關於service上設置的兩個屬性分別是什麼意思?我也不太了解。想了解的,可以自行搜索下,這個不是本文的重點。
然後,我們看一下入口的activity吧

publicclassLauncherActivityextendsAppCompatActivity{

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launcher);

findViewById(R.id.normal_service_btn).setOnClickListener(v->{
LogUtils.e("普通service模式");
//todo
startActivity(newIntent(get(),NormalActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
});
findViewById(R.id.aidl_service).setOnClickListener(v->{
LogUtils.e("AIDLservice模式");
//todo
});
}

publicAppCompatActivityget(){
returnthis;
}
} public class LauncherActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launcher); findViewById(R.id.normal_service_btn).setOnClickListener(v -> { LogUtils.e("普通service 模式"); // todo startActivity(new Intent(get(), NormalActivity.class) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); }); findViewById(R.id.aidl_service).setOnClickListener(v -> { LogUtils.e("AIDL service 模式"); // todo }); } public AppCompatActivity get() { return this; } }

依然是簡單明了

接下來,我們去看看NormalActivity?不,這個是服務的調用者,我們先去看服務,這樣清楚明了一點。
publicclassNormalServiceextendsService{
publicNormalService(){
}

@Override
publicIBinderonBind(Intentintent){
LogUtils.w("normalservicebind");
returnnewLocalBinder();
}

@Override
publicbooleanonUnbind(Intentintent){
LogUtils.w("normalserviceunbind");
returnsuper.onUnbind(intent);
}

@Override
publicvoidonRebind(Intentintent){
super.onRebind(intent);

LogUtils.w("normalservicerebind");
}

@Override
publicvoidonCreate(){
super.onCreate();
LogUtils.w("normalservicecreate");
}

@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
LogUtils.w("normalservicestart");
returnsuper.onStartCommand(intent,flags,startId);
}

@Override
publicvoidonDestroy(){
super.onDestroy();
LogUtils.w("normalservicedestroy");
}


publicclassLocalBinderextendsBinder{
publicNormalServiceget(){
returnNormalService.this;
}
}

/**
*publicmethodinvokedbycaller
*
*@returnanumberofrandom
*/
publicintgetResult(){
returnnewRandom().nextInt(500);
}
} public class NormalService extends Service { public NormalService() { } @Override public IBinder onBind(Intent intent) { LogUtils.w("normal service bind"); return new LocalBinder(); } @Override public boolean onUnbind(Intent intent) { LogUtils.w("normal service unbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); LogUtils.w("normal service rebind"); } @Override public void onCreate() { super.onCreate(); LogUtils.w("normal service create"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.w("normal service start"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); LogUtils.w("normal service destroy"); } public class LocalBinder extends Binder { public NormalService get() { return NormalService.this; } } /** * public method invoked by caller * * @return a number of random */ public int getResult() { return new Random().nextInt(500); } }

代碼略長,不過應該還算是清晰。而且裡面沒有什麼實質性邏輯。最關鍵的方法就是getResult()。是讓調用者調用的。另外,我實現了一個LocalBinder,目的很明確,就是要讓調用者可以綁定當前服務。

現在,該去看看該服務的調用者了。

publicclassNormalActivityextendsAppCompatActivity{
publicbooleanbind;
privateNormalService.LocalBindermBinder;
privateServiceConnectionmNormalConn;

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_normal);

setSupportActionBar((Toolbar)findViewById(R.id.toolbar));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Normalactivity");
finalDrawableupArrow=getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.colorWhite),PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);
TextViewtvShowResult=(TextView)findViewById(R.id.normal_show_tv);
tvShowResult.setText(getString(R.string.show_about_normal_service,""));
ButtonbtnExecute=(Button)findViewById(R.id.normal_ui_btn);
btnExecute.setOnClickListener(v->{
LogUtils.w("executenormalservicemethod...");
LogUtils.w("executenormalservicemethod...");
if(bind){
intresult=mBinder.get().getResult();
LogUtils.e("result====="+result);
tvShowResult.setText(getString(R.string.show_about_normal_service,result));
}else{
LogUtils.e("bindservicefail,tryagain......");
bindService(newIntent(this,NormalService.class),mNormalConn,BIND_AUTO_CREATE);
ToastHelper.show(getApplication(),"bindservicefail,tryagain......");
}
});
mNormalConn=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
bind=true;
LogUtils.w("normalactivityconnectednormalservice...");
mBinder=(NormalService.LocalBinder)service;
}

@Override
publicvoidonServiceDisconnected(ComponentNamename){
bind=false;
mBinder=null;
LogUtils.w("normalactivitydisconnectednormalservice!");
}
};

bindService(newIntent(this,NormalService.class),mNormalConn,BIND_AUTO_CREATE);
}

@Override
protectedvoidonDestroy(){
super.onDestroy();
unbindService(mNormalConn);
LogUtils.e("$$$unbindnormalservice");
}

@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
if(item.getItemId()==android.R.id.home){
finish();
returntrue;
}
returnsuper.onOptionsItemSelected(item);
}
}public class NormalActivity extends AppCompatActivity { public boolean bind; private NormalService.LocalBinder mBinder; private ServiceConnection mNormalConn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("Normal activity"); final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha); upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP); getSupportActionBar().setHomeAsUpIndicator(upArrow); TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv); tvShowResult.setText(getString(R.string.show_about_normal_service, "")); Button btnExecute = (Button) findViewById(R.id.normal_ui_btn); btnExecute.setOnClickListener(v -> { LogUtils.w("execute normal service method..."); LogUtils.w("execute normal service method..."); if (bind) { int result = mBinder.get().getResult(); LogUtils.e("result=====" + result); tvShowResult.setText(getString(R.string.show_about_normal_service, result)); } else { LogUtils.e("bind service fail ,try again......"); bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); ToastHelper.show(getApplication(), "bind service fail ,try again......"); } }); mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); mBinder = (NormalService.LocalBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } }; bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mNormalConn); LogUtils.e("$$$ unbind normal service"); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } }

代碼略長,因為裡面還做了除了調用服務之外的其他操作。關鍵代碼看 20~50 ,這30行的代碼即可。這個代碼也不用解釋了,就是在界面上有一個按鈕,每次點擊按鈕都會調用服務裡面的方法得到一個隨機數,並顯示在textview上面罷了。至於怎麼去綁定服務,我相信大家都很娴熟了,不必再解釋了。

不過我覺得值得注意的是38行的代碼mBinder = (NormalService.LocalBinder) service;,也就是我們通過類型強轉得到一個我們自己定義的IBinder對象,也只有得到它,才能得到服務的對象,然後調用服務裡面的方法。

ok,代碼結束了,一個最簡單的bindService完成了。運行截圖就不貼了,沒意義,大家都知道是什麼樣子的。

.........................

現在,去實現最簡單的aidl,也就是基於當前代碼的一些修改。

那麼,要怎麼修改呢? 首先,我們給service設置一個單獨的進程,修改清單文件,在service節點裡面添加一個屬性android:process=":normal".這樣就讓service和'activity'之間跨進程了。 然後,我們什麼也不做,直接運行代碼。注意:我們所做的修改僅僅是給service設置了一個單獨的進程,java代碼沒有改動一行。

現在運行之後,是什麼樣子的效果呢?程序崩潰了。看日志:


FATALEXCEPTION:main
Process:com.pythoncat.ipcorservice,PID:2811
java.lang.ClassCastException:android.os.BinderProxycannotbecasttocom.pythoncat.ipcorservice.service.NormalService$LocalBinder
atcom.pythoncat.ipcorservice.activity.NormalActivity$1.onServiceConnected(NormalActivity.java:58)
atandroid.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1256)
atandroid.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1273)
atandroid.os.Handler.handleCallback(Handler.java:815)
atandroid.os.Handler.dispatchMessage(Handler.java:104)
atandroid.os.Looper.loop(Looper.java:194)
atandroid.app.ActivityThread.main(ActivityThread.java:5667)
atjava.lang.reflect.Method.invoke(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:372)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:962)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)FATAL EXCEPTION: main Process: com.pythoncat.ipcorservice, PID: 2811 java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder at com.pythoncat.ipcorservice.activity.NormalActivity$1.onServiceConnected(NormalActivity.java:58) at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1256) at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1273) at android.os.Handler.handleCallback(Handler.java:815) at android.os.Handler.dispatchMessage(Handler.java:104) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5667) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:962) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

真正有用的日志就一行


java.lang.ClassCastException:android.os.BinderProxycannotbecasttocom.pythoncat.ipcorservice.service.NormalService$LocalBinder`.java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder`.

看了日志我們大概明白了,我們拿到的Ibinder對象,並不是我們在service中定義的NormalService$LocalBinder對象。

那麼,為什麼會這樣呢?簡單的理解就是,每個進程的內存是獨立的,在A進程開辟的內存,B進程並不能訪問。如何解決? 我並不知道怎麼解決。看大神們的博客大概就是說,通過IBinder所在的共享內存區域進行數據交換,實現跨進程通信,實現起來也就是aidl.

關於這方面的理論知識,我也不多介紹了,無論是android官方文檔,還是一些大神的博客,都對此有比較清晰的介紹。我就簡單說一下實現方式。

既然當前activity和service不在同一個進程了,無法通過之前的方式直接拿到IBinder對象,那麼,我們就定義一個.aidl來實現之間的通信。

從上面的代碼上看,我們實際上是希望調用service中的getResult()方法。那麼,我們就定義一個.aidl裡面包含該方法即可。

1.如何操作?右鍵appmodule --> new --> AIDL -->AIDL File .然後寫一個文件名如:NormalBinder,然後直接回車。在裡面添加需要調用的service中的方法。

interfaceNormalBinder{
/**
*Demonstratessomebasictypesthatyoucanuseasparameters
*andreturnvaluesinAIDL.
*/
voidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,
doubleaDouble,StringaString);
intgetResult();
}interface NormalBinder { /** * 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); int getResult(); }


2.接下來,rebuild一下項目。會自動生成一些Java文件。至於生成的是什麼,在哪裡,這裡也不說明了,跟主題無關。3.然後,在service中去實現一個可用於aidl的IBinder.

publicclassRemoteBinderextendsNormalBinder.Stub{

@Override
publicvoidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,doubleaDouble,StringaString)throwsRemoteException{

}

@Override
publicintgetResult()throwsRemoteException{
returnnewRandom().nextInt(500);
}
}public class RemoteBinder extends NormalBinder.Stub { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int getResult() throws RemoteException { return new Random().nextInt(500); } }

修改之後的service長這樣子:


publicclassNormalServiceextendsService{
publicNormalService(){
}

@Override
publicIBinderonBind(Intentintent){
LogUtils.w("normalservicebind");
//returnnewLocalBinder();
returnnewRemoteBinder();
}

@Override
publicbooleanonUnbind(Intentintent){
LogUtils.w("normalserviceunbind");
returnsuper.onUnbind(intent);
}

@Override
publicvoidonRebind(Intentintent){
super.onRebind(intent);

LogUtils.w("normalservicerebind");
}

@Override
publicvoidonCreate(){
super.onCreate();
LogUtils.w("normalservicecreate");
}

@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
LogUtils.w("normalservicestart");
returnsuper.onStartCommand(intent,flags,startId);
}

@Override
publicvoidonDestroy(){
super.onDestroy();
LogUtils.w("normalservicedestroy");
}


publicclassLocalBinderextendsBinder{
publicNormalServiceget(){
returnNormalService.this;
}
}

/**
*publicmethodinvokedbycaller
*
*@returnanumberofrandom
*/
publicintgetResult(){
returnnewRandom().nextInt(500);
}

publicclassRemoteBinderextendsNormalBinder.Stub{

@Override
publicvoidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,doubleaDouble,StringaString)throwsRemoteException{

}

@Override
publicintgetResult()throwsRemoteException{
returnnewRandom().nextInt(500);
}
}
} public class NormalService extends Service { public NormalService() { } @Override public IBinder onBind(Intent intent) { LogUtils.w("normal service bind"); // return new LocalBinder(); return new RemoteBinder(); } @Override public boolean onUnbind(Intent intent) { LogUtils.w("normal service unbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); LogUtils.w("normal service rebind"); } @Override public void onCreate() { super.onCreate(); LogUtils.w("normal service create"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.w("normal service start"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); LogUtils.w("normal service destroy"); } public class LocalBinder extends Binder { public NormalService get() { return NormalService.this; } } /** * public method invoked by caller * * @return a number of random */ public int getResult() { return new Random().nextInt(500); } public class RemoteBinder extends NormalBinder.Stub { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int getResult() throws RemoteException { return new Random().nextInt(500); } } }

4.然後需要修改調用的activity了。

得將之前的IBinder對象換成可以aidl的IBinder了。


mNormalConn=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
bind=true;
LogUtils.w("normalactivityconnectednormalservice...");
//mBinder=(NormalService.LocalBinder)service;
mBinder=NormalBinder.Stub.asInterface(service);
}

@Override
publicvoidonServiceDisconnected(ComponentNamename){
bind=false;
mBinder=null;
LogUtils.w("normalactivitydisconnectednormalservice!");
}
};mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); // mBinder = (NormalService.LocalBinder) service; mBinder = NormalBinder.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } };

發現什麼改變了沒有,就是將第6行替換成第7行。也就是mbinder的獲取方式改變了,得到的對象也不是之前的對象了。

完全替換之後的activity長這樣子的


publicclassNormalActivityextendsAppCompatActivity{
publicbooleanbind;
privateServiceConnectionmNormalConn;
privateNormalBindermBinder;

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_normal);

setSupportActionBar((Toolbar)findViewById(R.id.toolbar));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Normalactivity");
finalDrawableupArrow=getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.colorWhite),PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);
TextViewtvShowResult=(TextView)findViewById(R.id.normal_show_tv);
tvShowResult.setText(getString(R.string.show_about_normal_service,""));
ButtonbtnExecute=(Button)findViewById(R.id.normal_ui_btn);
btnExecute.setOnClickListener(v->{
LogUtils.w("executenormalservicemethod...");
LogUtils.w("executenormalservicemethod...");
if(bind){
//intresult=mBinder.get().getResult();
intresult=0;
try{
result=mBinder.getResult();
}catch(RemoteExceptione){
e.printStackTrace();
}
LogUtils.e("result====="+result);
tvShowResult.setText(getString(R.string.show_about_normal_service,result));
}else{
LogUtils.e("bindservicefail,tryagain......");
bindService(newIntent(this,NormalService.class),mNormalConn,BIND_AUTO_CREATE);
ToastHelper.show(getApplication(),"bindservicefail,tryagain......");
}
});
mNormalConn=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
bind=true;
LogUtils.w("normalactivityconnectednormalservice...");
//mBinder=(NormalService.LocalBinder)service;
mBinder=NormalBinder.Stub.asInterface(service);
}

@Override
publicvoidonServiceDisconnected(ComponentNamename){
bind=false;
mBinder=null;
LogUtils.w("normalactivitydisconnectednormalservice!");
}
};

bindService(newIntent(this,NormalService.class),mNormalConn,BIND_AUTO_CREATE);
}

@Override
protectedvoidonDestroy(){
super.onDestroy();
unbindService(mNormalConn);
LogUtils.e("$$$unbindnormalservice");
}

@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
if(item.getItemId()==android.R.id.home){
finish();
returntrue;
}
returnsuper.onOptionsItemSelected(item);
}
}public class NormalActivity extends AppCompatActivity { public boolean bind; private ServiceConnection mNormalConn; private NormalBinder mBinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("Normal activity"); final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha); upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP); getSupportActionBar().setHomeAsUpIndicator(upArrow); TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv); tvShowResult.setText(getString(R.string.show_about_normal_service, "")); Button btnExecute = (Button) findViewById(R.id.normal_ui_btn); btnExecute.setOnClickListener(v -> { LogUtils.w("execute normal service method..."); LogUtils.w("execute normal service method..."); if (bind) { // int result = mBinder.get().getResult(); int result = 0; try { result = mBinder.getResult(); } catch (RemoteException e) { e.printStackTrace(); } LogUtils.e("result=====" + result); tvShowResult.setText(getString(R.string.show_about_normal_service, result)); } else { LogUtils.e("bind service fail ,try again......"); bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); ToastHelper.show(getApplication(), "bind service fail ,try again......"); } }); mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); // mBinder = (NormalService.LocalBinder) service; mBinder = NormalBinder.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } }; bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mNormalConn); LogUtils.e("$$$ unbind normal service"); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } }

現在,一個最簡單的aidl就完成了。現在運行代碼,和之前的效果完全一樣。還是每點擊一次按鈕,就會在textview上顯示一個500以內的隨機數。不過,現在是跨進程調用了,不再是同一個進程了。為什麼說是跨進程?你可以嘗試分別輸出service所在的pid和activity所在的pid就一目了然了。

int pid = Process.myPid();,可以使用這句代碼完成當前pid的獲取。

吐槽下 amd 的cpu,超級辣雞!android studio 能卡死,即使是16G內存,2G獨顯,120G的固態。

結語

相信通過這長篇的說明,大家知道怎麼去寫一個最簡單的aidl了。我想,通過這個記錄,我應該也會對實現最簡單的一個aidl更加熟練一點。但是,我們知道aidl的使用場景往往是多module之間,多app之間。而且進行數據的交互可能是相互的,不僅僅是一方輸出,一方接收。而是雙方都能輸出,雙方都能夠接收。而且傳輸的數據也不僅僅是基本類型的數據,可能是一個pojo類型的數據。沒有關系,這只是一個開始。目的是拋磚引玉。後續,我也會不定期更新這方面的知識。

最後,關於我:野生安卓猿一只,入安卓坑已有幾年,一直徘徊在新手和菜鳥之間。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved