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

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文件里的内部类实现的,我们不需要深究它是如何自动生成的,也不需要知道它里面有什么东西		
		@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 过滤器来公开服务,如下:

<?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);  
	        } 

	}
}

对于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和服务器建立连接通信,进而调用服务器端实现的方法体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值