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:
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:
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:
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:
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.
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.
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.
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.
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.
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:
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:
After pressing POST, go and check the Facebook app.
Hurray! Your status is posted to Facebook.
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.
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:
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.
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.
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.
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!
Then tap on POST and open the Twitter app.
You can finally see your tweet.
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!
The post Social Network Integration on Android appeared first on Ray Wenderlich.