美文网首页
Android Framework 04---手写进程通信框架

Android Framework 04---手写进程通信框架

作者: 沪漂意哥哥 | 来源:发表于2022-03-29 20:30 被阅读0次

一. bean

RequestBean

public class RequestBean {
    private String className;
    private String methodName;
    private int type;
    private RequestParamter[] requestParamters;
    public RequestBean() {
    }

    public RequestBean(int type, String className, String methodName, RequestParamter[] requestParamters) {
        this.type = type;
        this.className = className;
        this.methodName = methodName;
        this.requestParamters = requestParamters;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public RequestParamter[] getRequestParamters() {
        return requestParamters;
    }

    public void setRequestParamters(RequestParamter[] requestParamters) {
        this.requestParamters = requestParamters;
    }
} 

RequestParamter

 public class RequestParamter {
    private String parameterClassName;
    private String parameterValue;

    public RequestParamter() {
    }

    public RequestParamter(String parameterClassName, String parameterValue) {
        this.parameterClassName = parameterClassName;
        this.parameterValue = parameterValue;
    }

    public String getParameterClassName() {
        return parameterClassName;
    }

    public void setParameterClassName(String parameterClassName) {
        this.parameterClassName = parameterClassName;
    }

    public String getParameterValue() {
        return parameterValue;
    }

    public void setParameterValue(String parameterValue) {
        this.parameterValue = parameterValue;
    }

}

二. CacheCenter

 public class CacheCenter {
    private ConcurrentHashMap<String, Class<?>> mClassMap;
    private ConcurrentHashMap<String, ConcurrentHashMap<String, Method>> mAllMethodMap;
    private ConcurrentHashMap<String, Object> mInstanceObjectMap;

    private static final CacheCenter ourInstance = new CacheCenter();
    public static CacheCenter getInstance() {
        return ourInstance;
    }

    public void putObject(String className, Object instance) {
        mInstanceObjectMap.put(className, instance);
    }

    public Object getObject(String className) {
        return mInstanceObjectMap.get(className);
    }

    private CacheCenter() {
        mClassMap = new ConcurrentHashMap<String, Class<?>>();
        mAllMethodMap = new ConcurrentHashMap<String, ConcurrentHashMap<String, Method>>();
        mInstanceObjectMap = new ConcurrentHashMap<String, Object>();
    }

    public void register(Class clazz) {
        registerClass(clazz);
        registerMethod(clazz);
    }

    private void registerClass(Class clazz) {
        String className = clazz.getName();
        mClassMap.put(className, clazz);
    }

    public Method getMethod(RequestBean requestBean) {
        ConcurrentHashMap<String, Method> map = mAllMethodMap.get(requestBean.getClassName());
        if (map != null) {
            String key = getMethodParameters(requestBean);
            return map.get(key);
        }
        return null;
    }

    public Class<?> getClassType(String parameterClassName) {
        try {
            Class clazz = Class.forName(parameterClassName);
            return clazz;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void registerMethod(Class clazz) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            ConcurrentHashMap<String, Method> map = mAllMethodMap.get(clazz.getName());
            if (map == null) {
                map = new ConcurrentHashMap<String, Method>();
                mAllMethodMap.put(clazz.getName(),map);
            }
            String key = getMethodParameters(method);
            map.put(key, method);
        }
    }

    public static String getMethodParameters(Method method) {
        StringBuilder result = new StringBuilder();
        result.append(method.getName());
        Class<?>[] classes=method.getParameterTypes();
        int length = classes.length;
        if (length == 0) {
            return result.toString();
        }
        for (int i = 0; i < length; ++i) {
            result.append("-").append(classes[i].getName());
        }
        return result.toString();
    }

    public static String getMethodParameters(RequestBean requestBean) {
        StringBuilder result = new StringBuilder();
        result.append(requestBean.getMethodName());
        if (requestBean.getRequestParamters() == null || requestBean.getRequestParamters().length == 0) {
            return result.toString();
        }
        int length = requestBean.getRequestParamters().length;
        RequestParamter[] requestParamters=requestBean.getRequestParamters();
        for (int i = 0; i < length; ++i) {
            result.append("-").append(requestParamters[i].getParameterClassName());
        }
        return result.toString();
    } 

}

三. core

BinderIPC

 public class BinderIPC {
    private CacheCenter cacheCenter = CacheCenter.getInstance();
    private static final BinderIPC ourInstance = new BinderIPC();
    BinderInterface binderInterface;
    private static final Gson GSON = new Gson();
    private Context sContext;

    public static BinderIPC getDefault() {
        return ourInstance;
    }

    public void init(Context context) {
        sContext = context.getApplicationContext();
    }

    public void register(Class<?> clazz) {
        cacheCenter.register(clazz);
    }

    public <T> T getInstance(Class<T> clazz, Object... parameters) {
        sendRequest(clazz, null, parameters, ServiceManager.TYPE_GET);
        return getProxy(clazz);
    }

    private <T> T getProxy(Class<T> clazz) {
        ClassLoader classLoader = sContext.getClassLoader();
        return (T) Proxy.newProxyInstance(classLoader, new Class[]{clazz}, new BinderProxy(clazz));
    }

    public <T> String sendRequest(Class<T> clazz, Method method, Object[] parameters, int type) {
        String className = clazz.getAnnotation(ClassId.class).value();
        String methodName = method == null ? "getInstance" : method.getName();
        RequestParamter[] requestParamters = null;
        if (parameters != null && parameters.length >0) {
            requestParamters = new RequestParamter[parameters.length];
            for (int i = 0; i < parameters.length; i++) {
                Object parameter = parameters[i];
                String parameterClassName = parameter.getClass().getName();
                String parameterValue = GSON.toJson(parameter);
                RequestParamter requestParamter = new RequestParamter(parameterClassName, parameterValue);
                requestParamters[i] = requestParamter;
            }
        }

        RequestBean requestBean = new RequestBean(type, className, methodName, requestParamters);
        String request = GSON.toJson(requestBean);
        String responce = null;
        try {
            responce= binderInterface.reuqest(request);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return responce;
    }

    public void open(Context context) {
        open(context, null);
    }

    public void open(Context context, String packageName) {
        init(context);
        bind(context.getApplicationContext(), packageName, ServiceManager.class);
    }

    private void bind(Context context, String packageName, Class<? extends ServiceManager> service) {
        Intent intent = null;
        if (TextUtils.isEmpty(packageName)) {
            intent = new Intent(context, service);
        }else {
            ComponentName component = new ComponentName(packageName, service.getName());
            intent = new Intent();
            intent.setComponent(component);
            intent.setAction(service.getName());
        }
        ServiceConnection serviceConnection = new IPCServiceConnection();
        context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private class IPCServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binderInterface = BinderInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}

BinderProxy

 public class BinderProxy implements InvocationHandler {
    private Class clazz;
    private static final Gson GSON = new Gson();
    public BinderProxy( Class clazz) {
        this.clazz = clazz;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String data = BinderIPC.getDefault().sendRequest(clazz, method,
                args, ServiceManager.TYPE_INVOKE);
        if (!TextUtils.isEmpty(data)) {
            Object object= GSON.fromJson(data, method.getReturnType());
            return object;
        }
        return null;
    }
}

四. 自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassId {
    String value();
}

一. 自定义Service

  public class ServiceManager extends Service {
    private Gson gson = new Gson();
    //服务获取
    public static final int TYPE_GET = 1;
    //服务调用
    public static final int TYPE_INVOKE = 2;
    private CacheCenter cacheCenter = CacheCenter.getInstance();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new BinderInterface.Stub() {
            @Override
            public String reuqest(String reuqest) throws RemoteException {
                RequestBean requestBean = gson.fromJson(reuqest, RequestBean.class);
                int type = requestBean.getType();
                switch (type) {
                    case TYPE_GET:
                        Method method = cacheCenter.getMethod(requestBean);
                        Object[] parameters = makeParameterObject(requestBean);
                        if (method != null) {
                            try {
                                Object object= method.invoke(null, parameters);
                                if (object != null) {
                                    cacheCenter.putObject(requestBean.getClassName(), object);
                                }
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                        break;
                    case TYPE_INVOKE:
                        Object object = cacheCenter.getObject(requestBean.getClassName());
                        Method tempMethod = cacheCenter.getMethod(requestBean);
                        Object[] mParameters = makeParameterObject(requestBean);
                        try {
                            Object result=tempMethod.invoke(object, mParameters);
                            String data = gson.toJson(result);
                            return data;
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                        break;
                }
                return null;
            }
        };
    }

    private Object[] makeParameterObject(RequestBean requestBean) {
        Object[] mParameters = null;
        RequestParamter[] requestParamters = requestBean.getRequestParamters();
        if (requestParamters != null && requestParamters.length > 0) {
            mParameters = new Object[requestBean.getRequestParamters().length];
            for (int i = 0; i < requestParamters.length; i++) {
                RequestParamter requestParamter = requestParamters[i];
                Class<?> clazz = cacheCenter.getClassType(requestParamter.getParameterClassName());
                mParameters[i] = gson.fromJson(requestParamter.getParameterValue(), clazz);
            }
        }else {
            mParameters = new Object[0];
        }
        return mParameters;
    }
}

五. aidl文件

 interface BinderInterface {
    String reuqest(String reuqest);
}

六. 自定义主进程数据

public class UserInfo {
    private String password;
    private String name;
    public UserInfo( ) {
    }

    public UserInfo(String password, String name) {
        this.password = password;
        this.name = name;
    }
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "password='" + password + '\'' +
                ", name='" + name + '\'' +
                '}';
    }

    public void setName(String name) {
        this.name = name;
    }
}  
 @ClassId("com.luisliuyi.demo.binder.Singlton")
public interface ISinglton {
    public UserInfo getUserInfo();
} 
 public class Singlton implements ISinglton{
    private static Singlton sInstance = null;
    private UserInfo userInfo;
    private Singlton() {
    }

    public UserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }

    public static synchronized Singlton getInstance() {
        if (sInstance == null) {
            sInstance = new Singlton();
        }
        return sInstance;
    }
}

 public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BinderIPC.getDefault().open(this);

        //服务注册
         BinderIPC.getDefault().register(Singlton.class);
        Singlton.getInstance().setUserInfo(new UserInfo("123456","luis"));
    }

    public void change(View view) {
        startActivity(new Intent(this, SecondActivity.class));
    }
}

六. 自定义其他进程

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.luisliuyi.demo.binder">

    <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=".SecondActivity" android:process=":f"/>

        <service android:name="com.luisliuyi.demo.binderlib.ServiceManager" android:exported="true">
            <intent-filter>
                <action android:name="com.example.ipclib.DavidServiceManager"></action>
            </intent-filter>
        </service>
    </application>

</manifest>
 public class SecondActivity extends Activity {
    ISinglton service = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        BinderIPC.getDefault().open(this);

    }

    public void getService(View view) {
//        拿到接口   一定要   服务顾客
        service = BinderIPC.getDefault().getInstance(ISinglton.class);
    }

    public void getUser(View view) { 
        Toast.makeText(this, service.getUserInfo().getName() + " : " + service.getUserInfo().getPassword(), Toast.LENGTH_SHORT).show();
    }
}

七. 代码地址

 https://gitee.com/luisliuyi/android-binder.git

相关文章

网友评论

      本文标题:Android Framework 04---手写进程通信框架

      本文链接:https://www.haomeiwen.com/subject/mcjbjrtx.html