您的位置:首页 > 移动开发 > Android开发

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

2013-10-14 10:58 399 查看
什么是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源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  进程通信