Android进程间通信AIDL基本使用(附源码)

什么是AIDL?

AIDL:Android Interface Definition Language,即Android接口定义语言。

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。

为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务


接着建立AIDL服务端步骤

1,在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同

  

在这个文件中只定义了一个接口

package huahua.myaidlserver;

interface Ihuahua {  
    String greet(String someone);  


2,如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)

上图中R.java上的那个Ihuahua.java就是系统自动生成的,这个文件不用管它,到时候在客户端需要用到


3,建立一个服务类AIDLServer,并实现由aidl文件生成的Java接口

package huahua.myaidlserver;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class AIDLService extends Service {
	
    private static final String TAG = "huahua.AIDLService";  
    
    Ihuahua.Stub stub = new Ihuahua.Stub() {
		
		@Override
		public String greet(String someone) throws RemoteException {
			  Log.i(TAG, "greet() called");  
			return  "Hello " + someone+ "!";
		}
	};

	@Override
	public void onDestroy() {
		 Log.i(TAG, "onDestroy() called");  
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		 Log.i(TAG, "onUnbind() called");  
		return true;
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "onBind() called");  
		return stub;
	}

}


Stub是存根的意思,在服务端创建Ihuahua.Stub对象,并且真正实现了Ihuahua.aidl接口中的方法.


4,在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值,这里我把原有默认启动的activity替换成了Service

        <service
            android:name="huahua.myaidlserver.AIDLService"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="huahuadashen.AIDLService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>


好了,这个服务端的程序就写完了,就只提供了一个接口而已

需要注意的是,这个服务端程序是一个后台程序,没有界面显示!


下面是客户端的实现

新建一个Android应用程序MyAIDLClient,然后把MyAIDLServer程序中gen/huahua目录中的myaidlserver文件夹拷贝到新程序中的src/huahua目录下(huahua这个包名可以任意修改)


拷贝过去以后,只用保留Ihuahua.java系统自动生成的这个java文件,其他的都可以删掉

接着就可以编写主Activity代码了

package huahua.myaidlclient;

import huahua.myaidlserver.Ihuahua;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
	private Button btn1;
	private Button btn2;
	private Button btn3;
	
	private Ihuahua ihuahuadashen;
	private ServiceConnection SC = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {	
			Log.i("ServiceConnection", "onServiceDisconnected() called"); 
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.i("ServiceConnection", "onServiceConnected() called");  
			ihuahuadashen = Ihuahua.Stub.asInterface(service);  
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		btn1 = (Button)findViewById(R.id.btn1);
		btn1.setOnClickListener(new BtnClick());
		btn2 = (Button)findViewById(R.id.btn2);
		btn2.setOnClickListener(new BtnClick());
		btn3 = (Button)findViewById(R.id.btn3);
		btn3.setOnClickListener(new BtnClick());
		
		btn1.setEnabled(true);  
		btn2.setEnabled(false);  
		btn3.setEnabled(false);  
	}
	
	private class BtnClick implements View.OnClickListener{

		@Override
		public void onClick(View v) {
			if(v.getId() == R.id.btn1)
			{
                Intent intent = new Intent("huahuadashen.AIDLService");  
                bindService(intent, SC, Context.BIND_AUTO_CREATE);  
                  
                btn1.setEnabled(false);  
                btn2.setEnabled(true);  
                btn3.setEnabled(true);  
			}
			else if(v.getId() == R.id.btn2)
			{
                unbindService(SC);  
                
                btn1.setEnabled(true);  
                btn2.setEnabled(false);  
                btn3.setEnabled(false);  
			}
			else if(v.getId() == R.id.btn3)
			{
				try {
					String str = ihuahuadashen.greet("everyone");
					Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();  
				} catch (RemoteException e) {
					Toast.makeText(MainActivity.this, "异常", Toast.LENGTH_SHORT).show();  
					e.printStackTrace();
				}  
                
			}
		}
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}
就实现了3个功能

第1个按钮是绑定服务端,intent中的参数"huahuadashen.AIDLService"要和服务端AndroidManifest.xml中声明的行为<action android:name="huahuadashen.AIDLService" />一致

第2个按钮取消绑定

绑定成功后,第3个按钮就可以用Ihuahua的对象来调用相应的接口了


可以看到在客户端程序中并不需要用到扩展名为aidl的文件,而且对于接口中的具体功能实现也看不到,

这个服务端程序跟C++中的动态库程序是不是有点相似呢,都是提供封装的接口给其他程序调用


下面是源代码地址

AIDL源码下载


发布了21 篇原创文章 · 获赞 8 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/zhangxuebing2/article/details/12654049