微博开放SDK按官方文档配置后接入所需功能,但测试反馈偶然会出现报错提示“occur exception”,多次尝试后复现,抓取报错详细信息为“please init sdk before use it. Wb.install()”,报错来源为微博开放SDK内部方法,按翻译意思是没有初始化,但明明已经进行过初始化再调用的功能,问题出在哪呢?

此文章已收入Android偶遇杂症合集(持续更新)

1、遇到的问题

前段时间做了个集成微博开放SDK的需求,接入以后把功能跑通,结果测试阶段发现偶尔会出现报错无法正常唤起微博的情况。

多次排查后发现,第一次唤起微博时很容易出错,报错信息是“occur exception”,详细报错信息是“please init sdk before use it. Wb.install()”,按翻译意思是没有初始化。

检查了代码后发现,在唤起微博之前确实已经进行了初始化操作,但依然很容易遇到这个问题。

2、原因分析

急着改bug的小伙伴可以直接看(3、解决方式)

由于不是必现,并且只出现在首次调用,初步判断初始化逻辑应该是异步的,话不多说,看微博开放SDK的源码到底做了啥。

首先我们对SDK进行了初始化操作:

// 1. 调用AuthInfo构造方法,实例化一个authInfo
val authInfo = AuthInfo(activity, mAppId, mRedirectUrl, SCOPE)
// 2. 通过WBAPIFactory实例化一个wbApi
val wbApi = WBAPIFactory.createWBAPI(activity)
// 3. 用获得的authInfo和wbApi对象注册APP
wbApi.registerApp(activity, authInfo)

看上去第一步和第二步只是实例化对象,应该内部没有什么操作,看看源码确认一下。

第一步实例化AuthInfo,看看AuthInfo的构造函数:

public final class AuthInfo implements Parcelable, Serializable {// ...public AuthInfo(Context var1, String var2, String var3, String var4) {// 都是赋值操作,没有异步逻辑this.app_key = var2;this.redirect_url = var3;this.scope = var4;this.package_name = var1.getPackageName();this.hash = e.b(var1, this.package_name);}//...
}

第二步通过WBAPIFactory实例化一个wbApi,看看WBAPIFactory源码:

public class WBAPIFactory {public WBAPIFactory() {}public static IWBAPI createWBAPI(Context var0) {// 直接构造了一个对象return new a(var0);}
}

看看WBAPIFactory构造的a对象的构造方法:

public final class a implements IWBAPI {// ...public a(Context var1) {// 也都是赋值操作,没有异步逻辑this.mContext = var1;this.s = new com.sina.weibo.sdk.auth.a((Activity)this.mContext);this.t = new e((Activity)this.mContext);}// ...
}

粗略看来好像没啥特殊的,没有异步的逻辑在其中,那问题可能出在第三步registerApp上了,看看registerApp都做了啥:

public interface IWBAPI {// ...void registerApp(Context var1, AuthInfo var2);// ...
}

是通过接口调用的,看看实现类:

public final class a implements IWBAPI {// ...public final void registerApp(Context var1, AuthInfo var2) {com.sina.weibo.sdk.a.a(var1, var2);}// ...
}

不做停留,跟进去看看:

public final class a {// ...public static void a(Context var0, AuthInfo var1) {if (!a) {if (var1 == null) {throw new RuntimeException("authInfo must not be null.");}b = var1;String var4 = var1.getAppKey();WeiboSsoSdkConfig var2;(var2 = new WeiboSsoSdkConfig()).setContext(var0.getApplicationContext());var2.setAppKey(var4);var2.setFrom("1478195010");var2.setWm("1000_0001");WeiboSsoSdk.initConfig(var2);try {// 抓到你了!一个异步操作WeiboSsoSdk.getInstance().visitorLogin(new VisitorLoginListener() {public final void handler(VisitorLoginInfo var1) {try {if (var1 != null) {com.sina.weibo.sdk.a.mAid = var1.getAid();com.sina.weibo.sdk.a.c();}} catch (Exception var2) {var2.printStackTrace();}}});return;} catch (Exception var3) {var3.printStackTrace();}}}// ...
}

果然,在初始化逻辑的第三步registerApp中有一个异步操作,WeiboSsoSdk.getInstance().visitorLogin(),看上去是有一个SDK通过APPKey等参数进行登录的逻辑,应该是鉴权校验用的。

翻了一下官方文档,并没有提供一个初始化完成的监听回调,WeiboSsoSdk.getInstance().visitorLogin()完成后也进入了一堆混淆过后的代码逻辑中,没有暴露给外界的方法可以用来监听状态。

换个思路,我们看看报错是从哪里来的,进入断点跟着代码的执行看看唤起微博时都发生了什么,就从微博授权登录开始看吧。首先我们知道入口是IWBAPI.authorize(),进入实现类com.sina.weibo.sdk.openapi.aauthorize()方法打个断点:

public final class a implements IWBAPI {// ...public final void authorize(WbAuthListener var1) {WbAuthListener var2 = var1;com.sina.weibo.sdk.auth.a var3 = this.s;c.a("WBSsoTag", "authorize()");if (var2 == null) {throw new RuntimeException("listener can not be null.");} else {var3.e = var2;Context var4;if (com.sina.weibo.sdk.a.a(var4 = (Context)var3.d.get()) && com.sina.weibo.sdk.b.a.e(var4) != null) {// 就是这一行执行完就报错了,跟进去看看var3.d();} else {var3.e();}}}// ...
}

var3.d()里藏着那只虫子,就快要抓住它了:

package com.sina.weibo.sdk.auth;
public final class a {// ...public final void d() {c.a("WBSsoTag", "startClientAuth()");try {Context var1;com.sina.weibo.sdk.b.a.a var2 = com.sina.weibo.sdk.b.a.e(var1 = (Context)this.d.get());Intent var3 = new Intent();if (var2 == null) {var3.setClassName("com.sina.weibo", "com.sina.weibo.SSOActivity");} else {var3.setClassName(var2.packageName, var2.ag);}// 报错的是这一行代码,之后就被catch到了错误,并提示"occur exception"AuthInfo var6 = com.sina.weibo.sdk.a.b();var3.putExtra("appKey", var6.getAppKey());var3.putExtra("redirectUri", var6.getRedirectUrl());var3.putExtra("scope", var6.getScope());var3.putExtra("packagename", var6.getPackageName());var3.putExtra("key_hash", var6.getHash());var3.putExtra("_weibo_command_type", 3);var3.putExtra("_weibo_transaction", "" + System.currentTimeMillis());Activity var4;if ((var4 = (Activity)this.d.get()) == null) {this.e.onError(new UiError(-1, "activity is null", ""));} else if (com.sina.weibo.sdk.b.a.a(var1, var3)) {var6.getAppKey();var3.putExtra("aid", com.sina.weibo.sdk.b.e.s());var4.startActivityForResult(var3, 32973);c.a("WBSsoTag", "start SsoActivity ");} else {this.e.onError(new UiError(-2, "your app is illegal", ""));}} catch (Exception var5) {var5.printStackTrace();c.b("WBSsoTag", var5.getMessage());this.e.onError(new UiError(-3, "occur exception", var5.getMessage()));}}// ...
}

看到了报错信息的产生位置了,com.sina.weibo.sdk.a.b()做了什么,为什么会有报错产生:

package com.sina.weibo.sdk;
public final class a {private static boolean a = false;private static AuthInfo b;private static String mAid;public static void a(Context var0, AuthInfo var1) {if (!a) {if (var1 == null) {throw new RuntimeException("authInfo must not be null.");}b = var1;String var4 = var1.getAppKey();WeiboSsoSdkConfig var2;(var2 = new WeiboSsoSdkConfig()).setContext(var0.getApplicationContext());var2.setAppKey(var4);var2.setFrom("1478195010");var2.setWm("1000_0001");WeiboSsoSdk.initConfig(var2);try {WeiboSsoSdk.getInstance().visitorLogin(new VisitorLoginListener() {public final void handler(VisitorLoginInfo var1) {try {if (var1 != null) {com.sina.weibo.sdk.a.mAid = var1.getAid();com.sina.weibo.sdk.a.c();}} catch (Exception var2) {var2.printStackTrace();}}});return;} catch (Exception var3) {var3.printStackTrace();}}}private static void a() {if (!a) {throw new RuntimeException("please init sdk before use it. Wb.install()");}}public static AuthInfo b() {a();return b;}// ...
}

原来又是它,第三步registerApp中异步操作的执行类,WeiboSsoSdk.getInstance().visitorLogin()方法的调用者。变量a的值不符合预期,所以报错了RuntimeException("please init sdk before use it. Wb.install()"),再想看看变量a的值什么时候再赋值为true就找不到地方了,线索就到这断了?!!

3、解决方式

别急,车到山前必有路,线索虽然断了,但是解决的办法已经出现在你眼前了。注意一下最后跟踪到报错的位置:

package com.sina.weibo.sdk;
public final class a {private static boolean a = false;// ...private static void a() {if (!a) {throw new RuntimeException("please init sdk before use it. Wb.install()");}}public static AuthInfo b() {a();return b;}// ...
}

RuntimeException("please init sdk before use it. Wb.install()")这个错误是com.sina.weibo.sdk.a.a()抛出的,上一个调用它的方法是com.sina.weibo.sdk.a.b(),仔细看看,com.sina.weibo.sdk.a类是public修饰的,虽然com.sina.weibo.sdk.a.a()方法是private修饰的,但是com.sina.weibo.sdk.a.b()方法是public修饰的,所以我们可以手动调用com.sina.weibo.sdk.a.b()方法来判断是否已完成微博开放平台的初始化!

修改一下原有的初始化逻辑,增加一个初始化是否完成的判断:

val authInfo = AuthInfo(activity, mAppId, mRedirectUrl, SCOPE)
val wbApi = WBAPIFactory.createWBAPI(activity)
wbApi.registerApp(activity, authInfo)
while (true) (try {// 如果没有抛出异常,断言通过,说明初始化已完成,循环结束a.b()break} catch (e: Exception) {e.printStackTrace()}
)

到此问题就解决了,在初始化完成之后再执行后续的操作,再没有出现“occur exception”的报错提示了。如果怕出现死循环,可以对循环加一个超时机制。

完毕

今天的分享就到这里,文章多有不足,各位小伙伴有什么想法可以直接评论或是私信,要是对你有所帮助就给我一个赞吧,喜欢我的小伙伴可以关注我哦~

此文章已收入Android偶遇杂症合集(持续更新)

支持我的小伙伴们可以微信搜索“Android思维库”,或者微信扫描下方二维码,关注我的公众号,每天都会推送新知识~

微博开放SDK初始化后使用报错please init sdk before use it. Wb.install()问题解决相关推荐

  1. linux7yum配置后使用报错,Centos7 使用yum安装MariaDB 10.1(报错缺少依赖的解决情况,报错信息贴在最后)-Go语言中文社区...

    1.创建 MariaDB yum 仓库 官方教程截图: 1.1 根据教程提示,创建MariaDB.repo 写入以下内容并保存: vi /etc/yum.repos.d/MariaDB.repo [m ...

  2. adb驱动安装和使用报错笔记

    adb驱动安装 adb驱动下载地址:https://adb.clockworkmod.com/ 安装时候选择一个容易记住的路径,这个很重要,因为adb驱动没有自动配置环境变量,所以实验时候将adb安装 ...

  3. 记录webpack使用问题,使用报错“UnhandledPromiseRejectionWarning,file-loader图片过大,无法加载图片,打包html文件报错TypeError

    记录webpack使用报错 版本号问题 运行npm run build,报错 "UnhandledPromiseRejectionWarning: TypeError: this.getRe ...

  4. “this”不能在常量表达式中使用报错的解决方法

    "this"不能在常量表达式中使用报错的解决方法 问题描述与思考 在用C++书写下面一段代码时,编译器报错"'this'不能在常量表达式中使用".在这里,我最开 ...

  5. git使用报错:fatal: Couldn't find remote ref master的解决方法

    git使用报错:fatal: Couldn't find remote ref master的解决方法 fatal: Couldn't find remote ref master 翻译过来就是:致命 ...

  6. Assets.car 解压工具 cartool 使用报错 segmentation fault cartool 解决方案

    Assets.car 解压工具 cartool 使用报错 segmentation fault cartool 解决方案 参考文章: (1)Assets.car 解压工具 cartool 使用报错 s ...

  7. CentOS系统yum源使用报错:Error: Cannot retrieve repository metadata

    服务器上的yum突然不好使用,使用yum的时候报错如下: [root@bastion-IDC src]# yum list ...... Could not retrieve mirrorlist h ...

  8. Python安装xlrd和xlwt的步骤以及使用报错的解决方法

    Python安装xlrd和xlwt的步骤以及使用报错的解决方法 参考文章: (1)Python安装xlrd和xlwt的步骤以及使用报错的解决方法 (2)https://www.cnblogs.com/ ...

  9. git使用报错: fatal: Couldn‘t find remote ref master的解决方法

    git使用报错: fatal: Couldn't find remote ref master的解决方法 参考文章: (1)git使用报错: fatal: Couldn't find remote r ...

最新文章

  1. python创建excel图表_python使用VBA(8):Excel创建图表(简单)
  2. neo4j查询多跳关系的方法
  3. 超云将成为数据中心演化的下一个阶段
  4. Jerry的Kubernetes学习笔记
  5. leetcode 452. 用最少数量的箭引爆气球(贪心算法)
  6. (转)Spring+JDBC组合开发
  7. 正则表达式 匹配标签里面的值 eg:image input
  8. 【快代理API】获取开放代理
  9. CrossApp环境搭建
  10. 表白生成器PHP源码,带自动生成的php表白程序 v1.0
  11. 计算机文字输入程序,电脑“造字”,其实很简单
  12. 某客服热线呼叫中心话务分析
  13. 开源直播美颜SDK工具算法分析
  14. PMP第四章:项目整合管理
  15. 玩游戏掉帧严重?看过来!
  16. 服务器阵列有什么作用,服务器存储-存储服务器和磁盘阵列有什么区别
  17. 计算机组成原理:VHDL设计微程序控制器(代码通俗易懂)
  18. Hive的nvl、coalesce、if、nvl2
  19. css–sprit_高级CSS –类已用完–通过使用结构化格式标签避免类
  20. 章泽天卸任刘强东旗下公司董事 官方回应:正常商业调整

热门文章

  1. 高维数据中特征筛选方法的思考总结——单变量分析筛选法
  2. 如何为员工开展针对性体检
  3. java根据两条直线的四个坐标点证明这两条线平行(计算直线斜率)或者三个点在一条直线上
  4. 对勾和叉怎么打_“对勾”“错叉”符号怎么打
  5. 电商数据课程-SQL笔记总结
  6. 手机黑屏显示服务器,三星服务器被攻击:出现黑屏、重启现象!华为迎来机会?...
  7. 老子云:近乎100%的还原,感觉自己玩到了端游
  8. 为什么带有E-Marker芯片的数据线才是快充数据线?
  9. mac下编译ncnn和ncnn中的pnnx
  10. android sqlcipher github,android – sqlcipher_export没有导出我的表