第二篇:Android学习之AIDL学习:
绑定远程服务
一、跨应用绑定服务Service:前言
在进行服务的绑定时,需要用到一个Service内自定以的Binder对象,而由于服务是远程的。所以,无法直接获取自定义Binder
类的定义。在Android中,有一种机制可以处理这种问题,就是通过使用AIDL来进行远程服务的绑定。
主要用道德就是后缀名时aidl的接口实现的。
二、实现
首先,需要有一个包含自定义服务的应用和一个普通应用。同时,需要在包含被调用服务的app中创建一个AIDL;创建方法如下:
选中java文件夹右键创建AIDL文件。会在与java同级目录下创建一个相应的aidl文件夹,其中有一个package,包名和
activity的一样。当创建好之后,需要在调用者目录下创建一个和被调用者相同的aidl文件夹,并在 其中创建相同的包,之后,将之前创建好
的aidl复制进去即可。
这里以app1和app2为例。其中内部构造如下:
app1:MainActivity、MyService、IServiceRemoteAIDL
在app1中需要创建一个aidl接口供其他应用访问。定义如下:
- IServiceRemoteAIDL.aidl
interface IServiceRemoteAIDL {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
- MyService.java
public class MyService extends android.app.Service{
public IBinder onBind(Intent intent){
return new com.snowlive.service14.IServiceRemoteAIDL(){
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString) throws RemoteException {
}
};
}
public void onCreate(){
System.out.println("MyService is Start");
}
}
这个例子主要是实现通过app2绑定app1的MyService
在进行远程服务的启动和绑定是都需要通过使用Intent的setComponent(ComponentName name)
方法创建相应的Intent
对象。从而实现调用其他应用服务的功能。绑定和解绑远程服务方法和对普通服务的操作无异。
app2:MainActivity.java
public class MainActivity extends Activity implements ServiceConnection{
private Intent serviceIntent;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent();
/**
*这里的ComponentName(String packageName,String className);
* 参数的含义依次为:服务的包名,服务的类名。
*/
serviceIntent.setComponent(new ComponentName("com.snowlive.service14","com.snowlive.service14.SendInfoService"));
//绑定服务
bindService(serviceIntent,this,(Context).BIND_AUTO_CREATE);
}
protected void onDestroy() {
super.onDestroy();
//解绑服务
unbindService(this);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("Bind Service");
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
通过在Activity的onCreate方法设置serviceIntent,并调用
bindService(Intent intent,ServiceConnection conn,int tag)
方法启动服务
在Activity的onDestroy方法调用stopService(ServiceConnectioin conn)
方法停止服务。
三、远程服务数据通信
在实现此功能时,只需要在更改上面的IServiceRemoteAIDL、MyService、MainActivity即可。
这里以,更改MyService 中的一个内部数据为例。
注意:app1和app2的ISerivceRemoteAIDL是都需要更改的,更改的代码是一样的。
具体更改如下:
- IServiceRemoteAIDL.aidl
interface IServiceRemoteAIDL {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void setData(String data);//设置Service内部数值的方法
}
- MyService.java
public class MyService extends android.app.Service{
private String data = "default data";
public IBinder onBind(Intent intent){
return new com.snowlive.service14.IServiceRemoteAIDL(){
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString) throws RemoteException {
}
@Override
public void setData(String data) throws RemoteException {
SendInfoService.this.data = data;
}
};
}
public void onCreate(){
new Thread(){
public void run(){
while(Running){
Log.w("MyServiceInfo:" ,data);
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
System.out.println("MyService is Start");
}
public void onDestroy(){
super.onDestroy();
Running = false;
}
}
更改app2:MainActivity.java的同时需要在activity中添加一个id为bt_sync的按键,用于更改远程服务的数据
- app2 的MainActivity.java
public class MainActivity extends Activity implements ServiceConnection,View.OnClickListener{
private Intent serviceIntent;
private com.snowlive.service14.IServiceRemoteAIDL remotebinder;//定义AIDL。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent();
/**
*这里的ComponentName(String packageName,String className);
* 参数的含义依次为:服务的包名,服务的类名。
*/
serviceIntent.setComponent(new ComponentName("com.snowlive.service14","com.snowlive.service14.SendInfoService"));
//绑定服务
bindService(serviceIntent,this,(Context).BIND_AUTO_CREATE);
findViewById(R.id.bt_sync).setOnClickListener(this);//为信息同步按键添加监听事件。
}
protected void onDestroy() {
super.onDestroy();
//解绑服务
unbindService(this);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("Bind Service");
//将接收到的Binder转化为IServiceRemoteAIDL
remotebinder = IServiceRemoteAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
public void onClick(View v){
if(remotebinder!=null){
try {
remotebinder.setData(etShow.getText().toString());
Toast.makeText(this,etShow.getText().toString(),Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
综上,通过定义AIDL作为远程服务的Binder返回对象来实现绑定远程服务,和远程服务通信的功能。
四、总结:
再次回顾,绑定远程服务及和远程服务通行实现过程:
AIDL操作:
- 在需要被调用的远程服务应用中定义AIDL,将需要实现的方法定义在AIDL中。
- 将定义好的AIDL的结构,原封不动的复制到需要调用该服务的应用中(文件名->包名->AIDL)
被调用的服务Serivce
- 在onBinder()方法中将返回值设置为AIDL对象同时实现其中方法,对服务中的数据进行操作。
- 为Intent设置Component,在Component中设置远程服务的具体信息(报名,类全名)。
调用者Activity
- 定义调用远程服务的Intent,设置其Component属性。
- 定义AIDL对象,在服务链接时用于接收Binder对象。
- 实现SericeConnection接口,接收Binder对象。
- 添加事件响应机制,实现数据的传输和服务的操作。