Twitter純正SDK TwitterKitでログイン認証

TwitterSDKの[TwitterKit](https://docs.fabric.io/android/twitter/index.html)で、ログイン認証する方法です。
単純なログイン画面の実装は[ドキュメント](https://docs.fabric.io/android/twitter/authentication.html)を見ていただくとして、今回はInstagram投稿時のTwitter認証と同じような動作を実装してみました。

![ezgif.com-maker (1).gif](https://qiita-image-store.s3.amazonaws.com/1598/15267/97bae815-5ffa-1480-1fe4-63cc42feebf8.gif "ezgif.com-maker (1).gif")

#TwitterKitのセットアップ
[Integrate the SDK](https://docs.fabric.io/android/fabric/integration.html)の手順に沿ってセットアップします。AndroidStudio、Eclipseを使っているならプラグインを入れれば簡単にセットアップできます。

#SwitchCompatタップ時の実装
`SwitchCompat`をタップした時の動きを実装します。

```java
SwitchCompat mSwitchView;
private TwitterAuthClient authClient;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mSwitchView = (SwitchCompat) findViewById(R.id.switch_twitter);

    // SwitchViewをタップした時に、Twitter認証していなければチェックをつけないようにしておく
    mSwitchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (Twitter.getSessionManager().getActiveSession() == null) {
                mSwitchView.setChecked(false);
            }
        }
    });
}

private void onClickSwitchTwitter() {
    // チェックがついていない時のみTwitterログイン状態を確認
    if (!mSwitchView.isChecked()
        && Twitter.getSessionManager().getActiveSession() == null) {
        authClient = new TwitterAuthClient();
        authClient.authorize(this, new Callback<TwitterSession>() {
            @Override
            public void success(Result<TwitterSession> result) {
                // セッションをセットしてチェックをつける
                Twitter.getSessionManager().setActiveSession(result.data);
                mSwitchView.setChecked(true);
            }

            @Override
            public void failure(TwitterException e) {
                Log.e(TAG, e.getMessage());
            }
        });
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (authClient != null) {
        authClient.onActivityResult(requestCode, resultCode, data);
    }
}
```

Twitterアプリがインストールされている場合はシングルサインオン認証してくれます。アプリがインストールされていない場合はWebViewの認証画面が表示されます。

#Authorize failedエラーが出た時
`Authorize failed.`というエラーが出た場合

* TWITTER_KEY、TWITTER_SECRETが間違っている
* 端末の時刻設定が未来日時になっている

のどちらかだと思います。

参考 : [[Android] 正しく時刻設定してないと Twitter 認証時にエラー発生](http://codenote.net/android/2063.html)

```java
com.twitter.sdk.android.core.TwitterAuthException: Failed to get request token
            at com.twitter.sdk.android.core.identity.OAuthController$1.failure(OAuthController.java:74)
            at com.twitter.sdk.android.core.internal.oauth.OAuth1aService$1.failure(OAuth1aService.java:215)
            at com.twitter.sdk.android.core.Callback.failure(Callback.java:28)
            at retrofit.CallbackRunnable$2.run(CallbackRunnable.java:53)
            at android.os.Handler.handleCallback(Handler.java:587)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:130)
            at android.app.ActivityThread.main(ActivityThread.java:3739)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:507)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:911)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:669)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: com.twitter.sdk.android.core.TwitterApiException: Received authentication challenge is null
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:389)
            at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
            at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
            at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
            at retrofit.Platform$Android$2$1.run(Platform.java:142)
            at java.lang.Thread.run(Thread.java:1019)
```