【问题标题】:Facebook friend picker SDK sample not working AndroidFacebook 朋友选择器 SDK 示例无法在 Android 上运行
【发布时间】:2014-05-08 13:53:50
【问题描述】:

请帮助我使用 3.14 SDK 从我的个人资料中获取 facebook 好友。代码中没有错误,但问题是在我的个人资料中获取朋友时获得空列表。我在 logcat 中收到错误消息

05-08 16:18:49.252: E/ActivityThread(25644): Failed to find provider info for com.facebook.orca.provider.PlatformProvider<br>
05-08 16:42:20.453: I/QCNEA(28696): |NIMS| getaddrinfo: hostname graph.facebook.com servname NULL numeric 4 appname <br>
05-08 16:51:32.482: D/Request(31861): Warning: Sessionless Request needs token but missing either application ID or client token<br>

我也在下面生成完整的代码供您参考

FriendPickerApplication.java*

package com.facebook.samples.friendpicker;

import android.app.Application;
import com.facebook.model.GraphUser;

import java.util.List;

    // We use a custom Application class to store our minimal state data (which users have been selected).
    // A real-world application will likely require a more robust data model.
    public class FriendPickerApplication extends Application {
        private List<GraphUser> selectedUsers;

        public List<GraphUser> getSelectedUsers() {
            return selectedUsers;
        }

        public void setSelectedUsers(List<GraphUser> selectedUsers) {
            this.selectedUsers = selectedUsers;
        }
    }<br>

FriendPickerSampleActivity.java

package com.facebook.samples.friendpicker;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.facebook.AppEventsLogger;
import com.facebook.Session.NewPermissionsRequest;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphUser;
import com.facebook.Session;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class FriendPickerSampleActivity extends FragmentActivity {
    private static final List<String> PERMISSIONS = new ArrayList<String>() {
        {
            add("user_friends");
            add("public_profile");
        }
    };
    private static final int PICK_FRIENDS_ACTIVITY = 1;
    private Button pickFriendsButton;
    private TextView resultsTextView;
    private UiLifecycleHelper lifecycleHelper;
    boolean pickFriendsWhenSessionOpened;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        resultsTextView = (TextView) findViewById(R.id.resultsTextView);
        pickFriendsButton = (Button) findViewById(R.id.pickFriendsButton);
        pickFriendsButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                onClickPickFriends();
            }
        });

        lifecycleHelper = new UiLifecycleHelper(this, new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                onSessionStateChanged(session, state, exception);
            }
        });
        lifecycleHelper.onCreate(savedInstanceState);

        ensureOpenSession();
    }

    @Override
    protected void onStart() {
        super.onStart();

        // Update the display every time we are started.
        displaySelectedFriends(RESULT_OK);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Call the 'activateApp' method to log an app event for use in analytics and advertising reporting.  Do so in
        // the onResume methods of the primary Activities that an app may be launched into.
        AppEventsLogger.activateApp(this);
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case PICK_FRIENDS_ACTIVITY:
                displaySelectedFriends(resultCode);
                break;
            default:
                Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
                break;
        }
    }

    private boolean ensureOpenSession() {
        if (Session.getActiveSession() == null ||
                !Session.getActiveSession().isOpened()) {
            Session.openActiveSession(
                    this, 
                    true, 
                    PERMISSIONS,
                    new Session.StatusCallback() {
                        @Override
                        public void call(Session session, SessionState state, Exception exception) {
                            onSessionStateChanged(session, state, exception);
                        }
                    });
            return false;
        }
        return true;
    }

    private boolean sessionHasNecessaryPerms(Session session) {
        if (session != null && session.getPermissions() != null) {
            for (String requestedPerm : PERMISSIONS) {
                if (!session.getPermissions().contains(requestedPerm)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    private List<String> getMissingPermissions(Session session) {
        List<String> missingPerms = new ArrayList<String>(PERMISSIONS);
        if (session != null && session.getPermissions() != null) {
            for (String requestedPerm : PERMISSIONS) {
                if (session.getPermissions().contains(requestedPerm)) {
                    missingPerms.remove(requestedPerm);
                }
            }
        }
        return missingPerms;
    }

    private void onSessionStateChanged(final Session session, SessionState state, Exception exception) {
        if (state.isOpened() && !sessionHasNecessaryPerms(session)) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(R.string.need_perms_alert_text);
            builder.setPositiveButton(
                    R.string.need_perms_alert_button_ok, 
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            session.requestNewReadPermissions(
                                    new NewPermissionsRequest(
                                            FriendPickerSampleActivity.this, 
                                            getMissingPermissions(session)));
                        }
                    });
            builder.setNegativeButton(
                    R.string.need_perms_alert_button_quit,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    });
            builder.show();
        } else if (pickFriendsWhenSessionOpened && state.isOpened()) {
            pickFriendsWhenSessionOpened = false;

            startPickFriendsActivity();
        }
    }

    private void displaySelectedFriends(int resultCode) {
        String results = "";
        FriendPickerApplication application = (FriendPickerApplication) getApplication();

        Collection<GraphUser> selection = application.getSelectedUsers();
        if (selection != null && selection.size() > 0) {
            ArrayList<String> names = new ArrayList<String>();
            for (GraphUser user : selection) {
                names.add(user.getName());
            }
            results = TextUtils.join(", ", names);
        } else {
            results = "<No friends selected>";
        }

        resultsTextView.setText(results);
    }

    private void onClickPickFriends() {
        startPickFriendsActivity();
    }

    private void startPickFriendsActivity() {
        if (ensureOpenSession()) {
            Intent intent = new Intent(this, PickFriendsActivity.class);
            // Note: The following line is optional, as multi-select behavior is the default for
            // FriendPickerFragment. It is here to demonstrate how parameters could be passed to the
            // friend picker if single-select functionality was desired, or if a different user ID was
            // desired (for instance, to see friends of a friend).
            PickFriendsActivity.populateParameters(intent, null, true, true);
            startActivityForResult(intent, PICK_FRIENDS_ACTIVITY);
        } else {
            pickFriendsWhenSessionOpened = true;
        }
    }
} <br>

PickFriendsActivity.java

package com.facebook.samples.friendpicker;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.widget.Toast;
import com.facebook.FacebookException;
import com.facebook.model.GraphUser;
import com.facebook.widget.FriendPickerFragment;
import com.facebook.widget.PickerFragment;

import java.util.List;

public class PickFriendsActivity extends FragmentActivity {
    FriendPickerFragment friendPickerFragment;

    public static void populateParameters(Intent intent, String userId,
            boolean multiSelect, boolean showTitleBar) {
        intent.putExtra(FriendPickerFragment.USER_ID_BUNDLE_KEY, userId);
        intent.putExtra(FriendPickerFragment.MULTI_SELECT_BUNDLE_KEY,
                multiSelect);
        intent.putExtra(FriendPickerFragment.SHOW_TITLE_BAR_BUNDLE_KEY,
                showTitleBar);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pick_friends_activity);

        FragmentManager fm = getSupportFragmentManager();

        if (savedInstanceState == null) {
            // First time through, we create our fragment programmatically.
            final Bundle args = getIntent().getExtras();
            friendPickerFragment = new FriendPickerFragment(args);
            fm.beginTransaction()
                    .add(R.id.friend_picker_fragment, friendPickerFragment)
                    .commit();
        } else {
            // Subsequent times, our fragment is recreated by the framework and
            // already has saved and
            // restored its state, so we don't need to specify args again. (In
            // fact, this might be
            // incorrect if the fragment was modified programmatically since it
            // was created.)
            friendPickerFragment = (FriendPickerFragment) fm
                    .findFragmentById(R.id.friend_picker_fragment);
        }

        friendPickerFragment
                .setOnErrorListener(new PickerFragment.OnErrorListener() {
                    @Override
                    public void onError(PickerFragment<?> fragment,
                            FacebookException error) {
                        PickFriendsActivity.this.onError(error);
                    }
                });

        friendPickerFragment
                .setOnDoneButtonClickedListener(new PickerFragment.OnDoneButtonClickedListener() {
                    @Override
                    public void onDoneButtonClicked(PickerFragment<?> fragment) {
                        // We just store our selection in the Application for
                        // other activities to look at.
                        FriendPickerApplication application = (FriendPickerApplication) getApplication();
                        application.setSelectedUsers(friendPickerFragment
                                .getSelection());

                        setResult(RESULT_OK, null);
                        finish();
                    }
                });
    }

    private void onError(Exception error) {
        String text = getString(R.string.exception, error.getMessage());
        Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
        toast.show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        try {
            FriendPickerApplication application = (FriendPickerApplication) getApplication();
            List<GraphUser> selectedUsers = application.getSelectedUsers();
            if (selectedUsers != null && !selectedUsers.isEmpty()) {
                friendPickerFragment.setSelection(selectedUsers);
            }
            // Load data, unless a query has already taken place.
            friendPickerFragment.loadData(false);
        } catch (Exception ex) {
            onError(ex);
        }
    }
}<br>

Androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.facebook.samples.friendpicker"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:name=".FriendPickerApplication"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar" >
        <activity
            android:name="FriendPickerSampleActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustResize" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="PickFriendsActivity"
            android:label="Pick Friends" >
        </activity>
        <activity
            android:name="com.facebook.LoginActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />

        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/app_id" />

        <provider
            android:name="com.facebook.NativeAppCallContentProvider"
            android:authorities="com.facebook.app.NativeAppCallContentProvider1441068969495032"
            android:exported="true" />
    </application>

</manifest>

【问题讨论】:

  • 我也遇到了同样的问题,谁能解决这个问题。

标签: java android facebook facebook-graph-api sdk


【解决方案1】:

经过长期的努力,我找到了解决上述问题的方法。 Facebook 最近发布了他们的新 SDK,以提高安全级别。在您的应用中使用 facebook SDK 有一些要求。

  1. 应用程序应发送提交并需要得到 facebook 的批准才能在 facebook 内使用,以使您自己的应用程序能够显示 朋友的详细信息、访问位置和其他特殊权限 审批手续与 Google Play 应用商店类似。

  2. 该应用程序必须在 Google Play 中列出,或者您可以将其作为测试用户集成(例如 Google Play 中的 beta 测试)。

  3. 应用程序应具有正确的包名称、启动活动、域名、网站 url 和电子邮件。

  4. 注册的app id必须与app namehash key相匹配,必须为在不同的机器

  5. 需要添加基本应用信息,包括截图说明应用标识

    李>
  6. 成功通过后,您的应用名称旁边会显示一个“活动”符号。

我希望这对其他人有用!!!

More information on Facebook site.

【讨论】:

  • 感谢您的宝贵回答。真的会帮助那些在更新的 facebook sdk 中寻找问题的人。
  • 是的,我从您的回复中得到了解决方案
  • 我们的应用如何获得批准?
【解决方案2】:

花了好几个小时试图解决这个问题后,我想为仍在寻找的人添加以下内容:

  1. 您将在列表中看到的唯一具有 user_friend 权限的朋友是其他已登录并批准您的应用的用户。 IE。如果没有其他人在使用它,您将不会在列表中看到任何人(我知道,如果您全部阅读,这很明显)
  2. 最简单的测试方法是设置一个测试应用程序,在“角色”下的 facebook 开发界面中添加测试用户,确保测试用户是朋友,然后在每次使用您的应用程序时登录。只有这样他们才会出现在列表中。
  3. 除非您特别要求,否则您的应用将没有 user_friends 权限(但是,您不需要通过 Facebook 审核,因为它是基本权限的一部分) - 我将其添加到 Splash 中的 onCreateView像这样的段(来自 SDK 中的 Scrumptios/Login 示例):

    LoginButton loginButton = (LoginButton) view.findViewById(R.id.login_button);
    loginButton.setReadPermissions(Arrays.asList("user_friends"));
    
  4. 使用 Facebook 测试用户界面以您的测试用户身份登录 facebook,以验证他们已接受正确的权限(在应用程序下)。

【讨论】:

  • 欢迎来到 StackOverflow Jonas。作为一个新用户,这个答案非常好。但我还是建议你访问help center。好一个:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多