社交化分享组件踩坑

issue:微信登录失败

问题是这样的,项目里的社交化分享是基于 UMShare 封装成的一个 ShareLib module,为了让这个 module 对调用者说更透明,我将 WXEntryActivity申明App module 移动到了 ShareLib module里, AndroidMainifest.xml 中关于 WXEntryActivity申明如下:

同时把 wxapi 目录(包含 WXEntryActivity.java 也一并转移,根目录下的 wxapi 目录如图:

App module 确实清爽了不少。但是,这么做会引发怎样的问题呢?

目前发现的问题

  • 用户点击微信登录总是失败,无法正常跳转到微信授权页面
  • 用户无法使用微信分享
  • 以上两种情况都会抛出 NameNotFoundException

冷静分析

友盟的文档

配置Android Mainifest XML,文档里明确指出是需要在 AndroidMainifest 里申明 WXEntryActivity, 并在根目录下新建一个 wxapi 包,然后将 WXEntryActivity 放在里面。但说如果把这些东西放到 module项目里会如何,友盟并没有说,emmmm…

遇事不觉 Debug

进入 UMShare SDK 的源码里探索了一番后,将错误锁定在了 checkWxBySelf 这个静态方法上,该方法声明如下:

public static String checkWxBySelf(Context context) {
  	// 获取包名
    String pkName = context.getPackageName();
  	// 获取类名
    String classPath = pkName + ".wxapi.WXEntryActivity";
    PackageInfo packageInfo = null;
    PackageManager packageManager = null;

    try {
      packageManager = context.getPackageManager();
      packageInfo = packageManager.getPackageInfo(pkName, 64);
    } catch (NameNotFoundException var8) {
      var8.printStackTrace();
    }

    String result = getSignatureDigest(packageInfo);

    try {
      // 1.通过全名加载 WXEntryActivity 类
      Class<?> clz = Class.forName(classPath);
      if(clz == null) {
        return "请检查微信后台注册签名:" + result.toLowerCase() + "\n" + "包名:" + pkName + "\n" + "没有配置微信回调activity或配置不正确";
      }

      if(Config.isUmengWx.booleanValue()) {
        if(clz.getSuperclass() == null) {
          return "WXEntryActivity配置不正确,您使用的是精简版,请使WXEntryActivity继承com.umeng.weixin.callback.WXCallbackActivity";
        }

        if(!clz.getSuperclass().toString().contains("com.umeng.weixin")) {
          return "WXEntryActivity配置不正确,您使用的是精简版,请使WXEntryActivity继承com.umeng.weixin.callback.WXCallbackActivity";
        }
      } else {
        if(clz.getSuperclass() == null) {
          return "WXEntryActivity配置不正确,您使用的是完整版,请使WXEntryActivity继承com.umeng.socialize.weixin.view.WXCallbackActivity";
        }

        if(!clz.getSuperclass().toString().contains("com.umeng.socialize")) {
          return "WXEntryActivity配置不正确,您使用的是完整版,请使WXEntryActivity继承com.umeng.socialize.weixin.view.WXCallbackActivity";
        }
      }
    } catch (ClassNotFoundException var9) {
      var9.printStackTrace();
      return "请检查微信后台注册签名:" + result.toLowerCase() + "\n" + "包名:" + pkName + "\n" + "没有配置微信回调activity或配置不正确";
    }

    try {
      ComponentName componentName = new ComponentName(context.getPackageName(), classPath);
      // 2.根据指定的组件,获取 ActivityInfo 信息
      packageManager.getActivityInfo(componentName, 0);
      return "请检查微信后台注册签名:" + result.toLowerCase() + "\n" + "包名:" + pkName + "\n" + "Activity微信配置正确";
    } catch (NameNotFoundException var7) {
      var7.printStackTrace();
      return "请检查微信后台注册签名:" + result.toLowerCase() + "\n" + "包名:" + pkName + "\n" + "没有配置微信回调activity没有在Manifest中配置";
    }
  }

注释里已经写了两个可能抛出异常的地方,和 packageName 都有关系,也就是说我们能否正确获取 packageName 直接影响到能否正常使用 UMShare SDK 的功能!很显然,我们的 App Module 里并没有对应的 WXEntryActivity,所以执行到注释1的时候就会抛出异常了!

补充

如果,我在 App module 里加上 wxapi 目录就 OK 了嘛?

答案是no!还是会报错,只不过这次是在注释2抛出异常。

又报错,这次明明加上了 wxapi 目录,已经可以找到 WXEntryActivity 了,为毛还是报错勒,emmm,再来冷静分析下吧。

多个 AndroidMainifest 的合并

关于多个 AndroidMainifest 的合并问题,可以去Android 官网补补课。

因为我们的项目有多个 module,每个 module 都有自己的 AndroidMainifest,而最终,这些文件会被合并为一个文件。

还是看看 Merged AndroidMainifest 吧

App module 下的 merge 后的 AndroidMainifest 模样

<activity
       android:name="info.hellovass.sharelib.wxapi.WXEntryActivity"
       android:configChanges="keyboardHidden|orientation|screenSize"
       android:exported="true"
       android:screenOrientation="portrait"
       android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

ShareLib module 下的 merge 后的 AndroidMainifest 模样:

<activity
       android:name="info.hellovass.sharelib.wxapi.WXEntryActivity"
       android:configChanges="keyboardHidden|orientation|screenSize"
       android:exported="true"
       android:screenOrientation="portrait"
       android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

分析

因为我们并没有在 App module 下的 AndroidMainifest 对 WXEntryActivity 做任何申明,所以,merge 时会合并 ShareLib module 里的申明,于是,就变成了上面这样子。看到这里,我想事情也明了了,因为这种情况,ShareLib module 的包名和 App module 的包名是不一致的。简单来说,WXEntryActivity 并未注册到 AndroidMainifest 中,所以会在 packageManager.getActivityInfo(component, 0) 出抛出异常。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏为数不多的Android技巧

Android插件化原理解析——广播的管理

在Activity生命周期管理 以及 插件加载机制 中我们详细讲述了插件化过程中对于Activity组件的处理方式,为了实现Activity的插件化我们付出了相...

1032
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第十天 Cookie&Session学习

当用户访问某些Web应用时,经常会显示出该用户上一次的访问时间。例如,QQ登录成功后,会显示用户上次的登录时间。通过本任务,读者将学会如何使用Cookie技术实...

1573
来自专栏Java3y

从零开始写项目第二篇【登陆注册、聊天、收藏夹模块】

登陆模块目标 我要将其弄成类似的登陆,功能是要比较完善的。 ? 本来我是想做一步写一步的,但是发现这样文章就会太乱,因为要改的地方太多了。前面写过的,后边就被修...

1.2K8
来自专栏Linux驱动

15.linux-LCD层次分析(详解)

如果我们的系统要用GUI(图形界面接口),这时LCD设备驱动程序就应该编写成frambuffer接口,而不是像之前那样只编写操作底层的LCD控制器接口。 什么是...

2656
来自专栏比原链

剥开比原看代码07:比原节点收到“请求区块数据”的信息后如何应答?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

872
来自专栏非典型程序猿

Golang任务队列machinery使用与源码剖析(二)

在Golang任务队列machinery使用与源码剖析(一)一文中,我们主要对golang中任务队列machinery的设计结构以及具体模块的功能与源码实现进行...

1.4K8
来自专栏坚毅的PHP

jersey处理支付宝异步回调通知的问题:java.lang.IllegalArgumentException: Error parsing media type 'application/x-www

tcpflow以流为单位分析请求内容,非常适合服务器端接口类服务查问题 这次遇到的问题跟支付宝支付后的回调post结果有关 淘宝的代码例子: publi...

6005
来自专栏向治洪

Android 使用android-support-multidex解决Dex超出方法数的限制问题

随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sdk或者公共支持的jar包,项目耦合性高,重复作用的类越来越多),相信很多人都遇到过如下的...

3498
来自专栏Android 研究

OKHttp源码解析(三)--中阶之线程池和消息队列

android的异步任务一般都是用Thread+Handler或者AsyncTask来实现,其中笔者当初经历过各种各样坑,特别是内存泄漏,当初笔者可是相当的欲死...

2363
来自专栏木木玲

Netty 那些事儿 ——— 心跳机制

7489

扫码关注云+社区

领取腾讯云代金券