Question

I would like to use Facebook SDK 3.0 for Android to do some simple Graph requests. As I won't use Fragments, I can't use the samples that are posted in the Facebook developer documentation.

I had some simple Activitys set up already, but they did not work. I've asked questions with bounty here and here. But that did not really help.

In the meantime I have been reading a lot of posts about the Facebook SDK and trying for dozens of hours, but without success. Finally, I found an additional code example on this blog. So I've set up a complete Activity which is to print all friends' hometown to the LogCat.

But this does not work, either. Instead, it asks for the basic permissions (public info + friend list) only and then quits. What am I doing wrong? The key hash, package name and class name for the Facebook app are set and there is nothing interesting printed to LogCat.

package com.my.package;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.Toast;
import com.facebook.*;

public class FBRequest extends Activity {

    private static final String PERMISSION_FRIENDS_HOMETOWN = "friends_hometown";
    private static final String PREFERENCE_ACCESS_TOKEN = "facebookAccessToken";
    private static final String PREFERENCE_EXPIRATION_DATE = "facebookAccessTokenExpires";
    private ProgressDialog mProgress;
    private SharedPreferences mPrefs;

    private void showToast(final String text) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
            }
        });
    }

    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        try {
            startFacebookRequest();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Session session = Session.getActiveSession();
        if (session != null) {
            session.onActivityResult(this, requestCode, resultCode, data);
        }
    }

    public interface FacebookConnectHandler {
        public void onSuccess();
        public void onFailure();
    }

    public void startFacebookRequest() {
        connectToFacebook(new FacebookConnectHandler() {
            @Override
            public void onSuccess() {
                // safety check
                if (isFinishing()) { return; }

                showProgressDialog("Connecting to Facebook ...");

                // check for publish permissions

                final List<String> permissions_required = Arrays.asList(PERMISSION_FRIENDS_HOMETOWN);

                if (Session.getActiveSession().getPermissions() == null || !Session.getActiveSession().getPermissions().containsAll(permissions_required)) {
                    // need to make a Session.openActiveSessionFromCache(...) call
                    // because of a bug in the Facebook sdk
                    // where a second call to get permissions
                    // won't result in a session callback when the token is updated

                    if (Session.openActiveSessionFromCache(FBRequest.this) == null) {
                        showToast("Could not connect to Facebook! (3)");
                        return;
                    }

                    Session.getActiveSession().addCallback(new Session.StatusCallback() {
                        @Override
                        public void call(Session session, SessionState state, Exception exception) {
                            if (exception != null || state.equals(SessionState.CLOSED) || state.equals(SessionState.CLOSED_LOGIN_FAILED)) {
                                // didn't get required permissions

                                session.removeCallback(this);

                                // safety check
                                if (!isFinishing()) {
                                    showToast("Could not connect to Facebook! (4)");
                                }
                            }
                            else if (state.equals(SessionState.OPENED_TOKEN_UPDATED) && session.getPermissions().containsAll(permissions_required)) {
                                // got required permissions

                                session.removeCallback(this);

                                // safety check
                                if (!isFinishing()) {
                                    startFacebookRequest();
                                }
                            }
                        }
                    });

                    Session.getActiveSession().requestNewReadPermissions(new Session.NewPermissionsRequest(FBRequest.this, permissions_required));
                    return;
                }
                startGraphRequest(Session.getActiveSession());
            }


            @Override
            public void onFailure() {
                cancelProgressDialog();
                showToast("Could not connect to Facebook! (1)");
            }
        });
    }

    private void startGraphRequest(Session session) {
        Request.executeGraphPathRequestAsync(session, "me/friends/?access_token="+session.getAccessToken()+"&fields=id,name,hometown&limit=500", new Request.Callback() {
            @Override
            public void onCompleted(Response response) {
                if (response != null) {
                    try {
                        JSONArray jarr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
                        JSONObject entry;
                        StringBuilder backupStr = new StringBuilder();
                        int nExistingEntries = existingEntries.length;
                        for (int i = 0; i < jarr.length(); i++) {
                            entry = jarr.getJSONObject(i);
                            if (!entry.isNull("id") && !entry.isNull("name") && !entry.isNull("hometown")) {
                                System.out.println(entry.getString("hometown"));
                            }
                        }
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                        showToast("Unexpected error!");
                    }
                }
            }
        });
    }

    private void connectToFacebook(final FacebookConnectHandler handler) {

        // 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) {

                if (isFinishing()) { return; }

                // check session state

                if (state.equals(SessionState.CLOSED) || state.equals(SessionState.CLOSED_LOGIN_FAILED)) {

                    clearFacebookSharedPreferences();

                    // 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();

                    saveFacebookSharedPreferences(session.getAccessToken(), session.getExpirationDate().getTime());

                    showToast("Succeeded connecting to Facebook");

                    handler.onSuccess();
                }
            }
        };

        // make the call to open the session

        showProgressDialog("Connecting to Facebook...");

        if (Session.getActiveSession() == null && mPrefs.contains(PREFERENCE_ACCESS_TOKEN) && mPrefs.contains(PREFERENCE_EXPIRATION_DATE)) {
            // open a session from the access token info
            // saved in the app's shared preferences

            String accessTokenString = mPrefs.getString(PREFERENCE_ACCESS_TOKEN, "");

            Date accessTokenExpires = new Date(mPrefs.getLong(PREFERENCE_EXPIRATION_DATE, 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);
        }
    }

    private void saveFacebookSharedPreferences(final String token, final long expiration) {
        if (mPrefs != null) {
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.putString(PREFERENCE_ACCESS_TOKEN, token);
            editor.putLong(PREFERENCE_EXPIRATION_DATE, expiration);
            editor.commit();
        }
    }

    private void clearFacebookSharedPreferences() {
        if (mPrefs != null) {
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.remove(PREFERENCE_ACCESS_TOKEN);
            editor.remove(PREFERENCE_EXPIRATION_DATE);
            editor.commit();
        }
    }

    private void showProgressDialog(final String text) {
        mProgress = ProgressDialog.show(getApplicationContext(), "Facebook", text, true, false);
    }

    private void cancelProgressDialog() {
        if (mProgress != null) {
            if (mProgress.isShowing()) {
                mProgress.dismiss();
            }
            mProgress = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelProgressDialog();
    }

}

Thanks in advance!

Edit: The code did work, but I had not called setContentView() and the Activity's finish() was called in one error case. This is why one was not able to see the second request for (extended) permissions.

Was it helpful?

Solution

The above code is working fine except small changes I did i.e while showing progress dialog its giving exception window bad token for this I have changed context. and I also commented one line that is not used 'existingEntries'.

I am able to login and app asked permission for access friends home town access. I can see friend ids and with their home towns.

Updated Working version:

package com.example.options;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.facebook.AccessToken;
import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.Session.Builder;
import com.facebook.Session.NewPermissionsRequest;
import com.facebook.Session.OpenRequest;
import com.facebook.SessionLoginBehavior;
import com.facebook.SessionState;

public class FBRequest extends Activity {

    private static final String PERMISSION_FRIENDS_HOMETOWN = "friends_hometown";
    private static final String PREFERENCE_ACCESS_TOKEN = "facebookAccessToken";
    private static final String PREFERENCE_EXPIRATION_DATE = "facebookAccessTokenExpires";
    private ProgressDialog mProgress;
    private SharedPreferences mPrefs;

    private void showToast(final String text) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
            }
        });
    }

    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        try {
            startFacebookRequest();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(resultCode == RESULT_OK && requestCode == Session.DEFAULT_AUTHORIZE_ACTIVITY_CODE)
        {
            Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
            Session session = Session.getActiveSession(); 

            if (session != null && !session.isClosed()) 
            {
                startFacebookRequest();
            }
        }
    }

    public interface FacebookConnectHandler {
        public void onSuccess();
        public void onFailure();
    }

    public void startFacebookRequest() {
        connectToFacebook(new FacebookConnectHandler() {
            @Override
            public void onSuccess() {
                // safety check
                if (isFinishing()) { return; }

                showProgressDialog("Connecting to Facebook ...");

                // check for publish permissions

                final List<String> permissions_required = Arrays.asList(PERMISSION_FRIENDS_HOMETOWN);

                if (Session.getActiveSession().getPermissions() == null || !Session.getActiveSession().getPermissions().containsAll(permissions_required)) {
                    // need to make a Session.openActiveSessionFromCache(...) call
                    // because of a bug in the Facebook sdk
                    // where a second call to get permissions
                    // won't result in a session callback when the token is updated

                    if (Session.openActiveSessionFromCache(FBRequest.this) == null) {
                        showToast("Could not connect to Facebook! (3)");
                        return;
                    }

                    Session.getActiveSession().addCallback(new Session.StatusCallback() {
                        @Override
                        public void call(Session session, SessionState state, Exception exception) {
                            if (exception != null || state.equals(SessionState.CLOSED) || state.equals(SessionState.CLOSED_LOGIN_FAILED)) {
                                // didn't get required permissions

                                session.removeCallback(this);

                                // safety check
                                if (!isFinishing()) {
                                    showToast("Could not connect to Facebook! (4)");
                                }
                            }
                            else if (state.equals(SessionState.OPENED_TOKEN_UPDATED) && session.getPermissions().containsAll(permissions_required)) {
                                // got required permissions

                                session.removeCallback(this);

                                // safety check
                                if (!isFinishing()) {
                                    startFacebookRequest();
                                }
                            }
                        }
                    });

                    NewPermissionsRequest req = new Session.NewPermissionsRequest(FBRequest.this, permissions_required);
                    req.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO);
                    Session.getActiveSession().requestNewReadPermissions(req);
                    return;
                }
                startGraphRequest(Session.getActiveSession());
            }


            @Override
            public void onFailure() {
                cancelProgressDialog();
                showToast("Could not connect to Facebook! (1)");
            }
        });
    }

    private void startGraphRequest(Session session) {
        Request.executeGraphPathRequestAsync(session, "me/friends/?access_token="+session.getAccessToken()+"&fields=id,name,hometown&limit=500", new Request.Callback() 
        {
            @Override
            public void onCompleted(Response response) {
                if (response != null) {
                    try {
                        JSONArray jarr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
                        JSONObject entry;
                        StringBuilder backupStr = new StringBuilder();
//                        int nExistingEntries = existingEntries.length;
                        for (int i = 0; i < jarr.length(); i++) {
                            entry = jarr.getJSONObject(i);
                            if (!entry.isNull("id") && !entry.isNull("name") && !entry.isNull("hometown")) {
                                System.out.println(entry.getString("hometown"));
                            }
                        }
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                        showToast("Unexpected error!");
                    }

                    showToast("Friends list populated");
                    cancelProgressDialog();
                }
            }
        });
    }

    private void connectToFacebook(final FacebookConnectHandler handler) {

        // 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) {

                if (isFinishing()) { return; }

                // check session state

                if (state.equals(SessionState.CLOSED) || state.equals(SessionState.CLOSED_LOGIN_FAILED)) {

                    clearFacebookSharedPreferences();

                    // 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();

                    saveFacebookSharedPreferences(session.getAccessToken(), session.getExpirationDate().getTime());

                    showToast("Succeeded connecting to Facebook");

                    handler.onSuccess();
                }
            }
        };

        // make the call to open the session

        showProgressDialog("Connecting to Facebook...");

        if (Session.getActiveSession() == null && mPrefs.contains(PREFERENCE_ACCESS_TOKEN) && mPrefs.contains(PREFERENCE_EXPIRATION_DATE)) {
            // open a session from the access token info
            // saved in the app's shared preferences

            String accessTokenString = mPrefs.getString(PREFERENCE_ACCESS_TOKEN, "");

            Date accessTokenExpires = new Date(mPrefs.getLong(PREFERENCE_EXPIRATION_DATE, 0));

            AccessToken accessToken = AccessToken.createFromExistingAccessToken(accessTokenString, accessTokenExpires, null, null, null);

            Session.openActiveSessionWithAccessToken(this, accessToken, callback);
        }
        else {
            // open a new session, logging in if necessary
            OpenRequest op = new Session.OpenRequest(this);

            op.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO);
            op.setCallback(null);

            List<String> permissions = new ArrayList<String>();
            permissions.add(PERMISSION_FRIENDS_HOMETOWN);
            op.setPermissions(permissions);

            Session session = new Builder(this).build();
            Session.setActiveSession(session);
            session.openForRead(op);
        }
    }

    private void saveFacebookSharedPreferences(final String token, final long expiration) {
        if (mPrefs != null) {
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.putString(PREFERENCE_ACCESS_TOKEN, token);
            editor.putLong(PREFERENCE_EXPIRATION_DATE, expiration);
            editor.commit();
        }
    }

    private void clearFacebookSharedPreferences() {
        if (mPrefs != null) {
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.remove(PREFERENCE_ACCESS_TOKEN);
            editor.remove(PREFERENCE_EXPIRATION_DATE);
            editor.commit();
        }
    }

    private void showProgressDialog(final String text) {
        cancelProgressDialog();
        mProgress = ProgressDialog.show(FBRequest.this, "Facebook", text, true, false);
    }

    private void cancelProgressDialog() {
        if (mProgress != null) {
            if (mProgress.isShowing()) {
                mProgress.dismiss();
            }
            mProgress = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelProgressDialog();
    }

}

Logcat:

......
......
03-11 18:57:26.781: I/System.out(6729): {"id":"10555075614xxxx","name":"Khammam"}
03-11 18:57:26.781: I/System.out(6729): {"id":"11042167564xxxx","name":"Warangal, India"}
03-11 18:57:26.789: I/System.out(6729): {"id":"11042167564xxxx","name":"Warangal, India"}
03-11 18:57:26.796: I/System.out(6729): {"id":"13074615695xxxx","name":"Jaggayyapet, India"}
03-11 18:57:26.812: I/System.out(6729): {"id":"12530386417xxxx","name":"Kodada, India"}
03-11 18:57:26.812: I/System.out(6729): {"id":"11047265564xxxx","name":"Vishakhapatnam, Andhra Pradesh, India"}

Updates:

At first time login it asks all permissions, and removed SSO login because I have not configured my facebook app with native app(using keystore hash key).

OTHER TIPS

USE following facebook SDK https://github.com/facebook/facebook-android-sdk/

Following is the code for your requirement (getting friend list from facebook)

try {

  Facebook mFacebook = new Facebook(Constants.FB_APP_ID);
  AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
  Bundle bundle = new Bundle();
  bundle.putString("fields", "birthday");
  mFacebook.request("me/friends", bundle, new FriendListRequestListener());

} catch(Exception e){
    Log.e(Constants.LOGTAG, " " + CLASSTAG + " Exception = "+e.getMessage());
}

public class FriendListRequestListener extends BaseRequestListener {

    public void onComplete(final String response) {
        _error = null;

        try {
            JSONObject json = Util.parseJson(response);
            final JSONArray friends = json.getJSONArray("data");

            FacebookActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    // Do stuff here with your friends array, 
                    // which is an array of JSONObjects.
                }
            });

        } catch (JSONException e) {
            _error = "JSON Error in response";
        } catch (FacebookError e) {
            _error = "Facebook Error: " + e.getMessage();
        }

        if (_error != null)
        {
            FacebookActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(getApplicationContext(), "Error occurred:  " + 
                                    _error, Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}

I hope it helps you & others.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top