yongjhih/RetroFacebook

How to convert a newMeRequest() call to use RetroFacebook

loudenvier opened this issue · 4 comments

Sorry for the newbie question, but I'm new to Facebook Graph API and even greener when it comes to RetroFacebook. I'm using Facebook SDK with the provided Login Button, setting the needed read permissions, and just after login I'm issuing a newMeRequest() call to get extra data for the user. I'm stuck converting my code to use RetroFacebook. How could I convert the following code to use RetroFacebook?

    void processLoginSuccess(LoginResult loginResult) {
        // I was trying to use this
        Facebook facebook = Facebook.create(this);
        facebook.me(); // this returns User which does not contain the extra fields I need
        
        // Instead of using Facebook's provided API
        GraphRequest request = GraphRequest.newMeRequest(
                loginResult.getAccessToken(),
                new GraphRequest.GraphJSONObjectCallback() {
                    @Override
                    public void onCompleted(JSONObject object, GraphResponse response) {
                        Log.v(TAG, response.toString());

                        try {
                            String name = object.getString("name");
                            String email = object.getString("email");
                            String birthday = object.getString("birthday"); // 01/31/1980 format
                        } catch (JSONException e) {
                            Log.e(TAG, "unexpected JSON exception", e);
                        }
                    }
                });
        Bundle parameters = new Bundle();
        parameters.putString("fields", "id,name,email,gender,birthday,picture,cover,age_range,locale,about,location");
        request.setParameters(parameters);
        request.executeAsync();
    }

I've included my pointless attempt at using facebook.me()... Just for reference...

I'm setting up the permissions on the FacebookLoginButton like this, and the code works:

        final LoginButton loginButton = (LoginButton)findViewById(R.id.login_button);
        loginButton.setCompoundDrawables(drawable, null, null, null);
        loginButton.setReadPermissions(Arrays.asList(
                "public_profile", "email", "user_birthday", "user_friends", "user_about_me", "user_location"));

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/39519544-how-to-convert-a-newmerequest-call-to-use-retrofacebook?utm_campaign=plugin&utm_content=tracker%2F17798003&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F17798003&utm_medium=issues&utm_source=github).

Hi @loudenvier ,

You can use the following lines to login with needed permissions:

final Facebook facebook = Facebook.create(activity);

loginButton.setOnClickListenter(v -> {
    facebook.logInWithReadPermissions(Arrays.asList("public_profile",
                                         "email",
                                         "user_birthday",
                                         "user_friends",
                                         "user_about_me",
                                         "user_location"))
        .flatMap(login -> facebook.getProfile())
        .subscribe(profile -> {
             System.out.println(profile.name());
             System.out.println(profile.email());
             System.out.println(profile.birthday());
        });
});
ejbp commented

I've tested this example using v4 version and I'm not obtaining any print so I've changed to this code:

    @Override
    protected void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);
        Facebook facebook = Facebook.create(this);
        setContentView(R.layout.activity_home);

        //Facebook Button
        LoginButton button_login_facebook = (LoginButton) findViewById(R.id.button_login_facebook);

        button_login_facebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                facebook.logInWithReadPermissions(Arrays.asList("public_profile",
                        "email",
                        "user_birthday"))
                        .flatMap(
                                loginResult -> {
                                    Log.d("HomeActivity", "LoginResult: " + loginResult);
                                    return null;
                                },
                                throwable -> {
                                    Log.d("HomeActivity", "Error: " + throwable);
                                    return null;
                                },
                                () -> {
                                    Log.d("HomeActivity", "Completed");
                                    return null;
                                });
            }
        });
    }

but it never prints the result of Log.d("HomeActivity", "LoginResult: " + loginResult); or even Log.d("HomeActivity", "Completed");

I forced an error like removing the facebook activity from manifest and it prints the result of Log.d("HomeActivity", "Error: " + throwable.getMessage()); and it prints the error correctly.

I get this on the log but nothing more:

4-05 17:21:32.047 15867-15867/com.xxxxx D/RetroFacebook: request new: public_profile
04-05 17:21:32.047 15867-15867/com.xxxxx D/RetroFacebook: request new: email
04-05 17:21:32.047 15867-15867/com.xxxxx D/RetroFacebook: request new: user_birthday

Any ideia?

Thanks in advance.

Hi @ejbp,

Do you override onActivityResult() like this:

public class XXXActivity extends Activity {
    // ..
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        facebook.onActivityResult(requestCode, resultCode, data);
    }
}

I think I forgot to write it on README, sorry.

ejbp commented

Yes. That was the issue but now I'm facing two issues:

---- UPDATE ------
1.
State:
. My facebook App is not yet authorised to access to my data
. First time I run the app (after installation or after logout)

When I run the app with this code (if I'm not logged):

package com.xxx;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import java.util.Arrays;

import retrofacebook.Facebook;

public class MainActivity extends AppCompatActivity {
    Facebook facebook;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        facebook = Facebook.create(this);
        setContentView(R.layout.activity_main);

        //Facebook Button
        Button button_login_facebook = (Button) findViewById(R.id.button_login_facebook);
        button_login_facebook.setOnClickListener(view -> {
            facebook.logInWithReadPermissions(Arrays.asList("public_profile",
                    "email"))
                    .flatMap(login -> facebook.getProfile())
                    .subscribe(profile -> {
                        Log.d("MainActivity", "Profile: " + profile);
                        Log.d("MainActivity", "Name: " + profile.name());
                        Log.d("MainActivity", "Email: " + profile.email());
                    },
                    throwable -> {
                        Log.d("MainActivity", "Error: " + throwable);

                    },
                    () -> {
                        Log.d("MainActivity", "Completed");
                    });
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        facebook.onActivityResult(requestCode, resultCode, data);
        Log.d("MainActivity", "I'm onActivityResult");
    }

}

The log result after I click the button is:

04-06 14:02:13.396 21569-21569/com.xxx D/RetroFacebook: request new: public_profile
04-06 14:02:13.396 21569-21569/com.xxx D/RetroFacebook: request new: email
04-06 14:02:13.444 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onCreate +
04-06 14:02:13.454 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onCreate -
04-06 14:02:13.454 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart +
04-06 14:02:13.462 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart -
04-06 14:02:13.462 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onResume +
04-06 14:02:13.464 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onResume -
04-06 14:04:54.385 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart +
04-06 14:04:54.385 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart -
04-06 14:04:54.387 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart +
04-06 14:04:54.387 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onStart -
04-06 14:04:54.952 21569-21569/com.xxx D/MainActivity: I'm onActivityResult
04-06 14:04:54.952 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onResume +
04-06 14:04:54.959 21569-21569/com.xxx I/Instrumentation: [AppLaunch] activity.onResume -

Meaning that the callbacks of subscription are never called.

2.
Though, if I click on the button again or enter the app after, meaning after I'm logged, the result is:

04-06 14:06:39.055 21569-21569/com.xxx D/RetroFacebook: no new permissions
04-06 14:06:39.071 21569-21569/com.xxx D/RetroFacebook: no new permissions
04-06 14:06:39.071 21569-21569/com.xxx D/RetroFacebook: no new permissions
04-06 14:06:39.072 21569-21569/com.xxx D/RetroFacebook: bundle
04-06 14:06:39.072 21569-21569/com.xxx D/RetroFacebook: graphRequest GET
04-06 14:06:39.072 21569-21569/com.xxx D/RetroFacebook: onSubscribe
04-06 14:06:39.358 21569-21569/com.xxx D/RetroFacebook: Profiles: {"name":"My Name","id":"11111111111111111"} 
04-06 14:06:39.379 21569-21569/com.xxx D/RetroFacebook: end
04-06 14:06:39.381 21569-21569/com.xxx D/MainActivity: Profile: Profile{id= 11111111111111111, name=My Name, firstName=null, middleName=null, lastName=null, gender=null, locale=null, languages=null, link=null, ageRange=null, thirdPartyId=null, installed=null, timeZone=null, updatedTime=null, verified=null, bio=null, birthday=null, cover=null, currency=null, education=null, email=null, hometown=null, location=null, political=null, favoriteAthletes=null, favoriteTeams=null, picture=null, quotes=null, relationshipStatus=null, religion=null, website=null, work=null}
04-06 14:06:39.381 21569-21569/com.xxx D/MainActivity: Name: My Name 
04-06 14:06:39.382 21569-21569/com.xxx D/MainActivity: Error: java.lang.NullPointerException: println needs a message

It means that it doesn't give me the email value, having in mind that in the authorisation facebook window I gave access to public profile and email.

After digging in your code, specifically in the logInWithReadPermissions function and getProfile I didn't find code to get the 'GraphRequest.newMeRequest' that is now needed to get all the user info, meaning that, If I add this code in the subscribe callback I'm now able to see all the user info that I've requested, email included:

facebook.logInWithReadPermissions(Arrays.asList("public_profile",
                    "email"))
                    .flatMap(login -> facebook.getProfile())
                    .subscribe(profile -> {
                        Log.d("MainActivity", "Profile: " + profile);

                        if(profile.name()!=null)
                            Log.d("MainActivity", "Name: " + profile.name());

                        if(profile.email()!=null)
                            Log.d("MainActivity", profile.email());

                        //THIS IS THE MISSING CODE
                        GraphRequest request =   GraphRequest.newMeRequest(
                            AccessToken.getCurrentAccessToken(),
                            (jsonObject, response) -> {
                                // Application code for user
                                Log.d("MainActivity", "JSON Object: " + jsonObject.toString());
                                Log.d("MainActivity", "Response from facebook: " + response.toString());
                            });

                        Bundle parameters = new Bundle();
                        parameters.putString("fields", "id,name,email,gender,birthday");
                        request.setParameters(parameters);
                        request.executeAsync();
                        //END OF MISSING CODE

                    },
                    throwable -> {
                        Log.d("MainActivity", "Error: " + throwable);

                    },
                    () -> {
                        Log.d("MainActivity", "Completed");
                    });

Though, this is not the point of your lib that intents to abstract this.

Conclusion

  1. It's not explained yet, why, when the user is not logged, the subscription is not being called
  2. Probably it's missing code to get all the user info