KotlinでTwitter4jを使ってTwitterのOauthログインを実装する

目次

  1. 背景
  2. Twitter Appの設定
  3. プロジェクトの作成
  4. 依存パッケージの指定
  5. 権限の追加
  6. ログイン画面の作成
  7. 接続情報Objectクラスの作成
  8. Fragmentの実装
  9. まとめ
  10. ところで…
  11. 関連記事

背景

こんにちは。 かりんとうマニア(@karintozuki)です。

Twitter4jを使ったTwitterのログイン機能をアプリに組み込む方法を紹介します。
冒頭のGIFのように、Dialogが開いて
ログイン・認証をするような挙動が実装できます。

ちなみに本記事、こちらの記事をだいぶ~~~パクリ~~~参考にしています。
https://johncodeos.com/how-to-add-twitter-login-button-to-your-android-app-using-kotlin
(ほぼ同じなのですが、この記事ではFragmentから実行しています。)

Twitter Appの設定

Twitter Developer Portalからアプリの設定をします。
https://developer.twitter.com/en/portal/dashboard

アプリを作成していない人は作成しておいてください。

作成したアプリの設定画面から
Authentication settings > 3-legged OAuth is enabledを有効にしてください

このときcallback urlを設定します。
callback://を指定します。

また、アプリのConsumer (API) Key と Consumer (API) Secretも使うので、
控えておいてください。

プロジェクトの作成

Android Studioからプロジェクトを作成します。
Basic Activityを選択してください。

プロジェクト名などは適当に決めてください。

依存パッケージの指定

appレベルのbuild.gradleに以下を追加します。

build.gradle
1
2
3
4
5
6
dependencies {
   // 中略
    implementation 'org.twitter4j:twitter4j-core:4.0.7'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'

}

権限の追加

AndroidManifest.xmlに権限を追加します。
<uses-permission android:name="android.permission.INTERNET" />
manifestタグの中に描きます。

AndroidManifest.xml
1
2
3
4
5
6
7
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bedroomcomputing.logintest">
    <application>
<!--中略-->
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

ログイン画面の作成

basicプロジェクトを選択した場合、
fragment_first.xmlがあると思います。
このボタンをログインボタンにしていきます。

ボタンとTextViewのテキストだけ
それっぽいものに変えておきます。

fragment_first.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <TextView
        android:id="@+id/textview_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Twitter Login" // ここを変更
        app:layout_constraintBottom_toTopOf="@id/button_first"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login" // ここを変更
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview_first" />
</androidx.constraintlayout.widget.ConstraintLayout>

接続情報Objectクラスの作成

APIキーやCallbackURLを保持するためのObjectクラスを作成します。
New > Kotlin File/Class

Objectを選択します。

ファイルの中身には先ほど控えたAPIキーとAPIシークレットを格納します。

TwitterConstants.kt
1
2
3
4
5
6
7
object TwitterConstants {

    var CONSUMER_KEY = "MY_CONSUMER_KEY"
    var CONSUMER_SECRET = "MY_CONSUMER_SECRET"
    var CALLBACK_URL = "MY_CALLBACK_URL"

}

Fragmentの実装

まずはRequestTokenを取得します。
ボタンのクリックリスナーにgetRequestTokenを追加します。

FirstFragment.kt
1
2
3
4
5
6
7
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

view.findViewById<Button>(R.id.button_first).setOnClickListener {
getRequestToken();
}
}

getRequestToken()関数を実装します。
注意する点としては、Coroutineを使って、次のWebView生成の関数を呼んでいるところです。

FirstFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
lateinit var twitter: Twitter

    private fun getRequestToken(){
        viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default){

            // twitterインスタンスにConsumer keyとConsumer Secretを設定
            val builder = ConfigurationBuilder()
                .setDebugEnabled(true)
                .setOAuthConsumerKey(TwitterConstants.CONSUMER_KEY)
                .setOAuthConsumerSecret(TwitterConstants.CONSUMER_SECRET)

            val config = builder.build()
            val factory = TwitterFactory(config)

            // twitter インスタンスを生成
            twitter = factory.instance

            try{
                // リクエストトークンを取得
                val requestToken = twitter.oAuthRequestToken
                withContext(Dispatchers.Main){
                    setupTwitterWebviewDialog(requestToken.authorizationURL)
                }
            } catch (e: IllegalStateException) {
                Log.e("ERROR: ", e.toString())
            }

        }
    }

次にDialogとWebViewを定義します。

FirstFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
lateinit var twitterDialog: Dialog
var accToken: AccessToken? = null

// Dialogの設定
private suspend fun setupTwitterWebviewDialog(url: String){
twitterDialog = Dialog(requireContext())
val webView = WebView(requireContext())

webView.isVerticalScrollBarEnabled = false
webView.isHorizontalScrollBarEnabled = false
webView.webViewClient = TwitterWebViewClient()
webView.settings.javaScriptEnabled = true
webView.loadUrl(url)
twitterDialog.setContentView(webView)
twitterDialog.show()

}

// WebViewの設定
inner class TwitterWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
if (request?.url.toString().startsWith(TwitterConstants.CALLBACK_URL)) {
Log.d("Authorization URL: ", request?.url.toString())
handleUrl(request?.url.toString())

// 認証が完了したらダイアログを閉じる
if (request?.url.toString().contains(TwitterConstants.CALLBACK_URL)) {
twitterDialog.dismiss()
}
return true
}
return false
}

OAuthトークンとユーザ情報を取得してみます。

FirstFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// OAuthのトークン取得
private fun handleUrl(url: String) {
val uri = Uri.parse(url)
val oauthVerifier = uri.getQueryParameter("oauth_verifier") ?: ""
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
val accToken = withContext(Dispatchers.IO) {
twitter.getOAuthAccessToken(oauthVerifier)
}
Log.i("token", accToken.token)
Log.i("token secret", accToken.tokenSecret)
getUserProfile()
}
}

// ユーザ情報取得
private suspend fun getUserProfile(){
val usr = withContext(Dispatchers.IO){ twitter.verifyCredentials() }

Log.i("twitter", usr.name)
Log.i("twitter", usr.screenName)
}
}

ここで取得できるTokenとTokenSecretを使うことで
次回からのダイアログを開いて認証する必要がなくなります。

動作としては以下の感じになります。
ボタンを押すと

Dialogが開きます。

ログインしてアプリを承認すると、トークンが取得できます。

まとめ

いかがでしたか。
TwitterのログインはOAuthやらなんやらでややこしいのですが、
Androidでやろうとするとなおややこしいですね。

GitHubに今回のプロジェクトを上げていますので、
興味がある方は見てみてください。
https://github.com/karintomania/twitterLoginTest

この記事がお役に立てれば幸いです。

それじゃ今日はこの辺で。

ところで…

仕事で扱っている技術がレガシーだったり、同じことの繰り返しだったりで
最近、成長してないと感じてませんか?

転職することで、もっと成長できるかもしれません。

いますぐ転職しない人でも、とりあえずエージェントに登録しておいて
案件や年収を眺めるだけでも市場の需要を知ることができ、勉強になります。

ここでエンジニアに人気の転職サイトを紹介します。

レバテックキャリア
エンジニアとして働いていて実務経験があるなら、
求人数の充実具合からレバテックキャリアがおすすめです。
IT転職ではデファクト・スタンダードですね。
▼レバテック キャリア 登録はこちら▼


Tech Clips
Tech Clipsは年収500万以上&自社サービスを持った会社に特化した求人サイトです。
首都圏限定になってはしまいますが、
収入を増やしたい、自社サービスを持った企業への転職をしたい人におすすめです。

▼Tech Clips 登録はこちら▼


関連記事

こちらの記事もおすすめです。

Twitter APIをJavaで触る!Twitter4jを使ってみた