问题小结(20)--AIDL学习及使用

来源:互联网 发布:天地图数据规范 编辑:程序博客网 时间:2024/06/06 07:42

AIDL:是 Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以用来不同进程间的通信。

最初接触aidl的时候,只是敲了一下教材上的代码,没有静下来思考过,感觉挺复杂的,由于畏难情绪在作祟,且目前还没有需要用到aidl的项目,所以一直就没有好好的研究过。今天仔细的看了一下,简单的梳理了一下流程,感觉其实不难的,所以在这里,我会用自己的方式描述一下它的整个的工作流程(可能原理上不是这样的)。

一、服务端部分

       首先我们要定义服务器端的aidl文件,在我们写好aidl文件时,然后 Android Eclipse 插件会自动帮你 根据这个 AIDL 文件生成 Java文件,在gen目录下,并且和其包名对应。

package com.duke.aidl;interface IService {       String setValue(String value);       String getValue(String value);}

当然客户端程序程序所用到的aidl文件和服务器端是一样的,并且双方aidl文件所在的包名也要相同。
aidl里面声明的方法也就是客户端程序能够调用的服务器端的方法。

      然后就是在服务类中实现aidl文件里声明的方法

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文件里的内部类实现的,我们不需要深究它是如何自动生成的,也不需要知道它里面有什么东西@Overridepublic String setValue(String value) throws RemoteException {// TODO Auto-generated method stubmvValue=value;return mvValue;}@Overridepublic String getValue(String value) throws RemoteException {// TODO Auto-generated method stubreturn value+":"+mvValue;}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn new ServiceRunningImpl();}}

在这个服务类中大家可以看到我们实现了 onBind() 方法。从AIDL文件生成的 Stub类是抽象类并且它实现了 IService接口。在我们的服务实现中,有一个扩展了 Stub类得内部类,名为 ServiceRunningImpl。此类充当着远程服务实现,而且 onBind()方法会返回此类的实例。到此,我们有了一个有效的 ADIL服务,但是外部的客户端还无法连接到它。
     最后呢要将服务向客户端公开,需要在AndroidManifest.xml文件中添加服务声明,而这一次我们需要一个Intent 过滤器来公开服务,如下:

<?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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubbindService(new Intent("com.duke.aidl.ServiceRunning"), sercon, Context.BIND_AUTO_CREATE);}});                btn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubcallService();}});                btn2=(Button) findViewById(R.id.button2);        btn2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubunbindService(sercon);}});    }            private ServiceConnection sercon=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stubmService=null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stubmService=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接口的实现。此接口定义了两个方法:一个供系统建立服务连接时调用,另一个在销毁服务连接时调用。

布局文件:

<?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张我们程序结构的截图吧,一个是服务端得,一个是 客户端的。

服务器端:


客户端:




总结:服务器端的aidl文件声明方法,通过服务实现这些方法

           客户端的aidl文件是告诉客户端它所能调用到的服务器端的哪些方法,然后通过绑定启动服务,通过ServiceConnection和服务器建立连接通信,进而调用服务器端实现的方法体。

原创粉丝点击