Android基于Aidl的跨进程间双向通信管理中心

得益于最近有点时间和精力,我想起来了一件事。那就是在上家公司,公司要求做一个APP进程间的通信的功能,并不是APP对APP的直接跨进程通信,而是通过一个服务中心,做接收,然后,再转发,避免应用之间耦合性高,不然的话,新增一个APP,其他APP也要进行升级更新(类似于有服务中心的聊天室)。

我就花几个小时写点东西吧,顺便记录一下

大家都知道在Android设备上,有很多方式,比如,广播,socket,共享内存,aidl等,其中广播和aidl都是基于android中iBinder机制

广播:

广播有缺陷,就是效率不高,有时候会遇到广播丢失,或者说广播的队列过长,导致消息发送慢;

共享内存:

共享内存没有安全性可言,而且多线程读写数据的话,会无法控制

socket:

socket耦合度较高,内存需要拷贝两次,适用于跨网络

AIDL:

基于binder,效率高;基于C/S架构,分层清晰,功能明确;有Linux的进程ID概念,更加安全等优点

流程图

很简单的架构,所有的APP消息传递都通过Server来做,工程结构如下,center(消息中心),app1,app2都依赖于lib(aidl接口库)

利用aidl中的RemoteCallbackList类(原理和源码我就不多说了,其实Client调用Server是大同小异的,只不过是反者来了一次),来实现client中的接口回调,这样才能从server主动给client发消息,一般我们都是client主动调用Server,现在轮到Server主动调用client

服务端的代码如下,你可以按照你项目的要求来做

package com.helang.messagecenterdemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import com.helang.lib.IMyAidlCallBackInterface;
import com.helang.lib.IMyAidlInterface;

/**
 * 消息服务中心(记得在 manifest.xml 加上 android:exported="true")
 */
public class MyService extends Service {
  private final static String TAG = MyService.class.getSimpleName();
  private RemoteCallbackList<IMyAidlCallBackInterface> callbackList = new RemoteCallbackList<>();//回调的关键(API>=17,才能使用)

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

  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return iBinder;
  }

  /**
   * 实现iBinder
   */
  private IMyAidlInterface.Stub iBinder = new IMyAidlInterface.Stub() {
    @Override
    public void sendMessage(String tag, String message) throws RemoteException {
      callbackList.beginBroadcast();
      sendMessageToAllClient(tag,message);
      Log.d(TAG,"tag="+tag+" message="+message);
      callbackList.finishBroadcast();
    }

    @Override
    public void registerListener(IMyAidlCallBackInterface listener) throws RemoteException {
      callbackList.register(listener);//注册回调listener
      Log.d(TAG,"registerListener");
    }

    @Override
    public void unregisterListener(IMyAidlCallBackInterface listener) throws RemoteException {
      callbackList.unregister(listener);//取消回调listener
      Log.d(TAG,"unregisterListener");
    }
  };

  /**
   * 发送消息给全部的client(你也可以指定发送给某个client,也可
   * 以根据自己的业务来封装一下Bean,记得要实现Parcelable接口来序列化
   * @param tag
   * @param message
   */
  private void sendMessageToAllClient(String tag,String message){
    for (int i = 0 ; i < callbackList.getRegisteredCallbackCount();i++){
      try {
        callbackList.getBroadcastItem(i).callback(tag,message);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }
  }
}

Client1和Client2代码是一样的,就是相互发消息:

package com.helang.app2;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.helang.lib.IMyAidlCallBackInterface;
import com.helang.lib.IMyAidlInterface;

public class MainActivity extends AppCompatActivity {
  private EditText editText;
  private Button bt_send;
  private TextView text;

  private IMyAidlInterface iMyAidlInterface;
  private ServiceCallBack serviceCallBack;

  private MyServiceConnection myServiceConnection;

  private Handler handler = new Handler();

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    bt_send = findViewById(R.id.bt_send);
    editText = findViewById(R.id.editText);
    text = findViewById(R.id.text);

    bt_send.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        if (iMyAidlInterface != null){
          try {
            iMyAidlInterface.sendMessage("app2",editText.getText().toString().trim());
          } catch (RemoteException e) {
            e.printStackTrace();
          }
        }
      }
    });

    bindService();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService();
  }

  private void bindService(){
    myServiceConnection = new MyServiceConnection();
    serviceCallBack = new ServiceCallBack();
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.helang.messagecenterdemo",
        "com.helang.messagecenterdemo.MyService"));
    startService(intent);//开启远程服务
    bindService(intent,myServiceConnection,BIND_AUTO_CREATE);//绑定服务

  }

  private void unbindService(){
    if (myServiceConnection != null){
      try {
        iMyAidlInterface.unregisterListener(serviceCallBack);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
      unbindService(myServiceConnection);
    }
  }

  /**
   * 连接Service
   */
  class MyServiceConnection implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
      iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);

      handler.post(new Runnable() {
        @Override
        public void run() {
          //注册回调
          if (iMyAidlInterface != null){
            try {
              iMyAidlInterface.registerListener(serviceCallBack);
            } catch (RemoteException e) {
              e.printStackTrace();
            }
          }
        }
      });

    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }
  }

  /**
   * service回到client的类
   */
  class ServiceCallBack extends IMyAidlCallBackInterface.Stub{

    @Override
    public void callback(final String tag, final String message) throws RemoteException {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          text.append("tag="+tag+" message="+message);
        }
      });
    }
  }
}

看看效果吧,Client2(app2)发消息给Client1(app1)

顺便说一句,提前打开Center服务,因为android 8.0之后的版本直接远程开启其他App后台进程服务,是行不通了,可以绑定一个前台进程,网上方法有很多,我这里就简单处理了

源码我都放在github:MessageCenter

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android中socketpair双向通信详解

    Android很多地方会涉及到进程间的通信,比如输入系统,那么进程间通信会涉及哪些内容呢? 1.进程:负责读取和分发事件 2.应用程序:负责处理输入事件 上面这两个进程会涉及哪些双向通信呢: 1.进程会发送输入事件 2.应用程序会告知事件处理完或APP已关闭 这里大家可能会有疑惑,binder系统能否实现上面所说的双向通信呢? 答案是不行,binder分为server和client,每次都由client主动发出请求,server收到请求后进行答复,这样的缺点就是每次请求只能单方发起,server

  • 详解Android跨进程IPC通信AIDL机制原理

    简介 AIDL:Android Interface Definition Language,即Android接口定义语言,用于生成Android不同进程间进行进程通信(IPC)的代码,一般情况下一个进程是无法访问另一个进程的内存的.如果某些情况下仍然需要跨进程访问内存数据,这时候Android系统就要将其对象分解成能够识别的原数据,编写这一组操作的代码是一项繁琐的工作,但是AIDL对底层进行了抽象的封装,简化了跨进程操作. AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量

  • Android IPC进程间通信详解最新AndroidStudio的AIDL操作)

    前言 前面梳理了Android的线程间的通信<Thread.Handler和HandlerThread关系何在?> ,这些都是在同一个进程中,那进程间的通信,或者说不同的应用间的通信该如何实现呢?这个时候就要用到AIDL(Android Interface Definition LanguageAndroid接口定义语言 ). 使用方法(AndroidStudio) 我发现现在AIDL的教程基本上还是eclipse的,但是在AndroidStudio里面使用AIDL还是有一些不同的,来看看怎么

  • android使用AIDL跨进程通信(IPC)

    AIDL的作用 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码.如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数. AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级.它是使用代理类在客户端和实现端传

  • Android Socket 线程连接openwrt与arduino单片机串口双向通信的实例解析

    废话不多说了,直接给大家贴代码了,具体代码如下所示: package zcd.netanything; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import android.app.Fragment; import android.content.BroadcastReceiver; import and

  • Android基于Aidl的跨进程间双向通信管理中心

    得益于最近有点时间和精力,我想起来了一件事.那就是在上家公司,公司要求做一个APP进程间的通信的功能,并不是APP对APP的直接跨进程通信,而是通过一个服务中心,做接收,然后,再转发,避免应用之间耦合性高,不然的话,新增一个APP,其他APP也要进行升级更新(类似于有服务中心的聊天室). 我就花几个小时写点东西吧,顺便记录一下 大家都知道在Android设备上,有很多方式,比如,广播,socket,共享内存,aidl等,其中广播和aidl都是基于android中iBinder机制 广播: 广播有

  • Android通过RemoteViews实现跨进程更新UI示例

    一.概述 前面一篇文章Android通过AIDL实现跨进程更新UI我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新UI是可行的,但有以下弊端: View中的方法数比较多,在IPC中需要增加对应的方法比较繁琐. View的每一个方法都会涉及到IPC操作,多次IPC带来的开销问题不容小觑. View中方法的某些参数可能不支持IPC传输.例如:OnClickListener,它仅仅是个接口没有序列化. 接下来我们通过RemoteViews实现跨进程更新UI 二.实现效果图 在同一个应用中有

  • Android Messenger实现进程间双向通信

    简介 Messenger是安卓进程间通信 (IPC) 最为简单的方式,可以实现进程间双向通信.详见官网介绍 代码实现 服务端应用实现 MessengerService接收客户端发送的消息: package com.test.messengerservice; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import

  • Android 基于MediatorLiveData实现红点的统一管理

    目录 背景 需求分析 思路分析 树形模型 具体代码实现 MediatorLiveData RedPointManager 验证刷新逻辑 总结 背景 小红点在各个App内随处可见,并且随着需求的不断迭代,需要展示小红点的需求越来越多. 不同需求之间,红点显示可能有冲突. 不同页面之间,红点显示会有关联. 同一个红点,可能显示成数字样式,红点样式,文案样式. 这个时候,如果没有对红点的展示逻辑做一个统一的抽象和管理的话,就会感觉很复杂,后续也不太好维护. 本文会基于MediatorLiveData,

  • Android AIDL实现跨进程通信的示例代码

    AIDL是Android接口定义语言,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能. 实现步骤 例:用 A程序去访问 B程序的MyService.java服务 在B中建立AIDL文件MyAidlService.AIDL,在AIDL文件里写我们的接口方法 在MyService中写AIDL文件定义的方法的具体服务逻辑 在B的manifest文件中,为Service添加action "com.xyb.servicetest.

  • Android Studio创建AIDL文件并实现进程间通讯实例

    在Android系统中,跨进程通信是非常普遍的事情,它用到了Binder机制处理进程之间的交互.Binder机制会开放一些接口给Java层,供android开发工程师调用进程之间通信.这些接口android封装到了AIDL文件里,当我们项目用到跨进程通信时可以创建.aidl文件,.aidl文件可以协助我们达到跨进程的通信.下面简单介绍用AndroidStudio创建AIDL文件的过程. a.新建AIDL文件 1.项目文件夹右键---> new --->选择AIDL 2.自定义一个接口名称 3.

  • Android AIDL实现两个APP间的跨进程通信实例

    本文为大家分享了Android AIDL实现两个APP间的跨进程通信实例,供大家参考,具体内容如下 1 Service端创建 首先需要创建一个Android工程然后创建AIDL文件,创建AIDL文件主要为了生成继承了Binder的Stub类,以便应用Binder进行进程间通信 servier端结构如下 AIDL代码如下 // IBookManager.aidl package com.example.bookserver.aidl; // Declare any non-default type

  • Android应用程序四大组件之使用AIDL如何实现跨进程调用Service

    一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentProvider实现了不同应用之间的跨进程调用,但ContentProvider主要是提供数据的共享(如sqlite数据库),那么我们希望跨进程调用服务(Service)呢?Android系统采用了远程过程调用(RPC)方式来实现.与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言

随机推荐