安装了原生Facebook应用程序的Android FacebookSDK登录即使在用户已经提供之后也会请求权限

Cla*_*tas 12 android facebook-android-sdk

条件:Android设备安装了本机Facebook apk但已注销.

每次满足此条件并且用户尝试使用Facebook的LoginButton登录或手动执行(见下文),登录后,Facebook SDK始终要求访问用户数据的权限,即使用户已经授予权限.

这是我在我的应用程序上实现的代码:

版本1 - 登录按钮:

XML:

<com.facebook.widget.LoginButton
    android:id="@+id/login_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
Run Code Online (Sandbox Code Playgroud)

Java的:

private static final List<String> PERMISSIONS = Arrays.asList("email", "user_groups");
private UiLifecycleHelper uiHelper;

@Override
protected void onCreate(Bundle savedInstanceState){
    uiHelper = new UiLifecycleHelper(this, callback);
    uiHelper.onCreate(savedInstanceState);
    loginButton = (LoginButton) findViewById(R.id.login_button);
    loginButton.setReadPermissions(PERMISSIONS);
}

private Session.StatusCallback callback = new Session.StatusCallback() {
    @Override
    public void call(Session session, SessionState state, Exception exception) {
        //modify interface or something
    }
};
Run Code Online (Sandbox Code Playgroud)

版本2 - 手动

XML:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/button"
    android:onClick="buttonOnClick"
    android:text="Login" />
Run Code Online (Sandbox Code Playgroud)

Java的:

private static final List<String> PERMISSIONS = Arrays.asList("email", "user_groups");

public void buttonOnClick(View v) {
    System.out.println("botaoOnClick");
    Session session = Session.getActiveSession();
    if (!session.isOpened() && !session.isClosed()) {
        System.out.println("session: " + session);
        session.openForRead(new Session.OpenRequest(this).setPermissions(PERMISSIONS).setCallback(callback));
    }
    else {
        Session.openActiveSession(this, true, callback);
    }
}

private Session.StatusCallback callback = new Session.StatusCallback() {
    @Override
    public void call(Session session, SessionState state, Exception exception) {
        //modify interface or something
    }
};
Run Code Online (Sandbox Code Playgroud)

即使是sdk附带的示例应用程序也是如此,但我已经看到其他一些应用程序(例如Foursquare)以我认为是自然行为的方式工作(如果用户尚未提供权限,则仅询问权限).

那么,有没有人知道实现预期结果的方法?最好不要编辑Facebook SDK本身.

提前致谢!

编辑1:附加信息:在回调方法上检查会话变量时,当满足上述条件时,权限始终为空.如果用户拒绝授予权限(不是第一次),并尝试再次登录,则会话将提供用户已经过去一段时间的权限,如预期的那样.

编辑2(2013-06-28):我决定上传一个重现这个问题的视频,因为我不太清楚每个人都理解我在解释中的含义.

链接到这里:http://www.youtube.com/watch?v = w4qJfoiVSsU

Gom*_*ino 2

这可能是因为您的应用程序(我假设处于调试模式)和与您的 appID 关联的 facebook 应用程序之间的签名不匹配。

基本上你应该确保:

  1. 使用 facebook sdk 的 Android 应用程序的签名已添加到facebook 应用程序仪表板 Facebook 应用程序仪表板 您可以使用 keytool 或在 Activity 的 onCreate 方法中添加以下代码轻松获取应用程序签名:

    @Override
    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    
    try {
        PackageInfo info = getPackageManager().getPackageInfo(
                getPackageName(), 
                PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            Log.d("TAG", "Hash to copy ==> "+ Base64.encodeToString(md.digest(), Base64.DEFAULT));
            }
    } catch (NameNotFoundException e) {
    
    } 
    catch (NoSuchAlgorithmException e) {
    
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. Facebook 登录复选框已启用

  3. 如果您未启用沙盒模式,您需要从应用程序详细信息页面选择一个类别

  4. 默认情况下,登录按钮使用 SingleSignOn 登录行为,这基本上会让您以 Facebook 应用程序所有者的身份登录,我建议您使用允许任何用户代表您的 Facebook 应用程序登录的登录行为。为此,只需在设置登录按钮的权限后添加此行:

    loginButton.setReadPermissions(PERMISSIONS);
    loginButton.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO);
    
    Run Code Online (Sandbox Code Playgroud)

如果您仍然遇到问题,我建议您阅读此文档facebook 登录故障排除

PS:仅供参考,如果您使用 UiLifecycleHelper,请不要忘记重写主要活动/片段生命周期方法,并将调用转发到 UiLifecycleHelper,如 javadoc 中所述。

使用此类时,客户端必须从 Activity 或 Fragment 中的相应方法调用所有公共方法。未能调用所有 * 方法可能会导致会话初始化不正确或未初始化。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

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

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    uiHelper.onSaveInstanceState(outState);
}

@Override
protected void onPause() {
    super.onPause();
    uiHelper.onPause();
}

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

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    uiHelper.onActivityResult(requestCode, resultCode, data);
}
Run Code Online (Sandbox Code Playgroud)