Domanda

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.

È stato utile?

Soluzione

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).

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top