編輯:關於Android編程
AIDL:是 Android Interface definition language的縮寫,它是一種android內部進程通信接口的描述語言,通過它我們可以用來不同進程間的通信。
最初接觸aidl的時候,只是敲了一下教材上的代碼,沒有靜下來思考過,感覺挺復雜的,由於畏難情緒在作祟,且目前還沒有需要用到aidl的項目,所以一直就沒有好好的研究過。今天仔細的看了一下,簡單的梳理了一下流程,感覺其實不難的,所以在這裡,我會用自己的方式描述一下它的整個的工作流程(可能原理上不是這樣的)。
一、服務端部分
首先我們要定義服務器端的aidl文件,在我們寫好aidl文件時,然後 Android Eclipse 插件會自動幫你 根據這個 AIDL 文件生成 Java文件,在gen目錄下,並且和其包名對應。
[java]
package com.duke.aidl;
interface IService {
String setValue(String value);
String getValue(String value);
}
package com.duke.aidl;
interface IService {
String setValue(String value);
String getValue(String value);
}當然客戶端程序程序所用到的aidl文件和服務器端是一樣的,並且雙方aidl文件所在的包名也要相同。
aidl裡面聲明的方法也就是客戶端程序能夠調用的服務器端的方法。
然後就是在服務類中實現aidl文件裡聲明的方法
[java]
package com.duke.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class ServiceRunning extends Service{
String mvValue="duke";
public class ServiceRunningImpl extends IService.Stub{
//實現方法就是通過繼承aidl文件自動生成的java文件裡的內部類實現的,我們不需要深究它是如何自動生成的,也不需要知道它裡面有什麼東西
@Override
public String setValue(String value) throws RemoteException {
// TODO Auto-generated method stub
mvValue=value;
return mvValue;
}
@Override
public String getValue(String value) throws RemoteException {
// TODO Auto-generated method stub
return value+":"+mvValue;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return new ServiceRunningImpl();
}
}
package com.duke.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class ServiceRunning extends Service{
String mvValue="duke";
public class ServiceRunningImpl extends IService.Stub{
//實現方法就是通過繼承aidl文件自動生成的java文件裡的內部類實現的,我們不需要深究它是如何自動生成的,也不需要知道它裡面有什麼東西
@Override
public String setValue(String value) throws RemoteException {
// TODO Auto-generated method stub
mvValue=value;
return mvValue;
}
@Override
public String getValue(String value) throws RemoteException {
// TODO Auto-generated method stub
return value+":"+mvValue;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return new ServiceRunningImpl();
}
}
在這個服務類中大家可以看到我們實現了 onBind() 方法。從AIDL文件生成的 Stub類是抽象類並且它實現了 IService接口。在我們的服務實現中,有一個擴展了 Stub類得內部類,名為 ServiceRunningImpl。此類充當著遠程服務實現,而且 onBind()方法會返回此類的實例。到此,我們有了一個有效的 ADIL服務,但是外部的客戶端還無法連接到它。
最後呢要將服務向客戶端公開,需要在AndroidManifest.xml文件中添加服務聲明,而這一次我們需要一個Intent 過濾器來公開服務,如下:
[html]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.duke.aidl"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<service android:name=".ServiceRunning">
<intent-filter>
<action android:name="com.duke.aidl.ServiceRunning"/>
</intent-filter>
</service>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.duke.aidl"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<service android:name=".ServiceRunning">
<intent-filter>
<action android:name="com.duke.aidl.ServiceRunning"/>
</intent-filter>
</service>
</application>
</manifest>二、客戶端程序
當客戶端與服務通信時,它們之間必須有一個協議或契約(AIDL)。所以,使用服務的第一步是,獲取服務的 AIDL文件並將其復制到客戶端項目中。當將AIDL文件復制到客戶端項目時,AIDL 編譯器將創建一個接口定義文件,這個文件與我們在服務端定義的文件相同。這會向客戶端公開所有的方法、參數並返回服務的類型。
首先新建一個客戶端工程,當然了包名不能和服務器端相同。
其次根據服務器端的aidl文件所在的包名,新建一個相同的包,讓後將服務器端的aidl文件復制到客戶端工程新建的包下。
最後是獲取服務的引用,以便調用服務器端實現的方法。對於遠程服務,必須調用 bindService()方法,而不是 startService()方法。
package com.duke.aidl.client;
import com.duke.aidl.IService;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class AidlServiceClientActivity extends Activity {
/** Called when the activity is first created. */
private IService mService=null;
private Button btn,btn1,btn2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn=(Button) findViewById(R.id.button);
btn1=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bindService(new Intent("com.duke.aidl.ServiceRunning"), sercon, Context.BIND_AUTO_CREATE);
}
});
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
callService();
}
});
btn2=(Button) findViewById(R.id.button2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
unbindService(sercon);
}
});
}
private ServiceConnection sercon=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mService=null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService=IService.Stub.asInterface(service);
// callService();
}
};
private void callService(){
try {
// String str=mService.setValue("value");
String val=mService.getValue("hello world");
Toast.makeText(this, "Value from service is " + val,
Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
Log.e("MainActivity", e.getMessage(), e);
}
}
}
package com.duke.aidl.client;
import com.duke.aidl.IService;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class AidlServiceClientActivity extends Activity {
/** Called when the activity is first created. */
private IService mService=null;
private Button btn,btn1,btn2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn=(Button) findViewById(R.id.button);
btn1=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bindService(new Intent("com.duke.aidl.ServiceRunning"), sercon, Context.BIND_AUTO_CREATE);
}
});
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
callService();
}
});
btn2=(Button) findViewById(R.id.button2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
unbindService(sercon);
}
});
}
private ServiceConnection sercon=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mService=null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService=IService.Stub.asInterface(service);
// callService();
}
};
private void callService(){
try {
// String str=mService.setValue("value");
String val=mService.getValue("hello world");
Toast.makeText(this, "Value from service is " + val,
Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
Log.e("MainActivity", e.getMessage(), e);
}
}
}對於AIDL 服務,需要提供ServiceConnection接口的實現。此接口定義了兩個方法:一個供系統建立服務連接時調用,另一個在銷毀服務連接時調用。
布局文件:
[html]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:text="@string/hello" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="bindService" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button1"
android:text="callService" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="unbindService" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:text="@string/hello" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="bindService" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button1"
android:text="callService" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="unbindService" />
</LinearLayout>第一個按鈕是綁定啟動服務,第二個是調用一下方法來驗證是否實現了和服務器端的通信,第三個是解綁服務。
為了避免大家把aidl文件放錯位置,來2張我們程序結構的截圖吧,一個是服務端得,一個是 客戶端的。
微信可以辦護照、續簽港澳通行證,只有1%的人知道!你也趕快來學習吧!對於需要經常出行出差的朋友來說,這個新get一定能帶來極大的方便。微信怎麼辦理港澳通行證
Swift 中的錯誤處理從 O-C 沿襲而來,但 Swift 1.0 之後逐漸發生了巨大改變。重要的改變發生在 Swift 2,它率先使用了“處理非異常的狀態
相信大家在android開發的過程中總會遇到要在Activity中間傳遞數據的情況,當然,遇到需要在Intent中傳遞對象的情況也不可避免,所以我就so了一下相關的知識,
寫BlueStacks安卓模擬器腳本的一般步驟,其實BlueStacks安卓模擬器腳本不是很難,只要跟下面步驟來,一步一步走,就學了。BlueStacks安