使用插件方式接入环信

有时候我们需要在应用中接入即时通讯等功能,可是又苦于apk过大、65535方法数等相关问题,这时候最好的方式就是用插件化的方式接入,下面是我用一个插件化框架接入环信的过程,跟大家分享一下。

这里我使用的是Apkplug这个插件化框架,这是一款我目前通过对比找到的最适合的插件化工具,在使用方便、运行稳定等方面均有良好表现,还提供后台托管,这一点也是极大的方便了开发者。
这里是这个框架的官方文档可以参考

环信插件开发

一、插件开发

首先我们对这个插件的需求是:能在一个有用户系统的宿主app里提供聊天功能。

进一步细分为如下具体功能:

1 能跟宿主一起登陆

2 能跟宿主用户系统有统一映射

3 能提供聊天界面

4 能提供好友界面

5 能提供最近会话界面

具体实现:

1 首先要按照环信的文档,先进行初始化和相关配置

public class MyApplication extends Application {
@Override
public void onCreate() {
    super.onCreate();

    EMOptions options = new EMOptions();

    EaseUI.getInstance().init(this, options);

    //xugai
    EMClient.getInstance().setDebugMode(false);

}
}

插件在宿主中启动时会自动执行application中的初始化代码。配置就不在这里贴了,可以参考环信文档或下面的demo代码。

2 跟宿主一起登陆,是为了能够跟宿主融合的更加融洽,如果点击按钮弹出一个登陆界面,则像是两个app之间的互相调用。所以在宿主登陆的时候,同时要登陆插件,并对用户透明。因此插件需要提供一个登陆接口。我用Dispatcher的方式声明接口:

继承一个com.apkplug.easemobplug.Processores类,实现Receive方法,在方法中调用环信登陆,宿主使用这个接口时可以把用户名、密码传过来。参数的传递是靠人为约定的,宿主开发者和插件开发者按照约定取值。DispatchAgent类是管插件和宿主理通信的类,在登陆完成后,我调用dispatchAgent.reply回调宿主,同样,给宿主发送结果的参数格式也是要人为约定好。

public class EaseLogin extends Processor {
BundleContext context;
DispatchAgent dispatchAgent;

public EaseLogin(BundleContext context) {
    super(context);
    this.context = context;
    dispatchAgent = new DispatchAgent(context);
}
@Override
public void Receive(URI uri, HashMap<String, Object> hashMap) {

    String userName = (String) hashMap.get("UserName");
    String passWord = (String) hashMap.get("Password");

    if(userName == null || passWord == null){
        dispatchAgent.reply(getMsgId(),false,new Exception("your username or password is null"));
        return;
    }
    EMClient.getInstance().login(userName, passWord, new EMCallBack() {
        @Override
        public void onSuccess() {
            dispatchAgent.reply(getMsgId(),true,"success");
        }

        @Override
        public void onError(int i, String s) {
            dispatchAgent.reply(getMsgId(),false,s);
        }

        @Override
        public void onProgress(int i, String s) {

        }
    });
}
}

这样一个登陆接口就做好了。

3 跟宿主应用统一用户系统,环信插件里的用户和聊天的好友一定是宿主应用用户系统中的用户及好友,所以哪些人是用户,那些人跟哪些人是好友,需要宿主告诉环信插件。

首先需要提供注册接口,宿主用户注册时,同步注册环信插件,映射关系随便定义:

public class EaseCreateAccount extends BaseProcessor {
    public EaseCreateAccount(BundleContext context) {
        super(context);
    }

    @Override
    public void Receive(URI uri, HashMap<String, Object> hashMap) {
        String userName = (String) hashMap.get("UserName");
        String password = (String) hashMap.get("Password");
        if(userName == null || password == null){
            dispatchAgent.reply(getMsgId(),false,new Exception("username or password is null"));
            return;
        }
        try {
            EMClient.getInstance().createAccount(userName,password);
            dispatchAgent.reply(getMsgId(),true,"success");
        } catch (HyphenateException e) {
            dispatchAgent.reply(getMsgId(),false,e);
        }
    }
}

好友的同步有两种实现方式:

1 直接由宿主调用插件接口,设置插件的好友列表

2 宿主只管好友添加,插件自己去服务器拿好友列表

貌似方法2要好很多,但是需要服务端的对接,只有服务端可以直接添加好友,客户端添加好友的接口,最多只能等对方登陆时候才添加成功。

demo里这两种我都实现了,跟上面登陆接口一样,我实现了一个直接给好友列表界面添加好友的接口,只供参考,我并没有调用。我用的第二种方式,当宿主的用户系统添加好友时,同时给环信添加好友,因此我对外提供了添加好友的接口。

public class EaseAddFriend extends BaseProcessor {
    public EaseAddFriend(BundleContext context) {
        super(context);
    }

    @Override
    public void Receive(URI uri, HashMap<String, Object> hashMap) {
        String username = (String) hashMap.get("UserName");
        try {
            EMClient.getInstance().contactManager().addContact(username, "you have to accept");
            dispatchAgent.reply(getMsgId(),true,"success");
        } catch (HyphenateException e) {
            dispatchAgent.reply(getMsgId(),false,e);
        }
    }
}

一系列你希望宿主用到的接口实现好后,就可以对外注册了,plugin.xml中添加:

<processor
    uri="http://apkplug.plug.com/meseplug/login"
    className="com.apkplug.easemobplug.Processores.EaseLogin"
/>

<processor
    uri="http://apkplug.plug.com/meseplug/init"
    className="com.apkplug.easemobplug.Processores.EaseInit"
/>

<processor
    uri="http://apkplug.plug.com/meseplug/regist"
    className="com.apkplug.easemobplug.Processores.EaseCreateAccount"
/>

<processor
    uri="http://apkplug.plug.com/meseplug/contect"
    className="com.apkplug.easemobplug.Processores.EaseContectsProcessor"
/>

<processor
    uri="http://apkplug.plug.com/meseplug/addfriend"
    className="com.apkplug.easemobplug.Processores.EaseAddFriend"
/>

<processor
    uri="http://apkplug.plug.com/meseplug/deletefriend"
    className="com.apkplug.easemobplug.Processores.EaseDeleteFriend"
/>

4 提供聊天界面、好友界面、会话界面,环信提供一些直接可用的界面,稍加改动就可以使用,宿主使用时,只需要用Intent启动即可,需要注意的是,一些manifest文件activity标签中配置的值,并不能同步到宿主,如果需要那些值,只能在宿主配置插件的activity,比如主界面,android:windowSoftInputMode="adjustPan"
这个值不配置的话,输入法弹出会压缩界面控件,只在插件里配置是不起作用的。

<activity android:name=".ui.MainActivity"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:windowSoftInputMode="adjustPan"
/>

提供了这些功能后,插件就开发完成了。

二、宿主开发

1 安装插件,为了方便,我这里直接用了本地安装

PlugManager.getInstance().installAssets("app-debug.apk", "1.0.0", new OnInstallListener() {
                        @Override
                        public void onDownloadProgress(String url, String filePath, long bytesWritten, long totalBytes, PlugInfo plugInfo) {

                        }

                        @Override
                        public void onInstallSuccess(final org.osgi.framework.Bundle bundle, PlugInfo plugInfo) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    textView.setText(textView.getText()+"\n插件安装成功");
                                }
                            });
                            startChat();
                        }

                        @Override
                        public void onInstallFailuer(int i, PlugInfo plugInfo, String errorMsg) {

                        }

                        @Override
                        public void onDownloadFailure(String errorMsg) {

                        }
                    });
                }

2 登陆插件,我已经注册过了用户,这里不再调用,调用方式相同。用DispatchAgent对象调用call方法,

final DispatchAgent dispatchAgent=new DispatchAgent(PlugManager.getInstance().getBundleContext());

    HashMap<String,Object> params2 = new HashMap<String, Object>();
    params2.put("UserName","apkplug");
    params2.put("Password","lbh131206");
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            textView.setText(textView.getText()+"\n开始登陆环信");
        }
    });
    dispatchAgent.call("http://apkplug.plug.com/meseplug/login", params2, new WorkerCallback() {
        @Override
        public void reply(URI uri, Object... objects) throws Exception {

            if(!(Boolean) objects[0]){
                return;
            }
            textView.setText(textView.getText()+"\n环信登陆成功");
            chatInitandLogin(dispatchAgent);

        }

        @Override
        public void timeout(URI uri) throws Exception {

        }

        @Override
        public void Exception(URI uri, Throwable throwable) {
            System.err.println(uri);
        }
    });

登陆后就随时可以进行界面跳转了

Intent intent = new Intent();
    intent.setClassName(MainActivity.this, className);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent)

demo地址:

宿主:
https://github.com/apkplug/SDKDemo/tree/master/EasePlugUser

插件:
https://github.com/apkplug/SDKDemo/tree/master/EasemobPlug

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,815评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 这种方式也是可以的,直接在ARP( )内进行pdst的赋值 注意,scapy发包有一个弊端,就是,如果目标地址暂时...
    FKTX阅读 275评论 0 1
  • 狐狸说我舔呀舔呀 我家老爷就硬了 我问后来呢 狐狸说我家老爷把我掰开 翻云覆雨地掰开 我再问他看到了什么 狐狸说我...
    楊孜阅读 445评论 0 2
  • 由于这几天没有多少闲暇时间用来看书,今天才将《暗时间》完结。《暗时间》最后几节内容是介绍数学方面的方法论,出神入化...
    王侦阅读 764评论 0 0