Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 問題小結(20)--AIDL學習及使用

問題小結(20)--AIDL學習及使用

編輯:關於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. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved