This post is about how to implement Twitter Integration in our Android app and let users do Sign In with a single click.
Integrating Twitter API in the Android app requires the app Consumer Key (API Key) and Consumer Secret (API Secret).
Steps to generate Twitter API Key and API Secret
1. Login at https://apps.twitter.com/ with your Twitter account and click on ‘Create App’.
2. Fill in the application details and get keys and tokens related to your project, then click on ‘App Settings‘.
3. Under User authentication settings click on set up.
4. Enable the authentication methods according to your requirement as shown below:
5. Enter App type, enable request email from users only if you want to request user’s email in your app and also select app permission according to your requirement.
6. Enter your website URL and enter twittersdk:// in Callback URI field which is mandatory in order to enable authentication through Twitter.
7. Fill in the below two properties which are mandatory when you enable “Request email from users” and then click on save.
Creating new project
1 . Create a new project by going to File ⇒ New Android Project, select Empty Activity, provide app name, select language to kotlin and then finally click on finish.
2 . Open app-level build.gradle file and add the below libraries under dependencies section and then click on Sync Now.:
dependencies {
//Include all the Twitter APIs
//compile 'com.twitter.sdk.android:twitter:3.1.1'
//include only the necessary dependencies to avoid the Android dex limit
implementation 'com.twitter.sdk.android:twitter-core:3.1.1'
//dependency to load image url over image view
implementation 'com.squareup.picasso:picasso:2.5.2'
}
3 . Open the AndroidManifest.xml file and add the Internet permission above the application element.
<uses-permission android:name="android.permission.INTERNET" />
4. Open your /app/res/values/strings.xml file and place the ‘Consumer Key’ and ‘Consumer Secret’ of our app generated by Twitter:
<resources>
<!--
place here CONSUMER_KEY(API Key) and CONSUMER_SECRET(API Secret)
-->
<string name="com.twitter.sdk.android.CONSUMER_KEY">ENTER YOUR CONSUMER_KEY</string>
<string name="com.twitter.sdk.android.CONSUMER_SECRET">ENTER YOUR CONSUMER_SECRET</string>
</resources>
Creating the Layout File
5. The below layout file consists of a TwitterLoginButton, an ImageView (to show user profile picture), and a TextView (to show user info).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">
<com.twitter.sdk.android.core.identity.TwitterLoginButton
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/userImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="50dp"
android:scaleType="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/userDetail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:padding="5dp"
android:text=""
android:textColor="@color/purple_500"
android:textSize="21sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/userImage" />
</androidx.constraintlayout.widget.ConstraintLayout>
Creating the Application class
6. Inside the MyApplication class initialize the TwitterKit SDK.
MyApplication.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
// Entry point to initialize the TwitterKit SDK.
Twitter.initialize(this)
}
}
7. Open the AndroidManifest.xml file and add the application name property as shown below:
<application
android:name=".MyApplication"
....
</application>
Creating the MainActivity File
8. The MainActivity.kt file contains the below code:
MainActivity.kt
package com.c1ctech.twitloginexp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.c1ctech.twitloginexp.databinding.ActivityMainBinding
import android.widget.Toast
import com.twitter.sdk.android.core.*
import android.content.Intent
import com.squareup.picasso.Picasso
import com.twitter.sdk.android.core.models.User
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
loginWithTwitter()
}
private fun loginWithTwitter() {
//user is not authenticated
if (getTwitterSession() == null) {
//Sets the Callback to invoke when login completes.
activityMainBinding.loginButton.setCallback(object : Callback<TwitterSession?>() {
//Unsuccessful call due to network failure, non-2XX status code, or unexpected exception.
override fun failure(exception: TwitterException?) {
Toast.makeText(
applicationContext,
"Login failed: " + exception,
Toast.LENGTH_LONG
).show()
}
//Called when call completes successfully.
override fun success(result: Result<TwitterSession?>?) {
Toast.makeText(applicationContext, "Login successful", Toast.LENGTH_LONG).show()
val twitterSession = result?.data
//get secret and token from twitterSession
/*val token = twitterSession?.authToken?.token
val secret = twitterSession?.authToken?.secret*/
if (twitterSession != null) {
//fetch user twitter info and display it on screen
fetchUserTwitterInfo()
}
}
})
} else {
Toast.makeText(this, "User already authenticated", Toast.LENGTH_SHORT).show()
fetchUserTwitterInfo()
}
}
//return the active session if available
private fun getTwitterSession(): TwitterSession? {
val twitterSession = TwitterCore.getInstance().sessionManager.activeSession
return twitterSession
}
// this method will provide you User model which contains all user information
fun fetchUserTwitterInfo() {
//fetch twitter image with other information if user is already authenticated
if (getTwitterSession() != null) {
//initialize twitter api client
val twitterApiClient = TwitterCore.getInstance().apiClient
//pass includeEmail : true if you want to fetch Email as well
val call =
twitterApiClient.accountService.verifyCredentials(true, false, true)
call.enqueue(object : Callback<User?>() {
// Called when call completes successfully.
override fun success(result: Result<User?>?) {
val user = result?.data
activityMainBinding.userDetail.text =
"""
User Id : ${user?.id}
User Name : ${user?.name}
Email Id : ${user?.email}
Screen Name : ${user?.screenName}
""".trimIndent()
var imageProfileUrl = user?.profileImageUrl
//NOTE : User profile provided by twitter is very small in size
//Link : https://developer.twitter.com/en/docs/accounts-and-users/user-profile-images-and-banners
//so if you want to get bigger size image then do the following:
imageProfileUrl = imageProfileUrl?.replace("_normal", "")
//load image using Picasso
Picasso.with(this@MainActivity)
.load(imageProfileUrl)
.placeholder(R.drawable.placeholder)
.into(activityMainBinding.userImage)
}
// Unsuccessful call due to unexpected exception.
override fun failure(exception: TwitterException?) {
Toast.makeText(
this@MainActivity,
exception?.message,
Toast.LENGTH_SHORT
).show()
}
})
} else {
//if user is not authenticated first ask user to do authentication
Toast.makeText(this, "User is not authenticated.", Toast.LENGTH_SHORT)
.show()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Pass the activity result to the login button.
activityMainBinding.loginButton.onActivityResult(requestCode, resultCode, data)
}
}
In the above code,
- getTwitterSession() method will return the active session if available.
- When a user successfully logs in, the loginButton.onActivityResult() will invoke, which will pass the response to the registered callback.
- If the login succeeds, the TwitterSession parameter has the userId, userName, authToken (contains token and secret), etc.
- If the TwitterSession parameter is not null, then we will fetch the user’s Twitter info and display it on the screen.
- If the login failed, the callback failure() method will call with an exception.
When you run the app it will look like this:
When a user clicks on Log in with Twitter button, it will ask for entering the user’s Twitter email/username and password then click on “Authorize app”.
When a user successfully logs in, it will show the user info as shown below: