hermes进程间通信
Posted 天耀106
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hermes进程间通信相关的知识,希望对你有一定的参考价值。
1、主界面Activity
package lwl.tianyao.hermes;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import com.winfo.gdmsaec.app.hermes.core.Heremes;
import lwl.tianyao.hermes.manager.UserManager;
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Heremes.regiest(UserManager.class);
UserManager.getInstance().setUserName("主进程设置用户:lwl");
public void getUserName(View view)
Toast.makeText(this, UserManager.getInstance().getUserName(), Toast.LENGTH_SHORT).show();
public void setUserName(View view)
UserManager.getInstance().setUserName("主进程设置用户:lwl");
public void goTest(View view)
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
public void go(View view)
Intent intent = new Intent(this, MMActivity.class);
startActivity(intent);
主界面布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="goTest"
android:text="跳转Test子进程" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="go"
android:text="跳转MM子进程" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="setUserName"
android:text="设置名字" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getUserName"
android:text="获取名字" />
</LinearLayout>
2、Test界面Activity
package lwl.tianyao.hermes;
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.support.annotation.Nullable;
import android.view.View;
import android.widget.Toast;
import lwl.tianyao.hermes.manager.MainService;
public class TestActivity extends Activity
private ServiceConnection serviceConnection;
IMainService iMainService;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
serviceConnection = new ServiceConnection()
@Override
public void onServiceConnected(ComponentName name, IBinder service)
iMainService = IMainService.Stub.asInterface(service);
@Override
public void onServiceDisconnected(ComponentName name)
;
bindService(new Intent(this, MainService.class), serviceConnection, BIND_AUTO_CREATE);
public void getUserName(View view)
try
Toast.makeText(this, iMainService.getUserName(), Toast.LENGTH_SHORT).show();
catch (RemoteException e)
e.printStackTrace();
public void setUserName(View view)
try
iMainService.setUserName("test进程设置用户:lwl");
catch (RemoteException e)
e.printStackTrace();
public void go(View view)
finish();
@Override
protected void onDestroy()
super.onDestroy();
unbindService(serviceConnection);
测试界面布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<Button
android:onClick="go"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="返回主进程"/>
<Button
android:onClick="setUserName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="设置名字"/>
<Button
android:onClick="getUserName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="获取名字"/>
</LinearLayout>
测试界面绑定服务:
package lwl.tianyao.hermes.manager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import lwl.tianyao.hermes.IMainService;
public class MainService extends Service
@Nullable
@Override
public IBinder onBind(Intent intent)
return new IMainService.Stub()
@Override
public String getUserName() throws RemoteException
return UserManager.getInstance().getUserName();
@Override
public void setUserName(String name) throws RemoteException
UserManager.getInstance().setUserName(name);
;
测试界面绑定服务aidl
// IMainService.aidl
package lwl.tianyao.hermes;
interface IMainService
String getUserName();
void setUserName(String name);
3、MM界面的Activity
package lwl.tianyao.hermes;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.Toast;
import com.winfo.gdmsaec.app.hermes.core.Heremes;
import lwl.tianyao.hermes.manager.IUserManager;
public class MMActivity extends Activity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mm);
Heremes.connect(this);
public void getUserName(View view)
IUserManager iUserManager = Heremes.getInstance(IUserManager.class);
Toast.makeText(this, iUserManager.getUserName(), Toast.LENGTH_SHORT).show();
public void setUserName(View view)
IUserManager iUserManager = Heremes.getInstance(IUserManager.class);
iUserManager.setUserName("----MM进程设置用户:lwl");
public void go(View view)
finish();
MM界面调用的Hermes类:
package com.winfo.gdmsaec.app.hermes.core;
import android.content.Context;
import android.util.Log;
import com.winfo.gdmsaec.app.hermes.core.model.Request;
import com.winfo.gdmsaec.app.hermes.core.model.Response;
import java.lang.reflect.Proxy;
public class Heremes
private static final String TAG = "Heremes";
//服务端
//注册 允许客户端调用的接口
public static void regiest(Class<?> service)
TypeCenter.getInstance().regiest(service);
//客户端
public static void connect(Context context)
connect(context, null, HermesService.HermesService0.class);
public static void connect(Context context, Class<? extends HermesService> service)
connect(context, null, service);
public static void connect(Context context, String pkgName)
connect(context, pkgName, HermesService.HermesService0.class);
public static void connect(Context context, String pkgName, Class<? extends HermesService> service)
Channel.getInstance().bind(context, pkgName, service);
public static void disconnect(Context context, Class<? extends HermesService> service)
Channel.getInstance().unBind(context.getApplicationContext(), service);
public static <T> T getInstance(Class<T> instanceClass, Object... parameters)
return getInstance(instanceClass, HermesService.HermesService0.class, parameters);
public static <T> T getInstance(Class<T> instanceClass, Class<? extends HermesService> service, Object... parameters)
return getInstance(instanceClass, "getInstance", service, parameters);
public static <T> T getInstance(Class<T> instanceClass, String methodName, Class<? extends HermesService> service, Object... parameters)
Response response = Channel.getInstance().send(Request.GET_INSTANCE, service, instanceClass, methodName, parameters);
if (response.isSuccess())
return getProxy(instanceClass, service);
Log.e(TAG, response.getMessage());
return null;
static <T> T getProxy(Class<T> instanceClass, Class<? extends HermesService> service)
return (T) Proxy.newProxyInstance(instanceClass.getClassLoader(), new Class[]instanceClass, new HermesInvocationHandler(instanceClass, service));
Hermes调用的通道类Channel:
package com.winfo.gdmsaec.app.hermes.core;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import com.winfo.gdmsaec.app.hermes.core.anonotation.ClassId;
import com.winfo.gdmsaec.app.hermes.core.model.Parameters;
import com.winfo.gdmsaec.app.hermes.core.model.Request;
import com.winfo.gdmsaec.app.hermes.core.model.Response;
import java.util.concurrent.ConcurrentHashMap;
public class Channel
private static final String TAG = "xiaolu";
private static volatile Channel instance;
private ConcurrentHashMap<Class<? extends HermesService>, Boolean> mBound = new ConcurrentHashMap<>();
private ConcurrentHashMap<Class<? extends HermesService>, HermesServiceConnection> mHermesServices = new ConcurrentHashMap<>();
private ConcurrentHashMap<Class<? extends HermesService>, IHermesService> mIHermes = new ConcurrentHashMap<>();
Gson gson = new Gson();
private Channel()
public static Channel getInstance()
if (null == instance)
synchronized (Channel.class)
if (null == instance)
instance = new Channel();
return instance;
public void bind(Context context, String pkgName, Class<? extends HermesService> service)
//已经绑定了,就不再绑定
Boolean isBound = mBound.get(service);
if (null != isBound && isBound)
return;
Intent intent;
if (TextUtils.isEmpty(pkgName))
intent = new Intent(context, service);
else
intent = new Intent();
intent.setClassName(pkgName, service.getName());
HermesServiceConnection hermesServiceConnection = new HermesServiceConnection(service);
mHermesServices.put(service, hermesServiceConnection);
context.bindService(intent, hermesServiceConnection, Context.BIND_AUTO_CREATE);
public void unBind(Context context, Class<? extends HermesService> service)
Boolean isBound = mBound.get(service);
if (null == isBound || !isBound)
return;
HermesServiceConnection hermesServiceConnection = mHermesServices.remove(service);
if (null != hermesServiceConnection)
context.unbindService(hermesServiceConnection);
public Response send(int type, Class<? extends HermesService> service, Class<?> instanceClass, String methodName, Object... parameters)
Boolean isBound = mBound.get(service);
if (null == isBound || !isBound)
return new Response(null, "服务未连接", false);
//获得classId
ClassId annotation = instanceClass.getAnnotation(ClassId.class);
String classId;
if (null != annotation)
classId = annotation.value();
else
classId = instanceClass.getName();
Parameters[] parametersList = makeParameters(parameters);
Request request = new Request(type, classId, methodName, parametersList);
IHermesService iHermesService = mIHermes.get(service);
try
if (iHermesService != null)
return iHermesService.send(request);
else
throw new RuntimeException();
catch (RemoteException e)
e.printStackTrace();
throw new RuntimeException();
private Parameters[] makeParameters(Object[] parameters)
Parameters[] p;
if (null != parameters)
p = new Parameters[parameters.length];
for (int i = 0; i < parameters.length; i++)
Object object = parameters[i];
p[i] = new Parameters(object.getClass().getName(), gson.toJson(object));
else
p = new Parameters[0];
return p;
class HermesServiceConnection implements ServiceConnection
private final Class<? extends HermesService> mService;
HermesServiceConnection(Class<? extends HermesService> service)
this.mService = service;
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder)
Log.d(TAG, "onServiceConnected: ");
IHermesService iHermesService = IHermesService.Stub.asInterface(iBinder);
mIHermes.put(mService, iHermesService);
mBound.put(mService, true);
@Override
public void onServiceDisconnected(ComponentName componentName)
Log.i(TAG, "onServiceDisconnected: ");
mIHermes.remove(mService);
mBound.put(mService, false);
Channel绑定的服务类HermesService:
package com.winfo.gdmsaec.app.hermes.core;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.gson.Gson;
import com.winfo.gdmsaec.app.hermes.core.model.Parameters;
import com.winfo.gdmsaec.app.hermes.core.model.Request;
import com.winfo.gdmsaec.app.hermes.core.model.Response;
import java.lang.reflect.Method;
public abstract class HermesService extends Service
private static final String TAG = "xiaolu";
private TypeCenter typeCenter = TypeCenter.getInstance();
private Gson gson = new Gson();
@Nullable
@Override
public IBinder onBind(Intent intent)
return new IHermesService.Stub()
@Override
public Response send(Request request) throws RemoteException
switch (request.getType())
case Request.GET_INSTANCE:
//单例
//参数
Object[] objects = restoreParameters(request.getParameters());
//调用的类型
Class<?> clazz = typeCenter.getClassType(request.getClassType());
//调用的方法
Method method = typeCenter.getMethod(clazz, request.getMethodName());
try
//调用
Object instance = method.invoke(null, objects);
//记住这个单例
typeCenter.putObject(request.getClassType(), instance);
return new Response(null, null, true);
catch (Exception e)
e.printStackTrace();
return new Response(null, e.getMessage(), false);
case Request.GET_METHOD:
Object[] objects = restoreParameters(request.getParameters());
Class<?> clazz = typeCenter.getClassType(request.getClassType());
Method method = typeCenter.getMethod(clazz, request.getMethodName());
Object object = typeCenter.getObject(request.getClassType());
try
Object returnObj = method.invoke(object, objects);
String source = gson.toJson(returnObj);
Response response = new Response(source, null, true);
Log.i(TAG, "source: " + source);
Log.i(TAG, "response: " + response.toString());
return response;
catch (Exception e)
return new Response(null, e.getMessage(), false);
return null;
;
protected Object[] restoreParameters(Parameters[] parameters)
Object[] objects;
if (null != parameters && parameters.length > 0)
objects = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++)
Parameters p = parameters[i];
objects[i] = gson.fromJson(p.getValue(), typeCenter.getClassType(p.getType()));
else
objects = new Object[0];
return objects;
public static class HermesService0 extends HermesService
public static class HermesService1 extends HermesService
public static class HermesService2 extends HermesService
HermesService调用的缓存类TypeCenter
package com.winfo.gdmsaec.app.hermes.core;
import android.text.TextUtils;
import com.winfo.gdmsaec.app.hermes.core.anonotation.ClassId;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
public class TypeCenter
private static TypeCenter typeCenter = null;
private ConcurrentHashMap<String, Class<?>> mClasses = new ConcurrentHashMap<>();
private ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Method>> mMethods = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> mInstance = new ConcurrentHashMap<>();
public static TypeCenter getInstance()
if (null == typeCenter)
synchronized (TypeCenter.class)
if (null == typeCenter)
typeCenter = new TypeCenter();
return typeCenter;
/**
* 记录对应class与其方法
*
* @param clazz
*/
public void regiest(Class<?> clazz)
regiestClass(clazz);
regiestMethod(clazz);
private void regiestMethod(Class<?> clazz)
mMethods.putIfAbsent(clazz, new ConcurrentHashMap<String, Method>());
ConcurrentHashMap<String, Method> methods = mMethods.get(clazz);
//应该将参数也加入key,因为可能重载
for (Method method : clazz.getMethods())
methods.put(method.getName(), method);
private void regiestClass(Class<?> clazz)
ClassId classId = clazz.getAnnotation(ClassId.class);
String className;
if (null != classId)
className = classId.value();
else
className = clazz.getName();
mClasses.putIfAbsent(className, clazz);
public Class<?> getClassType(String classType)
if (TextUtils.isEmpty(classType))
return null;
Class<?> clazz = mClasses.get(classType);
if (clazz == null)
try
clazz = Class.forName(classType);
catch (Exception e)
e.printStackTrace();
return clazz;
public Method getMethod(Class<?> clazz, String methodName)
ConcurrentHashMap<String, Method> stringMethodConcurrentHashMap = mMethods.get(clazz);
return stringMethodConcurrentHashMap.get(methodName);
public void putObject(String classType, Object instance)
mInstance.put(classType, instance);
public Object getObject(String classType)
return mInstance.get(classType);
Hermes类根据Channel执行动态代理的InvocationHandler处理器
package com.winfo.gdmsaec.app.hermes.core;
import android.util.Log;
import com.google.gson.Gson;
import com.winfo.gdmsaec.app.hermes.core.model.Request;
import com.winfo.gdmsaec.app.hermes.core.model.Response;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
class HermesInvocationHandler implements InvocationHandler
private static final String TAG = "xiaolu";
private Class<?> mInstanceClass;
private Class<? extends HermesService> mService;
private Gson gson = new Gson();
public <T> HermesInvocationHandler(Class<?> instanceClass, Class<? extends HermesService> service)
mInstanceClass = instanceClass;
mService = service;
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable
Log.d(TAG, "invoke: " + method.getName());
//再去请求服务端执行真正的方法
Response response = Channel.getInstance().send(Request.GET_METHOD, mService, mInstanceClass, method.getName(), objects);
if (response.isSuccess())
Class<?> returnType = method.getReturnType();
if (returnType != Void.class && returnType != void.class)
return gson.fromJson(response.getSource(), returnType);
return null;
该过程调用的model实体
request实体:
package com.winfo.gdmsaec.app.hermes.core.model;
import android.os.Parcel;
import android.os.Parcelable;
public class Request implements Parcelable
//获得单例对象
public static final int GET_INSTANCE = 0;
//执行方法
public static final int GET_METHOD = 1;
//请求类型
private int type;
//请求那个类(类的id)
private String classType;
//请求的方法名
private String methodName;
//执行方法的参数
private Parameters[] parameters;
public Request(int type, String classType, String methodName, Parameters[] parameters)
this.type = type;
this.classType = classType;
this.methodName = methodName;
this.parameters = parameters;
protected Request(Parcel in)
type = in.readInt();
classType = in.readString();
methodName = in.readString();
parameters = in.createTypedArray(Parameters.CREATOR);
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeInt(type);
dest.writeString(classType);
dest.writeString(methodName);
dest.writeTypedArray(parameters, flags);
@Override
public int describeContents()
return 0;
public static final Creator<Request> CREATOR = new Creator<Request>()
@Override
public Request createFromParcel(Parcel in)
return new Request(in);
@Override
public Request[] newArray(int size)
return new Request[size];
;
public int getType()
return type;
public void setType(int type)
this.type = type;
public String getClassType()
return classType;
public void setClassType(String classType)
this.classType = classType;
public String getMethodName()
return methodName;
public void setMethodName(String methodName)
this.methodName = methodName;
public Parameters[] getParameters()
return parameters;
public void setParameters(Parameters[] parameters)
this.parameters = parameters;
response实体:
package com.winfo.gdmsaec.app.hermes.core.model;
import android.os.Parcel;
import android.os.Parcelable;
public class Response implements Parcelable
//执行远程方法的返回结果
private String source;
//描述信息
private String message;
//是否成功执行远程方法
private boolean isSuccess;
public boolean isSuccess()
return isSuccess;
public void setSuccess(boolean success)
isSuccess = success;
public String getSource()
return source;
public void setSource(String source)
this.source = source;
public String getMessage()
return message;
public void setMessage(String message)
this.message = message;
public Response(String source, String message, boolean isSuccess)
this.source = source;
this.message = message;
this.isSuccess = isSuccess;
protected Response(Parcel in)
source = in.readString();
message = in.readString();
isSuccess = in.readByte() != 0;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(source);
dest.writeString(message);
dest.writeByte((byte) (isSuccess ? 1 : 0));
@Override
public int describeContents()
return 0;
public static final Creator<Response> CREATOR = new Creator<Response>()
@Override
public Response createFromParcel(Parcel in)
return new Response(in);
@Override
public Response[] newArray(int size)
return new Response[size];
;
@Override
public String toString()
return "Response" +
"source='" + source + '\\'' +
", message='" + message + '\\'' +
", isSuccess=" + isSuccess +
'';
Parameters实体:
package com.winfo.gdmsaec.app.hermes.core.model;
import android.os.Parcel;
import android.os.Parcelable;
public class Parameters implements Parcelable
//参数类型class
private String type;
//参数值 json 序列化后的字符串
private String value;
public Parameters(String type, String value)
this.type = type;
this.value = value;
protected Parameters(Parcel in)
type = in.readString();
value = in.readString();
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(type);
dest.writeString(value);
@Override
public int describeContents()
return 0;
public static final Creator<Parameters> CREATOR = new Creator<Parameters>()
@Override
public Parameters createFromParcel(Parcel in)
return new Parameters(in);
@Override
public Parameters[] newArray(int size)
return new Parameters[size];
;
public String getType()
return type;
public void setType(String type)
this.type = type;
public String getValue()
return value;
public void setValue(String value)
this.value = value;
自定义注解ClassId
package com.winfo.gdmsaec.app.hermes.core.anonotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ClassId
String value();
该过程调用的aidl
Request.aidl:
// Request.aidl
package com.winfo.gdmsaec.app.hermes.core.model;
parcelable Request;
Response.aidl:
// Request.aidl
package com.winfo.gdmsaec.app.hermes.core.model;
parcelable Response;
IHermesService.aidl:
// IHermesService.aidl
package com.winfo.gdmsaec.app.hermes.core;
import com.winfo.gdmsaec.app.hermes.core.model.Request;
import com.winfo.gdmsaec.app.hermes.core.model.Response;
interface IHermesService
Response send(in Request request);
AndroidManifest配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="lwl.tianyao.hermes">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MMActivity"
android:process=":mm" />
<service
android:name=".manager.MainService"
android:exported="true" />
<activity
android:name=".TestActivity"
android:process=":test" />
<service
android:name="com.winfo.gdmsaec.app.hermes.core.HermesService$HermesService0"
android:exported="true" />
</application>
</manifest>
原文下载地址:https://github.com/tianyao106/Hermes
以上是关于hermes进程间通信的主要内容,如果未能解决你的问题,请参考以下文章
饿了么开源项目Hermes:新颖巧妙易用的Android进程间通信IPC框架
饿了么开源项目Hermes:新颖巧妙易用的Android进程间通信IPC框架