ContentProvider call实现跨进程通信

github.com/wengeoo/PEvent.git

1、ContentProvider query

 作为 Android 四大基础组件之一的 ContentProvider 本来它的作用只是提供内容性质的跨进程访问。APP-A通过APP-B的ContentProvider相关实现,可以获取B的向外暴露的SQL或者SP数据,但是A如何通知B去更新ContentProvider的相关内容?

 传统方式有1:广播;2:AIDL,弊端是使用流程相对繁琐   

2、ContentProvider call

在 API 11 (Android 3.0) 中,ContentProvider 加入了一个新的方法,可以用来进行跨进程的方法调用,ContentProvider 中这个方法的定义如下:

Bundle call(String method, String arg, Bundle extras)

看看具体实现

A中实现

 private void update(String status) {
        getContext().getContentResolver().call(ACCOUNT_URI, "STATUS", status, new Bundle());
    }

B中实现

    @Override
    public Bundle call(String method, String arg, Bundle extras) {
      if ("STATUS".equals(method)) {
            //dosomething
        }
        return null;
    }

A中就能触发B的具体逻辑操作,类似复写,B也可以触发A的操作

3、继续扩展

我们实现一个基础库,通过ContentProvider+反射实现A调用B接口,B调用A接口,简化使用流程

3.1、实现一个基础IContentProvider,A/B中都继承

@Nullable
    @Override
    public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle in) {
        if (in == null) {
            return null;
        }
        long start = SystemClock.elapsedRealtime();
        Bundle response = new Bundle();
        in.setClassLoader(Par.class.getClassLoader());
        Parcelable returnResponse = in.getParcelable(PEVENT_KEY_RESPONSE);
        response.putParcelable(PEVENT_KEY_RESPONSE, returnResponse);
        try {
            String calling = getCallingPackage();
            long callingTime = SystemClock.elapsedRealtime();
            PEventLog.e(TAG, "used time calling:" + (callingTime - start));
            if (!TextUtils.isEmpty(calling)) {
                in.putString(PEVENT_KEY_CALLING_PACKAGE, calling);
            }
            String route = in.getString(PEVENT_KEY_ROUTE);
            int flags = in.getInt(PEVENT_KEY_FLAGS);
            if (TextUtils.isEmpty(route)) {
                throw new NotFoundRouteException(route + " was not found");
            }
            ArrayDeque<MethodInvoker> callers = PServiceManager.getInstance().lookupMethods(route);
            if (callers == null || callers.isEmpty()) {
                throw new NotFoundRouteException(route + " was not found");
            }
            Iterator<MethodInvoker> iterators = callers.iterator();
            while (iterators.hasNext()) {
                MethodInvoker methodInvoker = iterators.next();
                methodInvoker.invoke(in, response);
            }
            response.putInt(PEVENT_KEY_RESPONSE_CODE, PEVENT_RESPONSE_RESULE_SUCCESS);
        } catch (NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
            response.putInt(PEVENT_KEY_RESPONSE_CODE, PEVENT_RESPONSE_RESULE_NO_SUCH_METHOD);
        } catch (NotFoundRouteException e) {
            response.putInt(PEVENT_KEY_RESPONSE_CODE, PEVENT_RESPONSE_RESULE_NOT_FOUND_ROUTE);
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            response.putInt(PEVENT_KEY_RESPONSE_CODE, PEVENT_RESPONSE_RESULE_ILLEGALACCESS);
        } catch (Throwable e) {
            e.printStackTrace();
            response.putInt(PEVENT_KEY_RESPONSE_CODE, PEVENT_RESPONSE_RESULE_REMOTE_EXCEPTION);
        }
        return response;
    }

A中

PEvent pEvent = PEvent.newBuilder(MainActivity.this).setAuthority("com.pevent.example").build();
Bundle bundle = pEvent.route("/show/age").withString("age", "20").post();
    Bundle post(@NonNull Bundle in) {
        ContentResolver contentResolver = mContext.getContentResolver();
        Bundle out = null;
        try {
            out = contentResolver.call(base, "", null, in);
            parseReponse(in, out);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return out;
    }

B中

    @MainThread
    @Route("/show/age")
    public void showAge(final Bundle in, Bundle out) {
        out.putString("age", "10");
        String name = in.getString("age");
        tv.setText(name);
    }

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中,进程通信(IPC,Interprocess Communication)是指不同进程之间的通信。Android 中主要有以下几种进程通信方式: 1. Intent:通过 Intent 可以在不同应用程序之间传递消息和数据。通过发送和接收 Intent,不同进程之间可以实现简单的通信。 2. AIDL:AIDL(Android Interface Definition Language)是一种用于定义 Android 进程间通信接口的语言。通过 AIDL,一个应用程序可以将一个接口暴露给其他应用程序使用,从而实现进程通信。 3. ContentProviderContentProviderAndroid 提供的一种用于共享数据的组件。通过 ContentProvider,一个应用程序可以将数据存储在 SQLite 数据库、文件系统或网络上,并且其他应用程序可以通过 ContentResolver API 访问这些数据。 4. Messenger:Messenger 是一种基于 AIDL 的 IPC 机制,它允许不同进程之间传递 Message 对象。通过 Messenger,一个进程可以向另一个进程发送消息,并且可以通过 Handler 处理接收到的消息。 5. Socket:Socket 是一种传输层协议,可以在不同主机之间进行通信。在 Android 中,一个应用程序可以通过 Socket 进行进程通信,例如使用 HTTP 协议进行网络通信。 需要注意的是,进程通信可能会带来额外的开销和安全问题,因此应该谨慎使用。在使用进程通信时,需要确保数据的安全性和正确性,并避免出现死锁、死循环等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值