AIDL的用途不多介绍了,我写了个例子是项目AB来调用项目A 的功能。根据我的例子大家可以往自己的功能需求上拓展修改。
源代码地址:http://download.csdn.net/detail/zhzhh7378/7167441
原理很简单,项目A 定义为提供服务的项目。项目AB定义为需要服务的项目。
1,首先在A工程里面定义一个AIDL文件,(可单独定义一个包方面理解)。
这里我定义的aidl接口名字为AidlInterface后缀就是aidl这里大家注意aidl接口的写法。下面是aidl文件里面的内容
package com.test.aidl;
interface AidlInterface{
void sendMessage(in String message,out String[] list);
void toDoAnything();
String getMessage();
}
注意必须加包名,interface类名和文件名字保持一致,这和java类的要求一样。方法体不加修饰词。sendMessage();方法体的参数 in/out我也没太多研究,有文章介绍说
in表示这个参数是调用者传递的参数out的被调用者需要传递的参数。这里掉用者就是项目AB被调用者就是项目A了。因为到时候这个aidl文件会从A拷贝到AB里面的。关于in/out
的理解不在这里研究了,最终请以官方API文档为准。
到这里aidl的第一步就完成了。
2,把aidl文件连同包一并拷贝到项目AB里面(重要的是使两个工程拥有同样的包名并且里面都包含同样的aidl文件,注意包面只要有AIDL文件就行了我里面还放了一个service文件不用拷贝了),这个步骤可以推到后面再做。因为项目A还需要做几个步骤。
我们可以这样理解aidl就相当于接口文件,那我们项目A 是不是首先也得来实现这些接口呢。只有实现了接口才能在AB项目调用aidl里面的方法时A才能做出相应的动作。
下面我们继续来完成项目A 的步骤。
3,既然项目A 只是用来提供服务的所以肯定是在后台运行的,肯定得有一个服务service来监听AB等实现了或者拥有相同aidl接口文件的项目的调用。所以我们在A工程里面新建一个service命名为ServiceService.这个文件我放到了和adil同一个包里面了。
package com.test.aidl;
import com.example.a.MainActivity;
import com.test.aidl.AidlInterface.Stub;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class ServerService extends Service {
private String messages="";
private Intent intent;
private Context c;
private AidlInterface.Stub binder=new Stub(){
@Override
public void sendMessage(String message, String[] list)
throws RemoteException {
System.out.println("A-service-recived="+message);
messages=message;
}
@Override
public void toDoAnything() throws RemoteException {
intent =new Intent(c,MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@Override
public String getMessage() throws RemoteException {
return "这是A服务提供的信息";
}
};
@Override
public IBinder onBind(Intent arg0) {
this.c=this;
return binder;
}
}
注意:service里面要实现aidl接口用法为,aidl接口类名我的是AidlInterface所以就是AidlInterface.Stub 关于stub的理解我引用百度搜索结果
j2ee里面的stub是这样说的..为屏蔽客户调用远程主机上的对象,必须提供某种方式来模拟本地对象,这种本地对象称为存根(stub),存根负责接收本地方法调用,并将它们委派给各自的具体实现对象
通过new Stub(){}来实现对aidl接口里面的方法。在service里面实现onBind();方法并返回接口的实体。这样当A项目绑定了这个service的时候就会去执行AidlInterface.Stub binder所有拥有的方法。
这里我在方法toDoAnything()方法里面让他去启动项目A 的activity。这些操作可以随便定义。
4,定义了service并且需要后台不定时提供服务所以就得在项目A的AndroidManifast.xml文件里注册service;代码如下需要注意添加action标签。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.a"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.a.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 注意包名不要写错不然很悲剧的 -->
<service
android:name="com.test.aidl.ServerService"
android:process=":remote" >
<intent-filter>
<action android:name="com.test.aidl.AidlInterface" />
</intent-filter>
</service>
</application>
</manifest>
注意包名必须正确请不要省略。service里面name为服务名 process表示过程流程值为“:remote”表示远程遥控。其实就是夸进程的。添加意图intent 添加action名字为aidl接口类的路径。
5,服务有了可是没有地方开启服务,所以我们要在A首次运行的时候就开启服务不关闭。这里我在A的MainActivity里面开启服务。所以做实验的时候必须先运行项目A再去运行项目AB.开启服务的代码如下:
package com.example.a;
import com.test.aidl.AidlInterface;
import com.test.aidl.ServerService;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
}
private void bindService() {
System.out.println("a service start");
Intent service = new Intent(this, ServerService.class);
startService(service);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
到此项目A的准备工作就结束了,这个时候A已经拥有提供远程或者跨进程的服务了。项目A 的结构很简单就需要注意4个地方定义aidl接口文件、定义服务、注册服务、开启服务。这个时候没有把aidl拷贝到AB的话就拷贝吧。
下面开始介绍项目AB:在项目AB开始之前上面的第2步骤就得完成。
6,aidl文件拷贝过来以后请确认一下包名。AB里面要做的事情就是去调用接口的方法就行了。这里我就在AB的mainActivity里面做操作了代码如下:
package com.example.ab;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import com.test.aidl.AidlInterface;
public class MainActivity extends Activity {
private boolean onbindsuccess = false;
// 实现接口的两个步骤
private AidlInterface aidl = null;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
aidl = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
aidl = AidlInterface.Stub.asInterface(service);
onbindsuccess = true;
System.out.println("Bind success!!!" + aidl);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
/**
* 初始化控件
*/
private void init() {
Button btn = (Button) findViewById(R.id.button1);
Button btn2=(Button) findViewById(R.id.button2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
/**绑定服务这里真正的项目要做的事情会很多 比如判断a项目是否真的存在不存在就去下载安装等操作
* 这里我们已经确认项目A已经安装并且服务已经开启。
* @param v
*/
public void onBind(View v) {
System.out.println("bind click!!!");
Intent service = new Intent(AidlInterface.class.getName());
bindService(service, conn, BIND_AUTO_CREATE);
}
/**我定义的开始服务button点击事件
* @param v
*/
public void startService(View v) {
if (!onbindsuccess) {
System.out.println("bindservice faild");
return;
}
try {
aidl.sendMessage("从AB传递的信息", null);// 和A项目进行通信
aidl.getMessage();// 从A项目获取信息
aidl.toDoAnything();// 这个时候A项目的service会调用todoanything方法体里面的内容。
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
项目AB里面需要注意的是ServiceConnection 类,参考官方API service的介绍。当一个service开启运行的时候通过ServiceConnection 能直接访问此服务。
查阅官方API上面是定义了一个service 下面是通过ServiceConnection 来访问此服务
With that done, one can now write client code that directly accesses the running service, such as:
完成所有以后,现在可以编写客户机代码,直接访问正在运行的服务,如:
到此AB的代码已经完成,关于布局文件:
A里面我什么都没做,AB里面就在mainActivity里面加了俩按钮。完整的项目代码我已上传,不要积分大家可以下载研究学习:
http://download.csdn.net/detail/zhzhh7378/7167441