Android Service 之繫結服務和AIDL
阿新 • • 發佈:2019-02-03
今天在這裡給大家介紹Android 四大元件中service中的繫結模式onBind(),Activity和Service 之間可以繫結然後做到資料的互動,比如我做一個登入然後在服務中去進行判斷,在這裡演示一個簡單點的Demo就是一個普通的登入:
佈局如下,二個EditText和一個登入的Button:
在MainActivity中拿到幾個控制元件然後獲取值,再進行與服務之間的繫結<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/main_qqname_edit" android:hint="請輸入使用者名稱/QQ/電話號碼"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/main_qqpwd_edit" android:hint="請輸入密碼"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="login" android:text="登入"/>
private EditText main_qqname_edit; private EditText main_qqpwd_edit; private Intent intent; private QQLoginInterface qqLoginInterface; private QQLoginInterfaceOut qqLoginInterfaceOut; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //使用者名稱的控制元件 main_qqname_edit = (EditText) findViewById(R.id.main_qqname_edit); //密碼的控制元件 main_qqpwd_edit = (EditText) findViewById(R.id.main_qqpwd_edit); //繫結服務需要的Intent intent = new Intent(this,QQLoginServices.class); } //服務需要的ServiceConnection ServiceConnection connection=new ServiceConnection() { //繫結服務成功會呼叫的方法 @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { qqLoginInterface = (QQLoginInterface) iBinder; // qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder); } //繫結服務失敗會呼叫的方法 @Override public void onServiceDisconnected(ComponentName componentName) { } }; //進行互動時繫結服務 @Override protected void onResume() { super.onResume(); //繫結服務 bindService(intent,connection, Service.BIND_AUTO_CREATE); }
具體的詳解在註釋中寫清楚就不具體解釋了,服務的類中內容如下,註釋狀態中的程式碼不予本次內容有關:
在點選按鈕的時候進行如下操作:public class QQLoginServices extends Service { // class MyIBinder extends QQLoginInterfaceOut.Stub{ // // @Override // public boolean login(String qqname, String qqpwd) throws RemoteException { // if("100".equals(qqname)&&"123".equals(qqpwd)){ // return true; // } // return false; // } // } //onBind()方法中需要一個IBinder的返回型別值,所以我們在這裡例項化一個IBinder的子類Binder然後繼承一個介面來重寫這個方法提高安全性 class MyIBinder extends Binder implements QQLoginInterface{ @Override public boolean login(String qqname, String qqpwd) { if("100".equals(qqname)&&"123".equals(qqpwd)){ return true; } return false; } } //繫結服務時需要的生命週期:繫結 @Nullable @Override public IBinder onBind(Intent intent) { return new MyIBinder(); } }
//點選按鈕的方法
public void login(View view){
String qqname=main_qqname_edit.getText().toString();
String pwd=main_qqpwd_edit.getText().toString();
boolean flag=qqLoginInterface.login(qqname,pwd);
// boolean flag= false;
// try {
// flag = qqLoginInterfaceOut.login(qqname,pwd);
// } catch (RemoteException e) {
// e.printStackTrace();
// }
Toast.makeText(this,""+flag,Toast.LENGTH_LONG).show();
}
這裡的qqLoginInterface是我們之前繫結服務成功時裡面的那個介面,然後拿到接口裡面的登入方法把值給傳回去,在清單檔案中配置一下Service:
<service android:name=".QQLoginServices"
android:exported="true"
></service>
那麼這裡的Service中的繫結就這樣了,要注意我們的繫結中的互動會放回Binder中寫入方法的放回型別,如要需要改動可以自己更改型別。
好了,現在說一下AIDL ,Android介面語言,就是程序與程序之間的通訊,比如demo1和demo2都可以使用一個登入的方法,那麼就可以在demo2中去呼叫demo1的登入方法,就是提供一個介面你去呼叫。那麼這裡的佈局就如上 只是多做一個demo,然後什麼都不需要做很多的改變。
先建立一個AIDL,在Android studio中右擊可以new 一個AIDL 然後輸入一個名字,會產生一個AIDL的檔案,並且會產生一個相對應的java檔案。
在AIDL檔案中吧我們介面中的方法放進去也就是如下:
interface QQLoginInterfaceOut {
boolean login(String qqname,String qqpwd);
}
在服務類中需要更改由我們的AIDL作為IBinder返回,程式碼如下:
class MyIBinder extends QQLoginInterfaceOut.Stub{
@Override
public boolean login(String qqname, String qqpwd) throws RemoteException {
if("100".equals(qqname)&&"123".equals(qqpwd)){
return true;
}
return false;
}
}
直接繼承我們的AIDL類點出其中的Stub就可以,然後在MainActivity中不需要我們之前的那個介面來接收了,由我們的AIDL來接收,需要更改的程式碼如下:
//服務需要的ServiceConnection
ServiceConnection connection=new ServiceConnection() {
//繫結服務成功會呼叫的方法
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//qqLoginInterface = (QQLoginInterface) iBinder;
qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
}
//繫結服務失敗會呼叫的方法
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
在點選事件中直接用qqLoginInterfaceOut點出其中的方法就可以。第一個demo就是這樣,和上面介紹的在這裡看不出什麼變化,但是在第二個demo中我們可以直接訪問這裡的服務傳回來值在這裡做判斷了,
第二個demo中佈局什麼的和上面的demo一樣,只說一下需要改變的地方,首先把demo1中由AIDL產生的介面類同包名和類名Copy到與MainActivity的包同級目錄下,
MainActivity下的需要更改的程式碼如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_qqname_edit = (EditText) findViewById(R.id.main_qqname_edit);
main_qqpwd_edit = (EditText) findViewById(R.id.main_qqpwd_edit);
intent = new Intent();
ComponentName componentName=new ComponentName("com.example.android_services_bind_aidl","com.example.android_services_bind_aidl.QQLoginServices");
intent.setComponent(componentName);
}
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
// qqLoginInterface = (QQLoginInterface) iBinder;
qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
重點是Intent跳轉通過ComponentName來進行跳轉到demo1,ComponentName第一個引數是包名,第二個是包名加類名。
然後就可以輕鬆訪問到demo1中的那個服務了。
今天的分享就到這了,可能有些地方說的不清楚,但是在demo1中程式碼中的註釋希望大家看下可能可以幫助到。