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

微博开放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思维库”,或者微信扫描下方二维码,关注我的公众号,每天都会推送新知识~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值