Social Network Integration on Android

Learn how to let your users authenticate into your app using Facebook and Twitter, and see how to make posts to both social networks.

Version

  • Kotlin 1.2, Android 4.4, Android Studio 3

Many mobile apps require a user to create an account or to sign up for a service in order to use them. From a user’s point of view, this can be somewhat troublesome or annoying, and it’s not always the best user experience.

So how can you overcome this when building your app? To give users a seamless experience, you can give them the ability to sign in to your app with just a single tap of a button, using one of their social networking accounts, e.g., Facebook or Twitter.

In this tutorial, you’ll learn how to integrate a user’s Facebook and Twitter accounts into your Android app to allow them to log in and also share posts from your app into their social networking account.

Getting Started

Use the Download Materials link at the top or bottom of this tutorial to download and extract the Starter Project for this tutorial.

Next, open Android Studio 3.1.3 or later, and choose Open an existing Android Studio project from the welcome screen or File > Open form the menu. Open the folder root folder of the Sharetastic starter project.

You’ll be working on an app called Sharetastic, which allows a user to share a status update to Facebook or a tweet to Twitter.

Build and run the project and you’ll see the login screen for the app:

Starter project

As of now, the app does nothing. In this tutorial, you’ll go through it step-by-step and complete the social network integration.

Connecting With Facebook

To connect your app to Facebook, you’ll need an active Facebook account with which you’ll create an app to get a Facebook App ID.

Creating a Facebook App ID on Developers Portal & Setting Up

Go to the Facebook Developers Portal (log in with your Facebook account if needed).

On this page, you’ll see an option to Add a New App. Click the button and you’ll then need to create a Facebook App ID if you haven’t already:

Create Facebook App ID

Enter Sharetastic in the Display Name field and enter your email address in the Contact Email field, then click Create App ID. Facebook will prompt you with a captcha dialog; complete the request and click Submit.

Facebook will then direct you to another page:

Setup Facebook Login

Click on Set Up on the Facebook Login component. Then, from the new page containing the platform options, select Android.

You’ll then see the following page with the steps to build your Android project:

Steps to build

At this point, you will skip steps 1 and 2 because they have already been completed for you in the starter project. Even so, it’s good to know what they are:

Step 1 includes downloading the Facebook SDK, and Step 2 tells you how to import it into the project. Here, Gradle will be used to sync the Facebook SDK rather than manually downloading the SDK, which you can see in the app module build.gradle file:

implementation 'com.facebook.android:facebook-login:[4,5)'

In Step 3, you’ll add your Package name com.raywenderlich.sharetastic and default Activity name com.raywenderlich.sharetastic.MainActivity.

Facebook Step 3

Click on Save and then Continue (you may need to also confirm that your app is not yet in the Play Store).

For Step 4, you need to create a Development Key Hash and also a Release Key Hash if your app is live. A key hash is a 28-character-long string, which Facebook uses to verify the communication between your app and Facebook.

Key Hashes?

A key hash can be generated by typing the following command in the terminal:

For Mac and Linux:

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

For Windows:

Things are not that simple here. First, you need to have keytool from the JDK, Secondly, get the openssl library here.

keytool -exportcert -alias androiddebugkey -keystore "C:\Users\USERNAME\.android\debug.keystore" | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" sha1 -binary | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" base64

Finally, after generating your Key Hash, paste it in the section provided in the fourth step.

Paste key hash

Click Save then Continue.

For Step 5 on Single Sign On, if you’re working on a different app that is using notifications, you want want to set it to Yes, but, for now, leave it set to No and click on Save, then Next.

Single Sign On

Now, for Step 6, open up strings.xml in the app/res/values folder, and paste the following after updating the placeholders with the values provided by Facebook:

<string name="facebook_app_id">Your-App-ID</string>
<string name="fb_login_protocol_scheme">fbYour-App-ID</string>

Then, open AndroidManifest.xml and add the permission for accessing the Internet:

<uses-permission android:name="android.permission.INTERNET"/>

Additionally, under the application tag, paste the needed Facebook meta-data and activities:

    <meta-data android:name="com.facebook.sdk.ApplicationId" 
        android:value="@string/facebook_app_id"/>
    
    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges=
                "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:label="@string/app_name" />
    <activity
        android:name="com.facebook.CustomTabActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="@string/fb_login_protocol_scheme" />
        </intent-filter>
    </activity>

Finally, you’re done setting things up from the Facebook developer console! The remaining steps you’ll need to login are handled in the next section.

Now it’s time move on to writing some code.

Facebook setup complete

Log in With Facebook

Open up the main layout file activity_main.xml and add a Facebook login button below the TextView:

<com.facebook.login.widget.LoginButton
  android:id="@+id/facebookLoginButton"
  android:layout_width="wrap_content"
  android:layout_height="47dp"
  android:paddingBottom="15dp"
  android:paddingStart="10dp"
  android:paddingEnd="5dp"
  android:paddingTop="15dp"
  android:textSize="16sp"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintVertical_bias="0.58" />

In MainActivity, create the following constants at the top of the class:

val EMAIL = "email"
val PUBLIC_PROFILE = "public_profile"
val USER_PERMISSION = "user_friends"

Inside the empty method facebookSetup(), add the following code:

callbackManager = CallbackManager.Factory.create()
facebookLoginButton.setOnClickListener {
  facebookLoginButton.setReadPermissions(Arrays.asList(EMAIL, PUBLIC_PROFILE, USER_PERMISSION))
  facebookLoginButton.registerCallback(callbackManager, object : FacebookCallback<LoginResult> {
    override fun onSuccess(loginResult: LoginResult) {

    }

    override fun onCancel() {

    }

    override fun onError(exception: FacebookException) {
      Toast.makeText(context,exception.localizedMessage, Toast.LENGTH_SHORT).show()
    }
  })
}

This code first initializes the CallbackManager Facebook property that was declared but uninitialized in the starter project. It then adds a click listener for the Facebook login button. Inside the click listener, it provides the permissions needed to read the email, public profile and friends of the user. It also logs in the user by returning the AccessToken.

Then in onActivityResult(), pass the result onto the CallbackManager:

callbackManager.onActivityResult(requestCode, resultCode, data)

In the onSuccess of the callback, you’ll get the user’s profile by using Facebook’s Graph API. You’ll then send the user to the Share screen. First, we need to talk to the Graph API.

User Profile from the Graph API

You’ll now create a Kotlin object, whose sole purpose will be to contain the helper methods to connect to the Graph API.

Create an object called Helper in a new package com.raywenderlich.sharetastic.util.

Once created, write the method getFacebookUserProfileWithGraphApi() inside of it:

object Helper {

  fun getFacebookUserProfileWithGraphApi(context: Context) {

    if (AccessToken.getCurrentAccessToken() != null){
      val activity = context as Activity
      val request = GraphRequest.newMeRequest(
          AccessToken.getCurrentAccessToken()
      ) { jsonObject, _ ->
        val email = jsonObject?.get("email")?.toString() ?: ""
        val name = jsonObject.get("name").toString()
        val profileObjectImage = jsonObject?.getJSONObject("picture")?.getJSONObject("data")?.get("url").toString()

      }

      val parameters = Bundle()
      parameters.putString("fields", "id,name,link,picture.type(large), email")
      request.parameters = parameters
      request.executeAsync()
    }
  }
}

This method uses a call to GraphRequest.newMeRequest() to fetch the userid, name, picture and email of the user who is currently logged in.

To keep things clean, create a package com.raywenderlich.sharetastic.model and create a class in the package called UserModel to contain the user’s data after the Graph API returns the results.

Your UserModel class would look something like this:

class UserModel(val name: String, val userName: String, val profilePictureUrl: String, val socialNetwork: SocialNetwork) : Serializable

enum class SocialNetwork {
    Facebook, Twitter
}

I have created the enum class SocialNetwork in the same class; you could create a separate file for that if you wish. The enum class is only for identifying which social network account the user is currently logged in with.

Head back to Helper where you’ll now write the method that will help in sending the user to the Share screen.

fun startShareActivity(context: Context, user: UserModel) {
  val activity = context as Activity
  val intent = Intent(context, ShareActivity::class.java)
  intent.putExtra("user", user)
  activity.startActivity(intent)
  activity.finish()
}

This code takes the passed-in UserModel and sends it to the ShareActivity.

Go back to the method getFacebookUserProfileWithGraphApi() and after the line:

val profileObjectImage = jsonObject?.getJSONObject("picture")?.getJSONObject("data")?.get("url").toString() ?: ""

add the following:

val user = UserModel(name, email, profileObjectImage, SocialNetwork.Facebook)
startShareActivity(context, user)

These lines convert the user’s info to a UserModel and pass it into the method startShareActivity().

After completing that, go back to MainActivity. In the onSuccess inside of facebookSetup(), write:

Helper.getFacebookUserProfileWithGraphApi(context)

The user should only be sent to the Share screen when the user has a valid AccessToken, and this can happen only in the onSuccess block of code.

Additionally, you need to set up a few things in the ShareActivity.

Create a UserModel property in the class:

lateinit var user: UserModel

And inside onCreate(), add:

user = intent.extras.get("user") as UserModel
setData(user)

This piece of code is getting the passed in UserModel from the Intent method and passing the data to a new method setData().

The setData() method simply sets up the data in the UI, and includes conditionals that take slightly different actions depending on whether the logged in network is Facebook or Twitter.

fun setData(user: UserModel) {
  nameTextView.text = user.name
  userNameTextView.text =
      if (user.socialNetwork == SocialNetwork.Twitter)  "@${user.userName}"
      else user.userName
  connectedWithTextView.text = 
      if (user.socialNetwork == SocialNetwork.Twitter) "${connectedWithTextView.text} Twitter"
      else "${connectedWithTextView.text} Facebook"
  characterLimitTextView.visibility =
      if (user.socialNetwork == SocialNetwork.Twitter) View.VISIBLE
      else View.GONE
  postButton.text =
      if (user.socialNetwork == SocialNetwork.Twitter) "POST"
      else "CREATE POST"
  Picasso.with(this).load(user.profilePictureUrl).placeholder(R.drawable.ic_user).into(profileImageView)
  postEditText.visibility = View.GONE
}

Now, run your app then tap on Continue with Facebook. You’ll be asked to give your app the permission to access the information. After this step, you’ll be redirected to the following screen:

Successful login

You’ve successfully logged in!

Sharing on Facebook

It’s time to move on to posting a status to Facebook. For this, you need to change a few things.

Facebook recently changed its documentation and has removed the permission that was once required for the using the Graph API to share something on a user’s timeline. The alternative for that is now using the Facebook Share SDK.

Open the app build.gradle file, and add the following dependency in it:

implementation 'com.facebook.android:facebook-share:[4,5)'

Additionally, in your AndroiManifest.xml add the following line within the application tag:

<provider android:authorities="com.facebook.app.FacebookContentProvider{@string/facebook_app_id}"
  android:name="com.facebook.FacebookContentProvider"
  android:exported="true"/>

Now, open the ShareActivity class and write the method for posting status to Facebook:

fun postStatusToFacebook() {
  val builder = AlertDialog.Builder(this)
  builder.setTitle("Share Link")

  val input = EditText(this@ShareActivity)
  val lp = LinearLayout.LayoutParams(
      LinearLayout.LayoutParams.MATCH_PARENT,
      LinearLayout.LayoutParams.MATCH_PARENT)
  input.layoutParams = lp
  builder.setView(input)

  builder.setPositiveButton(android.R.string.ok) { dialog, p1 ->
    val link = input.text
    var isValid = true
    if (link.isBlank()) {
      isValid = false
    }

    if (isValid) {
      val content = ShareLinkContent.Builder()
          .setContentUrl(Uri.parse(link.toString()))
          .build()
      ShareDialog.show(this, content)
    }

    dialog.dismiss()
  }

  builder.setNegativeButton(android.R.string.cancel) { dialog, p1 ->
    dialog.cancel()
  }

  builder.show()
}

This code will present an alert dialog to allow the user to enter a link to share, and then show the user the Facebook share dialog. We’re not doing any validation on the link other than to check that it’s not blank; you’d want to do some validation to make sure it’s a valid URL.

In later versions of the Facebook Share SDK, including the one you’re using in Sharetastic, you must provide some type of content to share. Your options are links, photos, videos, and other multimedia. See the Facebook Share SDK documentation for more details.

Next, in the postButtonAction() method, inside the setOnClickListener, add a call to the new function:

postStatusToFacebook()

Build and run the app again. You’ll need to tap logout on the Facebook button and re-connect. In a production app, you’ll want to saved the logged in state of the user so that they don’t have to log in again.

Click on CREATE POST. Now, try posting something to Facebook:

Share link

Facebook dialog

After pressing POST, go and check the Facebook app.

Facebook app

Hurray! Your status is posted to Facebook.

Success

Logging Out of Facebook

Logging out is simply a one-line code, but, for logging out, you need to perform two additional tasks. You’ll now write a method in your ShareActivity that’ll do these tasks:

fun sendToMainActivity() {
  LoginManager.getInstance().logOut()
  finish()
  val intent = Intent(this, MainActivity::class.java)
  startActivity(intent)
}

Going over the above: the first line of code allows a user to log out of Facebook. The rest of the lines finish the current activity and take a user to MainActivity. Finally, call this method inside the onOptionsItemSelected like this:

R.id.action_logout -> {
  sendToMainActivity()
  return true
}

Once you tap the Logout button on top-right of the Share screen, you’ll be logged out from the app and taken to the Home screen.

Now, let’s connect the app with Twitter.

Connecting With Twitter

Like Facebook, you need a working Twitter account in order to integrate Twitter into your app, Twitter provides a Consumer Key and Consumer Secret for communication.

Creating a Twitter App on Developer Portal

Login to Twitter in a browser and head to Twitter’s Application Management Portal and click on Create New App.

Create new Twitter app

Complete the necessary fields with the appropriate information (you’ll need to use a unique name like Sharetastic + your initials, and you also must provide a Privacy Policy URL and Terms of Service URL in order to follow along, but these can be placeholders like example.com) then click Create your Twitter application.

You’ll be taken to the following page:

Details page


I had to name the app Share-tastic because Sharetastic wasn’t available. :]

Copy the Consumer Key and Consumer Secret from the Keys and Access Tokens tab and paste them into the strings.xml with the names Twitter_CONSUMER_KEY and Twitter_CONSUMER_SECRET, respectively.

Then click on the Permissions tab.

Permissions tab

If you want to get user’s email at the time of login, you have to check the option that says Request email addresses from users then click on Update Settings.

Setting Up

After finishing the creation of the app on the Twitter developer portal, you’ll now move on and add the Twitter Kit dependency.

Adding Twitter Kit Dependency

Note: This step can be skipped because it’s already done in the Starter Project

There are many dependencies provided by Twitter like Twitter Core, Tweet UI, Tweet Composer, and Twitter Mopub. For now, stick with Twitter Core because that’s the only dependency you need for this tutorial.

implementation 'com.twitter.sdk.android:twitter-core:3.1.1'

Paste the above dependency in the app build.gradle file and let the project sync.

Initializing Twitter Kit

Create a CustomApplication class extending from Application under a new package root. Override the onCreate() of the Application class as follows:

class CustomApplication : Application() {
  override fun onCreate() {
    super.onCreate()

    val config = TwitterConfig.Builder(this)
        .logger(DefaultLogger(Log.DEBUG))
        .twitterAuthConfig(TwitterAuthConfig(
            resources.getString(R.string.Twitter_CONSUMER_KEY),
            resources.getString(R.string.Twitter_CONSUMER_SECRET)))
        .debug(true)
        .build()
    Twitter.initialize(config)
  }
}

Then open AndroidManifest.xml and inside the tag application, paste the following snippet.

android:name=”com.raywenderlich.sharetastic.root.CustomApplication”

You are done setting up now and are ready to dive into writing some Twitter code!

Log in With Twitter

Add a Twitter login button to activity_main.xml:

<com.twitter.sdk.android.core.identity.TwitterLoginButton
  android:id="@+id/twitterLoginButton"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toBottomOf="@+id/facebookLoginButton"
  app:layout_constraintVertical_bias="0.1" />

Open MainActivity and inside the twitterSetup() method, add the following:

twitterLoginButton.callback = object : Callback<TwitterSession>() {
  override fun success(result: Result<TwitterSession>) {

  }

  override fun failure(exception: TwitterException) {
    Toast.makeText(context,exception.localizedMessage, Toast.LENGTH_SHORT).show()
  }
}

And in the onActivityResult() method, add the following line:

twitterLoginButton.onActivityResult(requestCode, resultCode, data)

Like the method you wrote that fetches the user info after Facebook’s login is complete, you need to write a similar method for Twitter that gets the user’s info at login.

Open the Helper file and write the following method:

fun getTwitterUserProfileWthTwitterCoreApi(
    context: Context, session: TwitterSession) {

  TwitterCore.getInstance().getApiClient(session).accountService
      .verifyCredentials(true, true, false)
      .enqueue(object : Callback<User>() {
        override fun success(result: Result<User>) {
          val name = result.data.name
          val userName = result.data.screenName
          val profileImageUrl = result.data.profileImageUrl.replace("_normal", "")
          val user = UserModel(name, userName, profileImageUrl, SocialNetwork.Twitter)
          startShareActivity(context, user)
        }

        override fun failure(exception: TwitterException) {
          Toast.makeText(context, exception.localizedMessage, Toast.LENGTH_SHORT).show()
        }
      })
}

You’re using TwitterCore to authenticate the user and then going to the share screen on a successful authentication.

Next, open MainActivity and in the success part of the twitterLoginButton callback, add:

Helper.getTwitterUserProfileWthTwitterCoreApi(context, result.data)

Now, build and run your project and tap on Log in with Twitter. You’ll need to be running Sharetastic on a device or emulator that has the Twitter app installed and in which you are logged in.

You’ll be shown a screen to accept connecting your Twitter account to Sharetastic, and after you allow it, you’ll successfully log in and be taken to the Share screen.

Twitter share screen

A Tweet for the Tweeps

Before posting a tweet, make the app a little more interactive by placing the Twitter’s character limit — i.e., 240 — and change the TextView count placed on the top right with respect to the number of characters written in the posting TextView.

Write a method onTextChangeListener inside ShareActivity:

fun onTextChangeListener() {
  postEditText.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable) {
      characterLimitTextView.text = "${s.length}/240"
    }

    override fun beforeTextChanged(s: CharSequence, start: Int,
                                   count: Int, after: Int) {
    }

    override fun onTextChanged(s: CharSequence, start: Int,
                               before: Int, count: Int) {
    }
  })
}

This code is handling the character count change logic at runtime.

Furthermore, change the setData() method of ShareActivity by replacing the line that sets the postEditText to be GONE with the following code:

if (user.socialNetwork == SocialNetwork.Twitter) {
  postEditText.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(240))
  onTextChangeListener()
} else {
  postEditText.visibility = View.GONE
}

Here, a character limit is applied on the TextView to stop a user from writing more than 240 characters.

Now, move on to posting a tweet. For that, you’ll write another method:

fun postATweet(message: String) {
  val statusesService = TwitterCore.getInstance().apiClient.statusesService
  val context = this
  statusesService.update(message, null, null, null, null, null, null, null, null)
      .enqueue(object : Callback<Tweet>() {
        override fun success(result: Result<Tweet>) {
          Toast.makeText(context,R.string.tweet_posted,Toast.LENGTH_SHORT).show()
        }

        override  fun failure(exception: TwitterException) {
          Toast.makeText(context,exception.localizedMessage,Toast.LENGTH_SHORT).show()
        }
      })
  postEditText.setText("")
}

Finally, you need to tweak the postButtonAction() method a little bit:

fun postButtonAction() {
  postButton.setOnClickListener { view ->
    if (postEditText.text.toString().isBlank() && user.socialNetwork == SocialNetwork.Twitter) {
      Toast.makeText(this, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
    } else if (user.socialNetwork == SocialNetwork.Facebook) {
      postStatusToFacebook()
    } else {
      postATweet(postEditText.text.toString())
    }
  }
}
 

Now the time has come in which you post your first tweet!

Build and run the app again. Like before, since you’re not saving the authenticated state of the user, you’ll need to login to Twitter again.

After logging in write, say, Hello Twitter from Sharetastic!

Share to Twitter

Then tap on POST and open the Twitter app.

Twitter appYou can finally see your tweet.

Feels Good

Feels good, doesn’t it?

Logging Out of Twitter

Like Facebook, logging out is pretty simple. All you have to do is change the method sendToMainActivity() in ShareActivity to the following:

if (user.socialNetwork == SocialNetwork.Facebook) {
  LoginManager.getInstance().logOut()
} else {
  TwitterCore.getInstance().sessionManager.clearActiveSession()
}
finish()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)

The only change here is that the Twitter session is being cleared.

Once you run the app again, you’ll be able to log out from Twitter as well. :]

Where to Go From Here?

The Final Project for this tutorial can be found in the Download Materials link at the top or bottom of this tutorial. If you try to build the final project, please be sure to add in your own Facebook and Twitter app ID’s and keys.

You now know how to authenticate a user into Facebook and Twitter, post content to each, and log a user out of each.

As was mentioned in the tutorial, in your app you’re going to want to persist the state of the logged in user, so that the user does not have to log in to Facebook or Twitter every time the app runs. Try saving the user state as a challenge, once you’ve worked your way through the tutorial. If the user is logged in, take them right to the share screen.

If you want to explore more about the Facebook SDK and TwitterKit, visit the resources below:

If you have any questions or comments, please let us know in the discussion below!

Contributors

Comments