Android基本功:跨进程调用Services(AIDL Service)
2016-08-15 18:34
441 查看
一、AIDL Service简介
Android系统中,各个应用都运行在自己的进程中,进程之间一般无法直接进行通信,为了实现进程通信(interprocess communication,简称IPC),Android提供了AIDL Service;
二、与本地Service不同
本地Service:直接把IBinder对象本身传递给客户端的ServiceConnection的onServiceConnected方法的第二个参数;
远程Service:只将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数;
三、AIDL文件
Android需要AIDL(Android Interface
Definition Language)来定义远程接口,这种接口定义语言并不是一种真正的变成语言,只是定义两个进程之间的通信接口;
与Java接口相似,但是存在如下几点差异:
AIDL定义接口的源代码必须以.aidl结尾;
AIDL用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其它类型全部都需要导包,即使它们在同一个包中也需要导包;
四、使用AIDL的步骤(详细代码可见AIDLService和AIDLClient项目)
1.创建AIDL文件
[java] view
plain copy
package com.example.aidlservice;
interface ICat {
String getColor();
double getWeight();
}
定义好AIDL文件后,ADT工具会自动在gen/com/example/aidlservice/目录下生成一个ICat.java接口,该类内部包含一个Stub内部类,实现了IBinder,ICat两个接口,这个Stub类会作为远程Service回调类;
2.将接口暴露给客户端
[java] view
plain copy
package com.example.aidlservice;
import java.util.Timer;
import java.util.TimerTask;
import com.example.aidlservice.ICat.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AidlService extends Service {
String[] colors = new String[] { "红色", "黄色", "黑色" };
double[] weights = new double[] { 2.3, 3.1, 1.58 };
private String color;
private double weight;
private CatBinder catBinder;
Timer timer = new Timer();
@Override
public void onCreate() {
super.onCreate();
catBinder = new CatBinder();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 随机地改变service组件内的color,weight属性的值
int rand = (int) (Math.random() * 3);
color = colors[rand];
weight = weights[rand];
System.out.println("---------" + rand);
}
}, 0, 800)};
@Override
public IBinder onBind(Intent arg0) {
/**
* 返回CatBinder对象,在绑定本地Service情况下,
* 该catBinder会直接传给客户端的ServiceConnected对象的ServiceConnected
* ()方法的第二个参数;在绑定远程Service的情况下
* ,只将catBinder对象的代理传给客户端的ServiceConnected对象的ServiceConnected()方法的第二个参数
*/
return catBinder;
}
@Override
public void onDestroy() {
timer.cancel();
}
/**
* 继承Stub,也就是实现了ICat接口,并实现了IBinder接口
*
* @author pengcx
*
*/
public class CatBinder extends Stub {
@Override
public String getColor() throws RemoteException {
return color;
}
@Override
public double getWeight() throws RemoteException {
return weight;
}
}
}
在AndroidManifext.xml文件中配置该Service;
[html] view
plain copy
<service android:name="com.example.aidlservice.AidlService" >
<intent-filter>
<action android:name="org.crazyit.aidl.action.AIDL_SERVICE" />
</intent-filter>
</service>
3.客户端访问AIDLService
将Service端的AIDL文件复制到客户端中,注意要在相同的包名下。
[java] view
plain copy
package com.example.aidlclient;
import com.example.aidlservice.ICat;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
public class AidlClient extends Activity {
private ICat catService;
private Button getButton;
private EditText colorEditText, weightEditText;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
catService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取远程Service的onBinder方法返回的对象代理
catService = ICat.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl_client);
getButton = (Button) findViewById(R.id.getbutton);
colorEditText = (EditText) findViewById(R.id.coloredittext);
weightEditText = (EditText) findViewById(R.id.weightedittext);
// 创建所需要绑定的Service的Intent
Intent intent = new Intent();
intent.setAction("org.crazyit.aidl.action.AIDL_SERVICE");
// 绑定远程的服务
bindService(intent, conn, Service.BIND_AUTO_CREATE);
getButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 获取并显示远程service的状态
try {
colorEditText.setText(catService.getColor());
weightEditText.setText(catService.getWeight() + "");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解除绑定
this.unbindService(conn);
}
}
错误:java.lang.SecurityException:
Binder invocation to an incorrect interface。在使用上请注意,服务端与客户端都要有相同的接口(使用到的),这里的“相同”是指完全相同,包括包名,也就是说要在不同工程下建立相同的包名。
Android系统中,各个应用都运行在自己的进程中,进程之间一般无法直接进行通信,为了实现进程通信(interprocess communication,简称IPC),Android提供了AIDL Service;
二、与本地Service不同
本地Service:直接把IBinder对象本身传递给客户端的ServiceConnection的onServiceConnected方法的第二个参数;
远程Service:只将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数;
三、AIDL文件
Android需要AIDL(Android Interface
Definition Language)来定义远程接口,这种接口定义语言并不是一种真正的变成语言,只是定义两个进程之间的通信接口;
与Java接口相似,但是存在如下几点差异:
AIDL定义接口的源代码必须以.aidl结尾;
AIDL用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其它类型全部都需要导包,即使它们在同一个包中也需要导包;
四、使用AIDL的步骤(详细代码可见AIDLService和AIDLClient项目)
1.创建AIDL文件
[java] view
plain copy
package com.example.aidlservice;
interface ICat {
String getColor();
double getWeight();
}
定义好AIDL文件后,ADT工具会自动在gen/com/example/aidlservice/目录下生成一个ICat.java接口,该类内部包含一个Stub内部类,实现了IBinder,ICat两个接口,这个Stub类会作为远程Service回调类;
2.将接口暴露给客户端
[java] view
plain copy
package com.example.aidlservice;
import java.util.Timer;
import java.util.TimerTask;
import com.example.aidlservice.ICat.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AidlService extends Service {
String[] colors = new String[] { "红色", "黄色", "黑色" };
double[] weights = new double[] { 2.3, 3.1, 1.58 };
private String color;
private double weight;
private CatBinder catBinder;
Timer timer = new Timer();
@Override
public void onCreate() {
super.onCreate();
catBinder = new CatBinder();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 随机地改变service组件内的color,weight属性的值
int rand = (int) (Math.random() * 3);
color = colors[rand];
weight = weights[rand];
System.out.println("---------" + rand);
}
}, 0, 800)};
@Override
public IBinder onBind(Intent arg0) {
/**
* 返回CatBinder对象,在绑定本地Service情况下,
* 该catBinder会直接传给客户端的ServiceConnected对象的ServiceConnected
* ()方法的第二个参数;在绑定远程Service的情况下
* ,只将catBinder对象的代理传给客户端的ServiceConnected对象的ServiceConnected()方法的第二个参数
*/
return catBinder;
}
@Override
public void onDestroy() {
timer.cancel();
}
/**
* 继承Stub,也就是实现了ICat接口,并实现了IBinder接口
*
* @author pengcx
*
*/
public class CatBinder extends Stub {
@Override
public String getColor() throws RemoteException {
return color;
}
@Override
public double getWeight() throws RemoteException {
return weight;
}
}
}
在AndroidManifext.xml文件中配置该Service;
[html] view
plain copy
<service android:name="com.example.aidlservice.AidlService" >
<intent-filter>
<action android:name="org.crazyit.aidl.action.AIDL_SERVICE" />
</intent-filter>
</service>
3.客户端访问AIDLService
将Service端的AIDL文件复制到客户端中,注意要在相同的包名下。
[java] view
plain copy
package com.example.aidlclient;
import com.example.aidlservice.ICat;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
public class AidlClient extends Activity {
private ICat catService;
private Button getButton;
private EditText colorEditText, weightEditText;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
catService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取远程Service的onBinder方法返回的对象代理
catService = ICat.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl_client);
getButton = (Button) findViewById(R.id.getbutton);
colorEditText = (EditText) findViewById(R.id.coloredittext);
weightEditText = (EditText) findViewById(R.id.weightedittext);
// 创建所需要绑定的Service的Intent
Intent intent = new Intent();
intent.setAction("org.crazyit.aidl.action.AIDL_SERVICE");
// 绑定远程的服务
bindService(intent, conn, Service.BIND_AUTO_CREATE);
getButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 获取并显示远程service的状态
try {
colorEditText.setText(catService.getColor());
weightEditText.setText(catService.getWeight() + "");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解除绑定
this.unbindService(conn);
}
}
错误:java.lang.SecurityException:
Binder invocation to an incorrect interface。在使用上请注意,服务端与客户端都要有相同的接口(使用到的),这里的“相同”是指完全相同,包括包名,也就是说要在不同工程下建立相同的包名。
相关文章推荐
- Android基本功:跨进程调用Services(AIDL Service)
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- Android AIDL跨进程调用Service
- android跨进程调用Service(AIDL服务)
- Android笔记三十.Service入门(四).跨进程调用Service(AIDL Service)
- Android四大组件应用系列5——使用AIDL实现跨进程调用Service
- Android AIDL:跨进程调用Service (AIDL Service)
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- Android---44---使用AIDL Service 实现跨进程调用Service
- android基础笔记:服务(Service)跨进程调用Service(AIDL Service)
- AIDL Service,跨进程调用Services
- Android的Service与BroadcastReceiver之二 跨进程调用Service(AIDL Service)
- 跨进程调用Service(AIDL服务) (附图 附源码) 推荐
- 初学Android,跨进程调用Service(六十)
- Android Service Messenger & AIDL 的跨进程通信例子 推荐
- Android菜鸟的成长笔记(21)——跨进程调用Service
- 跨进程调用Service(AIDL服务)
- AIDL Android跨进程通信调用实例
- Android -- service的开启方式, start开启和绑定开启服务,调用服务的的方法, aidl调用远程服务
- 跨进程调用Service(AIDL 服务)