因为做的APP是面向海外版,这两天突然说Twitter登录失败,查了各种原因和解决方案,最终解决,并提供两种解决方案。
Twitter大佬更新授权认证机制,应用后台没有更新过来,导致大面积登录出问题,很崩!
问题描述
如果手机安装Twitter客户端,无影响,如果未安装,则提示登录失败,不能登录。
二话不说,连上手机看日志:
06-15 16:22:25.734 1015-1015/com.example.testlogin E/Twitter: Invalid json: <?xml version="1.0" encoding="UTF-8"?><errors><error code="415">Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings</error></errors>
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45)
at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)
at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:110)
at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:95)
at com.twitter.sdk.android.core.TwitterApiException.<init>(TwitterApiException.java:43)
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45)
at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)
at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:110)
at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:95)
at com.twitter.sdk.android.core.TwitterApiException.<init>(TwitterApiException.java:43)
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
下面还有一串,但这才是主要原因,下面就不看了。分析下是啥,json解析失败,,正常来说是成功的,现在返回了一串xml代码,当然失败了。那么问题就在xml中的错误描述了。
Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings
可以,问题就是这个了,Twitter应用后台的Callback URL设置有问题,但是这个东西完全没动过,怎么会突然不行了?
查找解决方案
查查Twitter有没有搞事情?果然,最后发现Twitter在五月份发布了一则公告,提示使用Twitter登录的用户,如果需要继续使用Twitter登录的话,需要在应用后台将Callback URL添加到白名单里,ok,解决方案有了,到底填什么呢?讲真,Twitter官方也没有讲清楚,这几天到处也是一片提问的身影。。。。。
期间各种博客、社区、官网描述的都是Callback URL随便填个能够访问的地址就ok了,我也再次照着官方集成的android-kit写了一波,仍然不行,同样的错误。崩溃。
解决方案1
最后在某个issue中找到了一个Callback URL,据说是Twitter官方使用的url,把它填入到我们的应用后台白名单就ok了
对就是它:twittersdk://
填完之后是这样:
就这样,客户端什么也不用动了,继续正常使用。
解决方案2
另一种解决方案,这个改动起来大,需要更新客户端代码,因为催得急,所以也了解了一波,写了个demo接得差不多了(然后发现了第一种解决方案,分分钟回退代码)。
这个方案就是使用Twitter的Auth授权api直接去加载页面,对的,自己加载。
Twitter开发者官网的api中有认证这一块的api接口,
参数是必传的一个oauth_token
最后拼装起来就是这样的一个url和页面
所以,我们需要加载的就是这个页面了,自己写个webView去加载这个地址就行了!
最后是token怎么来,直接上代码好吧:
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.setOAuthConsumerKey(KEY);
configurationBuilder.setOAuthConsumerSecret(SECRET);
Configuration configuration = configurationBuilder.build();
mTwitter = new TwitterFactory(configuration).getInstance();
new Thread(new Runnable() {
@Override
public void run() {
try {
requestToken = mTwitter.getOAuthRequestToken();
runOnUiThread(new Runnable() {
@Override
public void run() {
webView.loadUrl(requestToken.getAuthenticationURL());
}
});
}catch (twitter4j.TwitterException e) {
e.printStackTrace();
}
}
}).start();
这样的话也能进入授权页面,然后再WebviewClient中监听,完成登录之后进入授权页面的时候,通过Twitter提供个另一个方法去获取用户的信息。
accessToken = mTwitter.getOAuthAccessToken(requestToken, strVerifier);
requestToken就是之前获取到的token,strVerifier这个参数,我们从url中获取,跳转授权网页的链接中有个参数叫做oauth_verifier,我们通过uri.getQueryParameter(“oauth_verifier”)获取到这个参数。
注意,这个是网络操作,耗时的。
最后,AccessToken中的信息就是twitter用户的信息了。
踩坑记录,希望能帮助到大家。