Firstly, I like to a have single
Activity
(let's call it BaseFacebookActivity
) that has all my Facebook methods in it and which Activities that do Facebook operations are to extend. Don't forget the onActivityResult(...)
method!, as follows:
public abstract class BaseFacebookActivity
extends Activity
{
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (Session.getActiveSession() != null)
Session.getActiveSession().onActivityResult(
this,
requestCode,
resultCode,
data);
}
// other methods to follow
}
Secondly, let's define an interface which will help us report back to the user when an attempt to open a Facebook session has been successful or not, as follows:
public interface FacebookConnectHandler
{
/** Method to call when the user's Facebook account
* was connected to
* and a Facebook session was opened successfully.*/
public void onSuccess();
/** Method to call when the user's Facebook account
* was not connected to
* or a Facebook session was not opened successfully.*/
public void onFailure();
}
Thirdly and finally, a method to put in your BaseFacebookActivity
which will connect to the user's Facebook account and open a Facebook session, as follows:
private void connectFacebookAccount(
final FacebookConnectHandler handler)
{
// safety check
if (!isActiveNetworkConnected())
{
handler.onFailure();
return;
}
// check whether the user already has an active session
// and try opening it if we do
// (note: making a Session.openActiveSessionFromCache(...) call
// instead of simply checking whether the active session is opened
// because of a bug in the Facebook sdk
// where successive calls to update a token
// (requesting additional permissions etc)
// don't result in a session callback)
if (Session.getActiveSession() != null
&& Session.openActiveSessionFromCache(this) != null)
{
handler.onSuccess();
return;
}
// initialise the session status callback
Session.StatusCallback callback = new Session.StatusCallback()
{
@Override
public void call(
Session session,
SessionState state,
Exception exception)
{
// safety check
if (isFinishing())
return;
// check session state
if (state.equals(SessionState.CLOSED)
|| state.equals(SessionState.CLOSED_LOGIN_FAILED))
{
clearFacebookInfoFromSharedPreferences();
// specific action for when the session is closed
// because an open-session request failed
if (state.equals(SessionState.CLOSED_LOGIN_FAILED))
{
cancelProgressDialog();
handler.onFailure();
}
}
else if (state.equals(SessionState.OPENED))
{
cancelProgressDialog();
saveFacebookInfoInSharedPreferences(
session.getAccessToken(),
session.getExpirationDate());
showToast("Succeeded connecting to Facebook");
handler.onSuccess();
}
}
};
// make the call to open the session
showProgressDialog("Connecting to Facebook...");
if (Session.getActiveSession() == null
&& getSharedPreferences().contains("facebookAccessToken")
&& getSharedPreferences().contains("facebookAccessTokenExpires"))
{
// open a session from the access token info
// saved in the app's shared preferences
String accessTokenString = getSharedPreferences().getString(
"facebookAccessToken",
"");
Date accessTokenExpires = new Date(getSharedPreferences().getLong(
"facebookAccessTokenExpires",
0));
AccessToken accessToken = AccessToken.createFromExistingAccessToken(
accessTokenString,
accessTokenExpires,
null,
null,
null);
Session.openActiveSessionWithAccessToken(this, accessToken, callback);
}
else
// open a new session, logging in if necessary
Session.openActiveSession(this, true, callback);
}
Done! In the next Blog post I'll show how to use this connectFacebookAccount(...)
method prior to making a Facebook API request like posting to the user's feed.
16 comments:
Thanks my friend for this interesting post, I've been looking desperately for such a tutorial!
I have a little question though:
Where are these functions defined?
isActiveNetworkConnected()
clearFacebookInfoFromSharedPreferences()
cancelProgressDialog()
saveFacebookInfoInSharedPreferences(session.getAccessToken(), session.getExpirationDate())
showProgressDialog("Connecting to Facebook...")
getSharedPreferences()
Thanks again my friend!
Hi Zakaria, these are nice-to-have methods which are not essential to the core of the post (working with the Facebook SDK) and which I abstracted away from the tutorial to keep the tutorial focused and simple(r).
Thank you such Needed tutorial of Facebook 3.0...
I have a Little question.
if (Session.getActiveSession() == null
&& getSharedPreferences().contains("facebookAccessToken")
&& getSharedPreferences().contains("facebookAccessTokenExpires"))
{
// open a session from the access token info
// saved in the app's shared preferences
String accessTokenString = getSharedPreferences().getString(
"facebookAccessToken",
"");
Date accessTokenExpires = new Date(getSharedPreferences().getLong(
"facebookAccessTokenExpires",
0));
I get the error to method getSharedPreferences()
Hi Adil,
Thanks... for Tutorial.
but I have not any idea of this Two
"facebookAccessToken"
"facebookAccessTokenExpires"
token value so, Please tell me token value. Thank you
facebookAccessToken
facebookAccessTokenExpires
Hi all, please note that the tutorial contains methods which you can omit or which are pretty straightforward to write but are outside the scope of the tutorial and would distract from the main purpose of the tutorial which is to demonstrate usage of the new Facebook SDK.
Hello adil,
do you use com.facebook.widget.LoginButton from sdk or a custom button?
Kostas, no, I didn't use the Facebook LoginButton and used a custom button instead.
Hey Adil, very nice example.
I have one question - i saw that you're not check for the token expiry time. what will happen if i get the token info from the shared preferences but it is already expired ?
Hi Adil,Thanks for yout post !
I already made Login an open a Session, but I would like to ask for Publish permissions later in my app, or maybe user don't need it untill next execution. I have my AccessToken saved, can I restore a session with this token and ask for new permissions? Dou you know if there is an easy call to do it? Thank!
Hi Anonymous, I'm not sure if this is what you're after but you might find this useful:
http://adilatwork.blogspot.co.uk/2013/02/facebook-android-sdk-30-requesting.html
Hi Adil,
thanks for tutorial. Also, I am little curious to know why not to use fb loggin button. What are the advantages of this approach over standard login button.
thanks,
Hi vishwas, the main reasons for my not using the fb login button and also the reason for my putting together these "Facebook Android SDK 3.0" Blog posts was because the documentation available at the time was very very poor.
Hey Adil, thanks for the work. This is a great resource to implement a Facebook login auth.
However, is there any possibilities for you to show all the source perhaps on github or whatnot? Just wanna have an extra understanding on the implementation. Great explanation!
Greetings Adil, Nice setup but I have a feeling I found an even better solution, most people wanna use Facebook SDK with Fragments since they can use used with so many things like ViewPagers and ScrollTabs, There are certain doubts I had while trying to interpret your code and develop my Fragments based generic solution based on that...
I created an AbstractFacebookFragment with a UILifecycleHelper without any Views and my code turns to be something like pasted below. Its pretty similar to yours with the exception of the one thing, this Fragment does not have a View, I am expecting all subclass fragments to extend this one and define their own views but what do you think should be done with the LoginButton, I am also using a UILifecycleHelper to reduce some of the things you did in the onActivityResult
package vivz.slidenerd.thefpamapp;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import java.util.Date;
import vivz.slidenerd.utils.NetworkUtils;
/**
* Created by Windows on 28-11-2014.
*/
public abstract class AbstractFacebookFragment extends Fragment {
private UiLifecycleHelper lifecycleHelper;
protected abstract void clearProgressDialog();
protected abstract void clearFacebookInfoFromSharedPreferences();
protected abstract void saveFacebookInfoToSharedPreferences(String accessToken, Date expirationDate);
protected void connectWithFacebook(final FacebookConnectionHandler connectionHandler) {
if (!NetworkUtils.isNetworkAvailable(getActivity())) {
connectionHandler.onFailure();
return;
}
if (Session.getActiveSession() != null
&& Session.openActiveSessionFromCache(getActivity()) != null) {
connectionHandler.onSuccess();
return;
}
Session.StatusCallback callback = new Session.StatusCallback() {
@Override
public void call(Session session, SessionState state, Exception exception) {
if (state.equals(SessionState.CLOSED) || state.equals(SessionState.CLOSED_LOGIN_FAILED)) {
clearFacebookInfoFromSharedPreferences();
if (state.equals(SessionState.CLOSED_LOGIN_FAILED)) {
clearProgressDialog();
connectionHandler.onFailure();
}
} else if (state.equals(SessionState.OPENED)) {
clearProgressDialog();
saveFacebookInfoToSharedPreferences(session.getAccessToken(), session.getExpirationDate());
connectionHandler.onSuccess();
}
onSessionStateChange(session, state, exception);
}
};
}
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleHelper = new UiLifecycleHelper(getActivity(), callback);
}
@Override
public void onResume() {
super.onResume();
lifecycleHelper.onResume();
}
@Override
public void onPause() {
super.onPause();
lifecycleHelper.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
lifecycleHelper.onSaveInstanceState(outState);
}
@Override
public void onStop() {
super.onStop();
lifecycleHelper.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycleHelper.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
lifecycleHelper.onActivityResult(requestCode, resultCode, data);
}
}
Thanks!!!!!! You're my hero!
Post a Comment