0
点赞
收藏
分享

微信扫一扫

理解Android系统的进程间通信原理…

少_游 2023-07-27 阅读 69


理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用)。有关RMI的相关知识,可以通过下图来归纳:






Android中的RPC也是参考了JAVA中的RMI方案,这里我们再详细了解一下RPC的实现过程。



Android中的RPC机制是为了实现一个进程使用另一个进程中的远程对象,它使用了Android自己的AIDL(接口定义语言),使用户很方便地定义出一个接口作为规范,通过一个远程Service为代理 ,客户端在绑定该远程Service过程中获取远程对象,进而使用该对象。可参考下图所示:




补充:RPC的另一个目的是对客户端只声明接口及方法,隐藏掉具体实现类,供客户端直接获取此接口实例。



实例代码:



实例一:通过Service来远程调用一个接口子类的函数方法



功能描述:在MainActivity中通过绑定MyService服务类,来远程调用MyPlayer(实现了IPlayer接口)的方法过程。需要定义一个IPlayer.aidl文件,ADT工具会自动生成一个IPlayer接口类,然后再由MyPlayer继承IPlayer接口类中的静态内部抽象类,实现接口方法,进而供其它应用程序远程调用。(在本例中为了方便,MainActivity与MyService类同处一个应用程序中,实现运用时,可以不在同一个应用程序中,只要有权限访问MyService服务,就能得到IPlayer接口,进而执行该接口实例方法)



程序清单:IPlayer.aidl


理解Android系统的进程间通信原理…_ide




package 
    com.magc.rpc;


    interface 
    IPlayer
 {

 
    void 
    setName(String name);
 
    void 
    addFile(String f_name);
 String ToString();
 }



理解Android系统的进程间通信原理…_ide



程序清单:IPlayer.java (ADT根据上面IPlayer.aidl文件自动生成,不能编辑该文件)




package 
    com.magc.rpc;

    public 
    interface 
    IPlayer 
    extends 
    android.os.IInterface
 {

    

    public 
    static 
    abstract 
    class 
    Stub 
    extends 
    android.os.Binder 
    implements 
    com.magc.rpc.IPlayer
 {

    private 
    static 
    final 
    java.lang.String DESCRIPTOR 
    = 
    "
    com.magc.rpc.IPlayer
    "
    ;

    

    public 
    Stub()
 {

    this
    .attachInterface(
    this
    , DESCRIPTOR);
 }

    

    public 
    static 
    com.magc.rpc.IPlayer asInterface(android.os.IBinder obj)
 {

    if 
    ((obj
    ==
    null
    )) {

    return 
    null
    ;
 }
 android.os.IInterface iin 
    = 
    (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);

    if 
    (((iin
    !=
    null
    )
    &&
    (iin 
    instanceof 
    com.magc.rpc.IPlayer))) {

    return 
    ((com.magc.rpc.IPlayer)iin);
 }

    return 
    new 
    com.magc.rpc.IPlayer.Stub.Proxy(obj);
 }

    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_setName:
 {
 data.enforceInterface(DESCRIPTOR);
 java.lang.String _arg0;
 _arg0 
    = 
    data.readString();

    this
    .setName(_arg0);
 reply.writeNoException();

    return 
    true
    ;
 }

    case 
    TRANSACTION_addFile:
 {
 data.enforceInterface(DESCRIPTOR);
 java.lang.String _arg0;
 _arg0 
    = 
    data.readString();

    this
    .addFile(_arg0);
 reply.writeNoException();

    return 
    true
    ;
 }

    case 
    TRANSACTION_ToString:
 {
 data.enforceInterface(DESCRIPTOR);
 java.lang.String _result 
    = 
    this
    .ToString();
 reply.writeNoException();
 reply.writeString(_result);

    return 
    true
    ;
 }
 }

    return 
    super
    .onTransact(code, data, reply, flags);
 }

    private 
    static 
    class 
    Proxy 
    implements 
    com.magc.rpc.IPlayer
 {

    private 
    android.os.IBinder mRemote;
 Proxy(android.os.IBinder remote)
 {
 mRemote 
    = 
    remote;
 }

    public 
    android.os.IBinder asBinder()
 {

    return 
    mRemote;
 }

    public 
    java.lang.String getInterfaceDescriptor()
 {

    return 
    DESCRIPTOR;
 }

    public 
    void 
    setName(java.lang.String name) 
    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.writeString(name);
 mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 
    0
    );
 _reply.readException();
 }

    finally 
    {
 _reply.recycle();
 _data.recycle();
 }
 }

    public 
    void 
    addFile(java.lang.String f_name) 
    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.writeString(f_name);
 mRemote.transact(Stub.TRANSACTION_addFile, _data, _reply, 
    0
    );
 _reply.readException();
 }

    finally 
    {
 _reply.recycle();
 _data.recycle();
 }
 }

    public 
    java.lang.String ToString() 
    throws 
    android.os.RemoteException
 {
 android.os.Parcel _data 
    = 
    android.os.Parcel.obtain();
 android.os.Parcel _reply 
    = 
    android.os.Parcel.obtain();
 java.lang.String _result;

    try 
    {
 _data.writeInterfaceToken(DESCRIPTOR);
 mRemote.transact(Stub.TRANSACTION_ToString, _data, _reply, 
    0
    );
 _reply.readException();
 _result 
    = 
    _reply.readString();
 }

    finally 
    {
 _reply.recycle();
 _data.recycle();
 }

    return 
    _result;
 }
 }

    static 
    final 
    int 
    TRANSACTION_setName 
    = 
    (android.os.IBinder.FIRST_CALL_TRANSACTION 
    + 
    0
    );

    static 
    final 
    int 
    TRANSACTION_addFile 
    = 
    (android.os.IBinder.FIRST_CALL_TRANSACTION 
    + 
    1
    );

    static 
    final 
    int 
    TRANSACTION_ToString 
    = 
    (android.os.IBinder.FIRST_CALL_TRANSACTION 
    + 
    2
    );
 }

    public 
    void 
    setName(java.lang.String name) 
    throws 
    android.os.RemoteException;

    public 
    void 
    addFile(java.lang.String f_name) 
    throws 
    android.os.RemoteException;

    public 
    java.lang.String ToString() 
    throws 
    android.os.RemoteException;
 }




package 
    com.magc.rpc;


    import 
    android.os.RemoteException;

    import 
    android.util.Log;


    import 
    com.magc.rpc.IPlayer.Stub;

    

    public 
    class 
    MyPlayer 
    extends 
    Stub {

 
    private 
    String name
    =
    ""
    ;
 @Override
 
    public 
    void 
    addFile(String fName) 
    throws 
    RemoteException {

 System.out.println(
    "
    add file ...
    "
    );

 }

 @Override
 
    public 
    void 
    setName(String name) 
    throws 
    RemoteException {

 
    this
    .name 
    = 
    name;
 Log.i(
    "
    magc
    "
    , 
    "
    setName--
    "
    +
    name);
 }

 
    public 
    String ToString()
 {
 String str 
    = 
    "
    MyPlayer--
    "
    +
    name;
 Log.i(
    "
    magc
    "
    , 
    "
    MyPlayer--
    "
    +
    name);
 
    return 
    str;
 }

 }





程序清单:MyService.java (一个Service类,供其它程序来远程绑定,返回IPlayer接口)



理解Android系统的进程间通信原理…_ide



package 
    com.magc.rpc;


    import 
    com.magc.rpc.IPlayer.Stub;


    import 
    android.app.Service;

    import 
    android.content.Intent;

    import 
    android.os.IBinder;



    

    public 
    class 
    MyService 
    extends 
    Service {

 
    private 
    Stub player 
    = 
    new 
    MyPlayer();
 @Override
 
    public 
    IBinder onBind(Intent arg0) {
 
    return 
    player;
 }

 @Override
 
    public 
    void 
    onCreate() {
 
    super
    .onCreate();
 }

 }


理解Android系统的进程间通信原理…_ide





程序清单:MainActivity.java (作为客户端远程调用IPlayer接口方法)




package 
    com.magc.rpc;


    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.util.Log;

    

    public 
    class 
    MainActivity 
    extends 
    Activity {
 
    private 
    String ACTION
    =
    "
    com.magc.rpc.action.MYSERVICE
    "
    ;
 
    private 
    IPlayer player;
 
    
 @Override
 
    public 
    void 
    onCreate(Bundle savedInstanceState) {
 
    super
    .onCreate(savedInstanceState);
 setContentView(R.layout.main);
 Intent intent 
    = 
    new 
    Intent();
 intent.setAction(ACTION);
 
    //
    绑定MyService服务
    
 
    bindService(intent, conn, BIND_AUTO_CREATE);


 }
 
    private 
    ServiceConnection conn 
    = 
    new 
    ServiceConnection() {

 @Override
 
    public 
    void 
    onServiceDisconnected(ComponentName name) {

 }

 
    
 @Override
 
    public 
    void 
    onServiceConnected(ComponentName name, IBinder service) {
 Log.i(
    "
    magc
    "
    , 
    "
    bind service .....
    "
    );
 player 
    = 
    IPlayer.Stub.asInterface(service);
 
    if
    (player
    !=
    null
    )
 {
 
    try 
    {
 player.setName(
    "
    magc
    "
    );
 player.ToString();
 } 
    catch 
    (RemoteException e) {
 
    // 
    TODO Auto-generated catch block
    
 
    e.printStackTrace();
 }
 }
 }
 };
 }



程序清单:AndroidManifest.xml (注册Activity和Service)



理解Android系统的进程间通信原理…_ide




举报

相关推荐

0 条评论