Facebook onCompleted is called twice - android

I did the following:
#Override
public void onResume() {
super.onResume();
// For scenarios where the main activity is launched and user
// session is not null, the session state change notification
// may not be triggered. Trigger it if it's open/closed.
Session session = Session.getActiveSession();
if (session != null && (session.isOpened() || session.isClosed())) {
onSessionStateChange(session, session.getState(), null);
}
uiHelper.onResume();
}
and
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (state.isOpened()) {
makeMeRequest(session);
} else if (state.isClosed()) {
}
}
and
private void makeMeRequest(final Session session) {
Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (session == Session.getActiveSession()) {
if (user != null) {
log.d("creating fragment"); //<<<<<<<<<<<<<<<
//creating a fragment when the request is complete
.....
}
}
if (response.getError() != null) {
}
}
});
request.executeAsync();
}
Please read the comment of the first code clause: as suggested by Facebook, that code works because without it, the fragment is not created in certain scenarios even though I'm logged in, but with this code, onCompleted is called twice and I get an exception. see my logging in the 3rd code clause: log.d("creating fragment") - I see it twice before the exception occurred.
Any idea what am I missing?
p.s.: I have a main activity that calls a fragment where the user can login to facebook

Session session = Session.getActiveSession();
if (session != null && (session.isOpened() || session.isClosed())) {
onSessionStateChange(session, session.getState(), null);
}
don't use above code in onresume(),
Activity normally called first oncreate() and then onresume().so that it's called twice.
please check it.

Related

uploading pictures to facebook using the facebook sdk for android

I am trying to upload a picture to facebook using the sdk for android. When i run the code my app crashes. Can someone help me. I am not too sure how to use the sdk. Is there another way to upload pictures?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.newUploadPhotoRequest(session, bm, new Request.Callback() {
#Override
public void onCompleted(Response response)
{
// TODO Auto-generated method stub
if (isFinishing()) {
return;
}
if (response.getError() != null) { // [IF Failed Posting]
Log.d("", "photo upload problem. Error="+response.getError() );
} // [ENDIF Failed Posting]
Object graphResponse = response.getGraphObject().getProperty("id");
if (graphResponse == null || !(graphResponse instanceof String) ||
TextUtils.isEmpty((String) graphResponse)) { // [IF Failed upload/no results]
Log.d("", "failed photo upload/no response");
} else { // [ELSEIF successful upload]
fbPhotoAddress = "https://www.facebook.com/photo.php?fbid=" +graphResponse;
}
}
} ).executeAsync();
}
}
});
}
}

Why can't I see access token in my logcat?

I am trying to see access_token in logcat but it's now showing up. Why?
private void updateUI() {
Session session = Session.getActiveSession();
Log.i("access_token", session.getAccessToken());
if ( user != null) {
profilePictureView.setProfileId(user.getId());
greeting.setText(getString(R.string.hello_user, user.getFirstName()));
accessToken.setText(session.getAccessToken());
} else {
profilePictureView.setProfileId(null);
greeting.setText(null);
accessToken.setText(null);
}
}

How to share the status for FB in Android programatically

I want to share the text/image programatically from my app on facebook.How should I proceed for that.After lots of googling I found lots of sample apps but as the latest FB SDK is deprecated those APIs it is hard to find the way using new SDK.Please help me out for this issue.
private void publishFeedDialog() {
Bundle params = new Bundle();
params.putString("name", "Facebook SDK for Android");
params.putString("caption", "Build great social apps and get more installs.");
params.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
params.putString("link", "https://developers.facebook.com/android");
params.putString("picture", "https://raw.github.com/fbsamples/ios-3.x- howtos/master/Images/iossdk_logo.png");
WebDialog feedDialog = (
new WebDialog.FeedDialogBuilder(getApplicationContext(),
Session.getActiveSession(),
params))
.setOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(Bundle values,
FacebookException error) {
if (error == null) {
// When the story is posted, echo the success
// and the post Id.
final String postId = values.getString("post_id");
if (postId != null) {
Toast.makeText(getApplicationContext(),
"Posted story, id: "+postId,
Toast.LENGTH_SHORT).show();
} else {
// User clicked the Cancel button
Toast.makeText(getApplicationContext(),
"Publish cancelled",
Toast.LENGTH_SHORT).show();
}
} else if (error instanceof FacebookOperationCanceledException) {
// User clicked the "x" button
Toast.makeText(getApplicationContext(),
"Publish cancelled",
Toast.LENGTH_SHORT).show();
} else {
// Generic, ex: network error
Toast.makeText(getApplicationContext(),
"Error posting story",
Toast.LENGTH_SHORT).show();
}
}
})
.build();
feedDialog.show();
}
This is what i get for fb API 3.5 doc & which I have tried but it is crashing the app by saying session is null.
Here your session is null because you have not started it yet.
You have to start your session after login.
You can achieve this by using
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
});
For more information try going through the tutorials from http://developers.facebook.com/docs/android/scrumptious/authenticate/. These are really helpful.
Here is how I implemented --
This class is used to do initial stuffs to facebook
LoginFacebookClass
/**
* for integrating facebook in your app..
* Firstly import FacebookSDK lib project and add in your project as lib project.
* then
* create an instance of this class
* and, then call the facebook login method by passing reference of your activity and true, if you want to fetch data and, false if you want to share data on faceboko
* Please do whatever you want in the interface callback methods
* implemented by this class
*
*
* Note: Please write a line exactly in your activity's on activity result as
* -- Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
* here, 'Session' is Class of Facebook.
* 'this' is reference of your activity
*/
public class FacebookLoginClass implements FB_Callback
{
Context context;
FBImPlmentation fbImpl;
String mImageURLString = "", mPhotoTypeString = "";
// private FBBean userDataBean;
/**
* constructor for FacebookLoginClass
* #param con : context of activity
* #param string
* #param mImageURLString2
*/
public FacebookLoginClass(Context con)
{
this.context = con;
fbImpl = FBImPlmentation.getInstance(context, this);
}
public FacebookLoginClass(Context con, String imageURLString, String photoType)
{
this.context = con;
fbImpl = FBImPlmentation.getInstance(context, this);
mImageURLString = imageURLString;
mPhotoTypeString = photoType;
}
/**
* method for initiating facebook Login
* #param isDataFetch : true for fetching user data, false for sharing on wall
*/
public void facebookLogin(boolean isDataFetch)
{
fbImpl.CheckSession(isDataFetch);
}
/**
* method for facebookLogout
*/
public void facebookLogout()
{
fbImpl.fbLogout();
}
#Override
public void onLogin(Session s)
{
fbImpl.getDataFromFB(s);
}
#Override
public void onLoginForShareData()
{
Log.e("facebook.", "True in..........");
Bundle postParams = new Bundle();
postParams.putString("name", "");
postParams.putString("caption", "");
postParams.putString("description", " Android, share your pics and videos");
if (mPhotoTypeString.equalsIgnoreCase("photo"))
{
postParams.putString("picture", mImageURLString);
}
else
{
postParams.putString("link", "");
}
fbImpl.publishFeedDialog(postParams);
}
#Override
public void onAuthFailiure()
{
}
#Override
public void onUserData(FBBean fbUserDataBean)
{
try
{
if (BejoelUtility.isNetworkAvailable(context))
{
String imageURLString = "http://graph.facebook.com/" + fbUserDataBean.getUserID() + "/picture?type=large";
new FacebookTwitterLoginAsyncTask(context, fbUserDataBean.getFirstNAme(), fbUserDataBean.getLastName(),
fbUserDataBean.getMailId(), fbUserDataBean.getUserBday(), fbUserDataBean.getUserSex(), "", "", imageURLString,
fbUserDataBean.getAccessToken(), "facebook").execute();
}
else
{
BejoelUtility.showMsgDialog(context, context.getString(R.string.app_name), context.getString(R.string.no_internet));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
#Override
public void onPost(boolean postStatus)
{
// TODO Auto-generated method stub
}
#Override
public void onFriendRequest(boolean shareAppStatus)
{
// TODO Auto-generated method stub
}
#Override
public void onLogout(boolean status)
{
// TODO Auto-generated method stub
}
}
This class interact with facebook
public class FBImPlmentation
{
public static List<String> READ_PERMISSIONS = Arrays.asList("email");
public List<String> WRITE_PERMISSIONS = Arrays.asList("publish_actions");
private static FBImPlmentation fbImpl;
private FB_Callback mInterface;
private static Activity activity;
boolean isDataFetch=false;
private String mAccessTokenString = "";
/**
* constructor for facebookImplementation
* #param con :context of activity via FacebookLogin Class
* #param mInterface : refrence of class implementing FB_Callback interface..as in our case,
* it is refrence of FacebookLogin Class
* #return : instance of FBImplementation
*/
public static FBImPlmentation getInstance(Context con, FB_Callback mInterface)
{
activity = (Activity) con;
if (fbImpl == null)
fbImpl = new FBImPlmentation();
fbImpl.mInterface = mInterface;
return fbImpl;
}
/**
* method to be called for facebook Logout
*/
public void fbLogout()
{
if (Session.getActiveSession() != null)
{
Session.getActiveSession().closeAndClearTokenInformation();
}
Session.setActiveSession(null);
mInterface.onLogout(true);
}
/**
* method for checking session.
* if session is not open, then open a new session.
* If session is already open then..just call the fbcallback onlogin method
* #param isDataFetch2
*/
public void CheckSession(boolean isDataFetch2)
{
fbImpl.isDataFetch= isDataFetch2;
Session s = Session.getActiveSession();
if (s != null && s.isOpened())
{
if(isDataFetch)
mInterface.onLogin(s);
else
mInterface.onLoginForShareData();
mAccessTokenString = s.getAccessToken();
}
else
{
Session.openActiveSession(activity, true, mFBCallback);
}
}
// Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity, permissions);
Session.StatusCallback mFBCallback = new Session.StatusCallback()
{
// call method is always called on session state change
#Override
public void call(Session session, SessionState state, Exception exception)
{
if (session.isOpened())
{
List<String> permissions = session.getPermissions();
if (!isSubsetOf(READ_PERMISSIONS, permissions))
{
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity, READ_PERMISSIONS);
session.requestNewReadPermissions(newPermissionsRequest);
return;
}
else if(isDataFetch)
{
mInterface.onLogin(session);
}
else
{
mInterface.onLoginForShareData();
}
}
}
};
/**
* method for fetching the user data
* #param session : it takes the refrence of active session
*/
public void getDataFromFB(Session session)
{
Request.executeMeRequestAsync(session, new Request.GraphUserCallback()
{
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response)
{
if (user != null)
{
// code to retrieve user's data and pass to signup fragment
FBBean fbUserDataBean = new FBBean();
if (mAccessTokenString != null)
fbUserDataBean.setAccessToken(mAccessTokenString);
else
{
fbUserDataBean.setAccessToken("");
}
if (user.getUsername() != null && !(user.getUsername().equals(null)))
fbUserDataBean.setUserName(user.getUsername());
else
{
fbUserDataBean.setUserName("");
}
if (user.getFirstName() != null && !(user.getFirstName().equals(null)))
fbUserDataBean.setFirstNAme(user.getFirstName());
else
{
fbUserDataBean.setFirstNAme("");
}
if (user.getLastName() != null && !(user.getLastName().equals(null)))
fbUserDataBean.setLastName(user.getLastName());
else
{
fbUserDataBean.setLastName("");
}
if (user.getBirthday() != null && !(user.getBirthday().equals(null)))
fbUserDataBean.setUserBday(user.getBirthday());
else
{
fbUserDataBean.setUserBday("");
}
if (user.asMap().get("gender") != null)
{
fbUserDataBean.setUserSex(user.asMap().get("gender").toString());
}
else
{
fbUserDataBean.setUserSex("");
}
if (user.getProperty("email") != null && !(user.getProperty("email").equals(null)))
fbUserDataBean.setMailId(user.getProperty("email").toString());
else
{
fbUserDataBean.setMailId("");
}
if (user.getId() != null && !(user.getId().equals(null)))
fbUserDataBean.setUserID(user.getId());
else
{
fbUserDataBean.setUserID("");
}
// String[] sportsArray = FacebookUtils.getSportsArray(user.getInnerJSONObject());
// if (sportsArray != null && !(sportsArray.equals(null)))
// fbUserDataBean.setSportsname(sportsArray);
mInterface.onUserData(fbUserDataBean);
}
}
});
}
private boolean isSubsetOf(Collection<String> subset, Collection<String> superset)
{
for (String string : subset)
{
if (!superset.contains(string))
{
return false;
}
}
return true;
}
/**
* method for publishing posts
*/
public void publishFeedDialog(Bundle postParams)
{
Session s = Session.getActiveSession();
List<String> permissions = s.getPermissions();
if (!isSubsetOf(WRITE_PERMISSIONS, permissions))
{
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity,
WRITE_PERMISSIONS);
s.requestNewPublishPermissions(newPermissionsRequest);
return;
}
// Bundle postParams = new Bundle();
// postParams.putString("name", "Facebook SDK for Android");
// postParams.putString("caption", "Build great social apps and get more installs.");
// postParams.putString("description", "Video by Lata manadjahgkfdjhaskjd akhgfkjashfkjash");
// postParams.putString("link", "");
// postParams.putString("picture", "");
WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(activity, Session.getActiveSession(), postParams))
.setOnCompleteListener(new OnCompleteListener()
{
#Override
public void onComplete(Bundle values, FacebookException error)
{
if (error == null)
{
// When the story is posted, echo the success
// and the post Id.
final String postId = values.getString("post_id");
if (postId != null)
{
mInterface.onPost(true);
}
else
{
// User clicked the Cancel button
mInterface.onPost(false);
}
}
else
if (error instanceof FacebookOperationCanceledException)
{
// User clicked the "x" button
// Toast.makeText(MainActivity.this.getApplicationContext(), "Publish cancelled",
// Toast.LENGTH_SHORT).show();
mInterface.onPost(false);
}
else
{
// Generic, ex: network error
// Toast.makeText(MainActivity.this.getApplicationContext(), "Error posting story",
// Toast.LENGTH_SHORT).show();
mInterface.onAuthFailiure();
}
}
}).build();
feedDialog.show();
}
}

Facebook Session cancel dialog

I'm developping an app that uses this : https://developers.facebook.com/docs/android/native-login/
I have followed the Facebook dev tutorial, so basically I have the session check, it opens the dialog, and I'm trying to get the Cancel event (when the user cancel the facebook dialog) but I have no method on this.
Maybe you can help.
Thanks
EDIT: Actually, even if I click the cancel button, I still receive the GraphUser correctly. That's weird.
With Android SDK 3.5, I got the cancel event via exception, if the state change callback with instance of FacebookOperationCanceledException or FacebookAuthorizationException, its an cancel event:
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (exception instanceof FacebookOperationCanceledException || exception instanceof FacebookAuthorizationException) {
// Cancelled by user, show alert
new AlertDialog.Builder(this).setTitle(R.string.cancelled).setMessage(R.string.permission_not_granted).setPositiveButton(R.string.ok, null).show();
} else {
Session session = Session.getActiveSession();
if ((session != null && session.isOpened())) {
// Session ready
}
}
}
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
It works just great
Add a Session.StatusCallback to your open request where you can check the SessionState.
new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
//check state
}
};
Check out this question.

Method is called multiple times but called only once

I implemented Facebook SDK in my Android application. I am using the login function of the SDK. What i am trying to do is the following :
When MainActivity starts, check if there is an active session
If there isn't, give the user the chance to login into facebook
If there is, user has to be redirected to an other Activity (let's call this : HomeActivity).
When my application starts, it starts the MainActivity. My onCreate() method looks like this :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.app = (ApplicationClass)getApplicationContext();
app.setUiHelper(new UiLifecycleHelper(this, callback));
uiHelper = app.getUiHelper();
uiHelper.onCreate(savedInstanceState);
if(this.app.getLoggedIn()) {
setContentView(R.layout.login);
startLoggingIn(); // <-- Makes login button invisible and starts spinner
login();
} else {
setContentView(R.layout.login);
}
}
ApplicationClass is a class where i set all kind of information that can be used throughout the application lifecycle. It doesn't really matter but i thought i include it in the example.
So when MainActivity starts, it should call login() method, which looks like this :
public void login() {
logging_in = true;
Log.i(TAG, "Loggin in");
synchronized (this) {
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (Session.getActiveSession().isOpened()) {
// make request to the /me API
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) { // User is logged in
app.setUser(user);
app.setLoggedIn(true);
// Redirect user to the HomeActivity
Intent intent = new Intent(getBaseContext(), HomeActivity.class);
startActivity(intent);
}
}
});
}
}
});
logging_in = false;
}
}
And finally, my callback for Facebook session looks like this :
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (state.isOpened()) {
synchronized (this) {
if( ! logging_in ) {
login();
}
}
} else if (state.isClosed()) {
setContentView(R.layout.login);
}
}
It does it all well, except the login() method gets called about many times. The output in my log is :
Why does it get called so many times? It obviously make sure the HomeActivity intent is started multiple times. I can't figure out why.
Solution
Changed my Session.StateCallback a little bit. It now looks like this :
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (state.isOpened()) {
if(state == SessionState.OPENED_TOKEN_UPDATED) {
Log.i(TAG, "OPENED_TOKEN_UPDATED");
login();
} else if (state == SessionState.OPENED) {
if(app.getUser() != null) {
// Redirect user to the HomeActivity
Intent intent = new Intent(getBaseContext(), HomeActivity.class);
startActivity(intent);
} else {
login();
}
}
} else if (state.isClosed()) {
if(state == SessionState.CLOSED_LOGIN_FAILED) {
Log.i(TAG, "CLOSED_LOGIN_FAILED");
setContentView(R.layout.login);
} else if(state == SessionState.CLOSED) {
Log.i(TAG, "CLOSED");
//setContentView(R.layout.login);
}
}
}
Its most likely because you're calling login from onSessionState changed.
When you login what do think is going to happen to the session, it's going to change right.
And when it changes it calls onSessionState change and you call login.
I would expect that to loop infinitely but it seems Facebook have done some handling for this.
I also faced the same problem .. I just changed my activity result code . And it worked ..

Categories

Resources