美文网首页
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