Android 远程 service 和 Binder

来源:互联网 发布:网络投资理财公司 编辑:程序博客网 时间:2024/06/06 06:31

Android 中 的远程 Service 以及Binder介绍

1.远程 Service 介绍

 在Android平台,每个应用程序都是一个单独的JVM,都运行在自己的进程空间里, 通常,一个进程不允许访问另一个进程的内存空间(一个应用不能访问另一个应用)。当用户(程序开发人员)想在一个App中访问另一个App的进程空间的时候,就需要进程间通信。在Android中,远程服务为我们提供了实现进程间通信的方式,其中,AIDL是应用程序开发人员常的一种方式。
    

    AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity 与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"


  总结来说,一个应用想要和运行在其他进程中的 Service,这个Service我们叫做远程Service


2.Binder 介绍

直观来说,Binder是Android中的一个类,它继承了IBinder接口。从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有;从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

Binder一个很重要的作用是:将客户端的请求参数通过Parcel包装后传到远程服务端,远程服务端解析数据并执行对应的操作,同时客户端线程挂起,当服务端方法执行完毕后,再将返回结果写入到另外一个Parcel中并将其通过Binder传回到客户端,客户端接收到返回数据的Parcel后,Binder会解析数据包中的内容并将原始结果返回给客户端,至此,整个Binder的工作过程就完成了。由此可见,Binder更像一个数据通道,Parcel对象就在这个通道中跨进程传输,至于双方如何通信,这并不负责,只需要双方按照约定好的规范去打包和解包数据即可。

3. 远程Service 结构


 IRemoteService.aidl  在工程的src 下创建名为.aidl 的文件,定义需要实现的接口,定义好之后刷新,会在工程的gen目录下生成 IRemoteService.java,当然我们也可以自己写IRemoteService.java,但是这里涉及到Binder

  创建RemoteService继承自Service, 实现IRemoteService.java的接口

   在客户端Activity中调用Service


IRemoteService.aidl:


interface ISoftSimService {

    int Operation(int a);

}

自动生成的 IRemoteService.java


这里涉及到Binder的机制,后面再补上

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original fileHello/src/com/example/hello/IRemoteService.aidl
 */
package com.example.hello;
public interface IRemoteService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.hello.IRemoteService
{
private static final java.lang.String DESCRIPTOR = "com.example.hello.IRemoteService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.example.hello.IRemoteService interface,
 * generating a proxy if needed.
 */
public static com.example.hello.IRemoteService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.hello.IRemoteService))) {
return ((com.example.hello.IRemoteService)iin);
}
return new com.example.hello.IRemoteService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_Operation:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.Operation(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.hello.IRemoteService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * Indicates the underlying service is connected and methods at {@link ISoftSimService} are
     * ready to use.
     */
@Override public void Operation(int var) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(var);
mRemote.transact(Stub.TRANSACTION_Operation, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_Operation = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
/**
     * Indicates the underlying service is connected and methods at {@link ISoftSimService} are
     * ready to use.
     */
public void Operation(int var) throws android.os.RemoteException;
}


RemoteService.java 实现重要代码块

public class RemoteService extends Service {


    //MyRemoteSercie,继承我们的AIDL文件自动生成的内部类,
    //并且实现我们AIDL文件定义的接口方法
    private class MyRemoteSercie extends IFileCountService.Stub{

        @Override
        public int Operation(int a) throws RemoteException {
             
           ....
                      
        }
            return fileCnt;
        
    }
    }
    
    @Override
    public IBinder onBind(Intent arg0) {
        //返回AIDL实现
        return new MyRemoteServiceImpl();
    }
       
    @Override
    public void onDestroy(){
        Log.e(TAG, "Release MyService");
        super.onDestroy();
    }
    
    
}


Activity 调用:

public class MyActivity extends Activity {


       @Override
       public void onCreate(Bundle savedInstanceState){


                    bindService();


       }
       
       IRemoteService iService=null;
       private ServiceConnection  conn=new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {


            iService=IRemoteService.Stub.asInterface(service);
            
            try {
                iService.Operation(1);
            }
            catch (RemoteException e) {


                e.printStackTrace();
            }


        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected");
        }
       };
       
       private void bindService(){
           Intent intent=new Intent(this,RemoteService.class);
           startService(intent);
           bindService(intent, conn, Context.BIND_AUTO_CREATE);
       } 
}



原创粉丝点击