跨進程調用Service:
有時候我們會用到自己寫的應用程序中要調用其他應用程序或系統應用程序中Service的一些方法。那在android中,我們怎麼才能做到跨應用(進程)調用Service中的方法呢。
下面就會用到AIDL服務。這裏簡單對AIDL介紹一下:
AIDL:Android Interface Definition Language,即Android接口定義語言。Android系統中的進程之間不
能共享內存,因此,需要提供一些機制在不同進程之間進行數據通信。爲了使其他的應用程序也可以訪問本應用程序提供的服務,Android系統採用了遠程過程調用(Remote Procedure Call,RPC)方式來實現。與很多其他的基於RPC的解決方案一樣,Android使用一種接口定義語言(Interface Definition Language,IDL)來公開服務的接口。我們知道4個Android應用程序組件中的3個(Activity、BroadcastReceiver和ContentProvider)都可以進行跨進程訪問,另外一個Android應用程序組件Service同樣可以。因此,可以將這種可以跨進程訪問的服務稱爲AIDL(Android Interface Definition Language)服務。
建立AIDL服務要比建立普通的服務複雜一些,具體步驟如下:
(1)在Eclipse Android工程的Java包目錄中建立一個擴展名爲aidl的文件。該文件的語法類似於Java代碼,但會稍有不同。
(2)如果aidl文件的內容是正確的,ADT會自動生成一個Java接口文件(*.java)。
(3)建立一個服務類(Service的子類)。
(4)實現由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服務,尤其要注意的是,<action>標籤中android:name的屬性值就是客戶端要引用該服務的ID,也就是Intent類的參數值。
下面我們通過一個實例來說明怎麼跨進程調用Service。
需求:在一個輸入框中輸入1-5其中一個數字,1:張三,2:李四,3:王五,4:趙六,5:田七一一對應。輸入1,點擊查詢按鈕,TextView上就會顯示“張三”,以此類推。
效果圖:
思路:
1.新建一個android項目,寫好佈局文件,在activity中找到相應的控件,爲各個控件設置相應的點擊事件。
2.另新建一個沒有主界面的Service項目,也可以有,但是在此就沒有設置相應的activity。
3.在Service項目下新建一個接口(沒有修飾符),在裏面我們可以寫自己需要的抽象方法。
package cn.cbd.personservice.adil; interface PersonServiceAidl { String getPersonInfo(int num); }
4.在工作目錄下找到Service項目中的此接口,把後綴名.java改成.aidl 然後返回eclipse(或ADT)刷新項目,我們可以看到在gen目錄下自動生成了一個PersonServiceAidl.java文件。
5.把整個cn.cbd.personservice.adil包拷到另一個應用的rec目錄下,然後刷新項目。
特別注意:
在清單文件中對遠程服務進行配置的時候,一定要加上
<service android:name=".PersonService"> <intent-filter > <!--遠程服務中,必須這樣一個action --> <action android:name="aaa.bbb.ccc"/> </intent-filter> </service>
否則會報錯,其中的"<action android:name="aaa.bbb.ccc"/>”是自定義的。
下面是主Acitivity中的一些內容:
package cn.cbd.person; import android.app.Activity; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import cn.cbd.personservice.adil.PersonServiceAidl; public class PersonActivity extends Activity { private EditText et_main; private Button btn_query; private TextView tv_showName; private PersonServiceAidl aidl; private MyServiceConnection conn; private Intent service; // PersonService public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); et_main = (EditText) findViewById(R.id.et_main); btn_query = (Button) findViewById(R.id.btn_query); tv_showName = (TextView) findViewById(R.id.tv_showName); //新建一個MyServiceConnection對象conn conn = new MyServiceConnection(); //service = new Intent("aaa.bbb.ccc"); service = new Intent(); service.setClassName("cn.cbd.personservice", "cn.cbd.personservice.PersonService"); //開啓服務 //this.startService(service); // 綁定服務 this.bindService(service, conn, Context.BIND_AUTO_CREATE); btn_query.setOnClickListener(new OnClickListener() { public void onClick(View v) { String num = et_main.getText().toString().trim(); // 調用服務中的方法 try { String name = aidl.getPersonInfo(Integer.valueOf(num)); tv_showName.setText(name); } catch (NumberFormatException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { this.unbindService(conn); //this.stopService(service); super.onDestroy(); } public class MyServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder service) { aidl = PersonServiceAidl.Stub.asInterface(service); } public void onServiceDisconnected(ComponentName name) { } } }
從上面我們可以看到,當我們通過bindService(service,conn,flag)綁定服務綁定成功時,就會執行實現類MyServiceConnection類中的onServiceConnected(ComponentName name, IBinder service)方法。在此方法中我們可以獲得操作服務中的方法的對象(aidl = PersonServiceAidl.Stub.asInterface(service);),這個對象我們可以操作服務中的方法。
下面附有項目包源碼,大家不理解的可以自己看一下。
解壓以後,先部署項目PersonService,然後在部署項目Person。