首页 > 系统相关 >解Android系统的进程间通信原理(二)----RPC机制(转)

解Android系统的进程间通信原理(二)----RPC机制(转)

时间:2023-05-08 22:32:31浏览次数:32  
标签:PC机 ---- String 间通信 magc IPlayer android os public


解Android系统的进程间通信原理(二)----RPC机制


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



解Android系统的进程间通信原理(二)----RPC机制(转)_移动开发



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



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



解Android系统的进程间通信原理(二)----RPC机制(转)_android_02



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



实例代码:



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



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



程序清单:IPlayer.aidl



package com.magc.rpc;

interface IPlayer
{

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



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



/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\\work\\Android_App\\MyRPCService\\src\\com\\magc\\rpc\\IPlayer.aidl
 */
package com.magc.rpc;
public interface IPlayer extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
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";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.magc.rpc.IPlayer interface,
 * generating a proxy if needed.
 */
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;
}



程序清单:MyPlayer.java  (实现IPlayer的静态内部抽象类Stub)



package com.magc.rpc;

import android.os.RemoteException;
import android.util.Log;

import com.magc.rpc.IPlayer.Stub;
/**
 * 
 * @author magc
 * 实现IPlayer接口类中的静态内部抽象类,即实现IPlayer接口方法
 * 将来供其它应用程序远程调用执行方法
 */
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接口)




package com.magc.rpc;

import com.magc.rpc.IPlayer.Stub;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;


/**
 * 
 * @author magc
 * 此服务类作为一个代理角色,供其它应用程序绑定,并返回接口实例
 * 
 * 可看作是代理模式的应用
 */
public class MyService extends Service {

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

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

}



程序清单: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;
/**
 * 
 * @author magc
 * 作为一个客户端通过绑定MyService服务,实现远程调用IPlayer接口方法
 * 
 */
public class MainActivity extends Activity {
    private  String ACTION="com.magc.rpc.action.MYSERVICE";
    private IPlayer player;
    /** Called when the activity is first created. */
    @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) {
            
        }
        
        /**
         * 绑定MyService服务后,返回IPlayer接口,进而调用该接口方法 
         */
        @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)




<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.magc.rpc"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="9" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".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=".MyService">
        <intent-filter>
        <action android:name="com.magc.rpc.action.MYSERVICE" />
        <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        </service>
    </application>
</manifest>



上面Android应用程序运行后结果如下所示:




解Android系统的进程间通信原理(二)----RPC机制(转)_ide_03



解Android系统的进程间通信原理(二)----RPC机制(转)_移动开发_04


小结:


1、重点理解Android中对AIDL文件的定义,以及理解ADT工具自动生成的接口类IPlayer,特别是它的静态内部类Stub以及Stub的asInterface方法,


2、Service作为一个代理角色,在其它应用程序通过Stub类的asInterface方法在绑定到一个服务时才能实现返回该接口实例,进而对该实例进行相关操作。


待续

标签:PC机,----,String,间通信,magc,IPlayer,android,os,public
From: https://blog.51cto.com/u_2198048/6256344

相关文章

  • android native jni 代码
    数组的常用操作:  对象的常用操作: 另外 这个里面有JNI各个方法的说明 可以当做api 2、推荐一个网址 里面关于jni的学习内容比较多    ===============================================================================================================//找到类......
  • 全志A10平板上的ubuntu终极安装版,支持HDMI和平板本机LCD,全新内核硬浮点加速,堪比i3 XP
     这个ubuntu系统仍然是安装在miniSD卡中。与原andorid系统相互独立,构成android/ubunut双系统,原android丝毫不动,工作学习开发可以使用ubuntu。    该款img映像文件来自Linaro 12.06 armhf build项目,目前版本为http://dl.miniand.com/toby_corkindale/linaro-alip-armhf-t4......
  • KBC POKER完整功能介绍
    先用效果图来解释下面是完整版的配列视图看不清的请点击看大图键盘爱好者是用键盘来表达自己的想法传递我们的理念首先向大家介绍的就是POKER的语法:POKER有五套“语言系统” 其中Fn是这套系统的核心组成部分1.键帽正面的同刻——是最普通最好理解的大家所见即所得2.键帽侧面......
  • AtCoder Beginner Contest 209(D,E)
    AtCoderBeginnerContest209(D,E)D(树,lca)D这个题给出\(n\)个点,\(n-1\)条边,有两个人,一个人在\(c\)点,一个人在\(d\)点,两人以相同的速度朝着对方走来(并且都是按照最短路的走法),问这两个人相遇是在点上,还是在路上这一题意很好知道,就是判断这两点之间的最短距离的奇偶性然后我就一......
  • JVM快速入门
    内存结构1.程序计数器1.1.定义ProgramCounterRegister程序计数器(寄存器)1.2.作用记住下一条jvm指令的执行地址1.3.特点是线程私有的不会存在内存溢出2.虚拟机栈2.1.定义JavaVirtualMachineStacks(Java虚拟机栈)每个线程运行时所需要的内存,称为虚拟机栈每个栈......
  • 模板类
    1、复数类Complex有两个数据成员:a和b,分别代表复数的实部和虚部,并有若干构造函数和一个重载-(减号,用于计算两个复数的距离)的成员函数。要求设计一个函数模板template<classT>doubledist(Ta,Tb)对int,float,Complex或者其他类型的数据,返回两个数据的间距。以上类名和函......
  • CMake+Visual Studio构建Qt程序
    转载:https://www.codenong.com/cs106288798/转载:https://zhuanlan.zhihu.com/p/400804242一、编写代码文件main.cpp#include<QApplication>#include"Mainwindow.h"intmain(intargc,char*argv[]){QApplicationapp(argc,argv);MainWindowmain......
  • 1008 数组元素循环右移问题
    一、问题描述:一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0​A1​⋯AN−1​)变换为(AN−M​⋯AN−1​A0​A1​⋯AN−M−1​)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法......
  • 【大数据】yarn 任务中的几种状态变化详细过程
    目录一、概述1)Application状态2)Container状态二、资源不足情况下状态变化1)资源不足情况下2)任务超时时间配置1、yarn-site.xml文件中配置超时时间2、mapred-site.xml文件中配置超时时间三、环境准备四、Yarn工作流程五、Yarn常用命令1)查看应用程序3)查看指定应用程序的日志4)查......
  • JS之根据两地经纬度获得两点之间的距离
    JS之根据两地经纬度获得两点之间的距离:constgetDistance=(lat1,lng1,lat2,lng2)=>{lat1=lat1||0;lng1=lng1||0;lat2=lat2||0;lng2=lng2||0;varrad1=(lat1*Math.PI)/180.0;varrad2=(lat2*Math.PI)/180.0;vara=ra......