※はじめは Android 4.4以下でこの現象が発生していると思われましたが、5.0.2以下でも発生していることがわかったため、一部加筆修正しました。
Android 5.0.2 以下で Twitter のPINコード認証ができなくなった (2016-06-30更新)
Twitterにて、Android 5.0.2 以下の環境でアプリ内部のブラウザやAndroid標準ブラウザを利用したPINコード認証がうまくできなくなりました。
以前はAndroid 2.* でうまくで認証できなくなったため UserAgentのAndroidバージョン書き換えて対処していました。
その後、今年6月に入ったあたりで Android 4.0 – 4.3 でも認証できなくなり、こちらもUserAgentでAndroid バージョンを書き換えて対処していました。
ところが Android 4.4 でも認証できなくなり、UserAgentのAndroid バージョンを書き換えただけでは認証できなくなってしまいました。
この対応をした後に、Android 5.0 や 5.0.2 でも同様の現象が発生しているという報告があり、さらに調整を行いました。
エラーメッセージ「必要な情報が取得できませんでした」が表示される
上記のバージョンで認証を行うと
「必要な情報が取得できませんでした。連携アプリに戻ってもう一度試してみてください。」
と表示されます。戻ってもう一度試したところで何も状況が変わることはありません。
ちなみに英語だと、
This page requires some information that was not provided. Please return to the site that sent you to this page and try again … it was probably an honest mistake.
と表示されます。
なぜ認証できないのか?
Twitter社は認証ページを表示するときにブラウザのUserAgentを判断して、Android のバージョンが古いと、違うWebデータを返しているようで、そのWebページで不都合が発生しているようです。
Twitterの仕様変更か、制限か、不具合だと考えられます。不具合だとしても長期的に修正されない状況から判断してTwitter社はこれを修正することはないと思われます。Twitter社のForumで2015年9月に英語で質問を投稿していますが、返信は何もついていません。
どう対応したか?
UserAgent をいろいろ加工して試験をしました。独自に生成したUserAgentに差し替えたところ、正常に認証が終了してPINコードが表示されるようになりました。何が最適解なのかはここでは追求せず、とりあえず動作したのでこの対応で完了したいと思います。
今回実装したコード (2016-06-30更新)
今回実装したJavaのコードを載せておきます。
TwitterAuthUtils.java
package net.sinproject.twitter; public class TwitterAuthUtils { public static String VALID_USER_AGENT = "Mozilla/5.0 (Linux; Android 5.0;) Chrome/39.0.0.0 Mobile Safari/537.36"; public static String getValidUserAgent(String userAgent) { if (userAgent.matches(".*Android (2|3|4)(.[0-9]*)*.*")) return VALID_USER_AGENT; userAgent = userAgent.replaceFirst("Chrome/(37|38)", "Chrome/39"); return userAgent; } // public static String getValidUserAgentOld(String userAgent) { // return userAgent.replaceFirst("Android ((2|3).[0-9](.[0-9])*|4.[0-3](.[0-9])*)", "Android 5.0"); // } }
OAuthActivity.java
package net.sinproject.android.tweecha.core.activity; import ... public class OAuthActivity extends ActionBarActivity { @Override public void onCreate(Bundle savedInstanceState) { ... WebView webView = (WebView) findViewById(R.id.oauthWebView); String originalUserAgent = webView.getSettings().getUserAgentString(); String arrangedUserAgent = TwitterAuthUtils.getValidUserAgent(originalUserAgent); webView.getSettings().setUserAgentString(arrangedUserAgent); ... } }
TwitterAuthUtilsTest.java
package net.sinproject.twitter; import junit.framework.TestCase; import org.junit.Test; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; public class TwitterAuthUtilsTest extends TestCase { @Test public void testGetValidAgent() throws Exception { assertThat(TwitterAuthUtils.getValidUserAgent("Android 2.3"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 2.3.1"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 2.3.2"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 2.3.4"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 3.0.9"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 3.1.0"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 3.2"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.0"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.1"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.1.1"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.2"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.2.2"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.3"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Android 4.3.2"), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat(TwitterAuthUtils.getValidUserAgent("Google Android 4.3 hogehoge ..."), is(TwitterAuthUtils.VALID_USER_AGENT)); assertThat( TwitterAuthUtils.getValidUserAgent("Mozilla/5.0 (Linux; Android 5.0; Google Nexus 5 - 5.0.0 - API 21 - 1080x1920 Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36") , is("Mozilla/5.0 (Linux; Android 5.0; Google Nexus 5 - 5.0.0 - API 21 - 1080x1920 Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36") ); assertThat( TwitterAuthUtils.getValidUserAgent("Mozilla/5.0 (Linux; Android 5.1; Samsung Galaxy S6 - 5.1.0 - API 22 - 1440x2560 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36") , is("Mozilla/5.0 (Linux; Android 5.1; Samsung Galaxy S6 - 5.1.0 - API 22 - 1440x2560 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36") ); } // @Test // public void testGetValidAgentOld() throws Exception { // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 2.3"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 2.3.1"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 2.3.2"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 2.3.4"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 3.0.9"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 3.1.0"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 3.2"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.0"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.1"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.1.1"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.2"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.2.2"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.3"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Android 4.3.2"), is("Android 4.4.4")); // assertThat(TwitterAuthUtils.getValidUserAgentOld("Google Android 4.3 hogehoge"), is("Google Android 4.4.4 hogehoge")); // } }