fragmentでfacebookログインする方法

activityからfacebookログインするプログラムはいくつかのサイトで見つかるのですが、
fragmentからは見当たらなかったので記載します。

基本的にはactivity向けに書かれたプログラムを流用してfragmentに書き換えるだけですが、
以下のように機械的に書き変えたらはまりました・・。

```lang:java
import java.util.Arrays;

import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;

public class TopFragment extends Fragment {

    private View view;
    private CallbackManager callbackManager;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d("TEST", "onCreateView");
        view = inflater.inflate(R.layout.top_fragment, container, false);

        FacebookSdk.sdkInitialize(getActivity());
        Button toLoginBtn = (Button) view.findViewById(R.id.to_login_button);
        toLoginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("TEST", "LoginManager.getInstance() start");
                LoginManager.getInstance().logInWithReadPermissions(getActivity(), Arrays.asList("public_profile", "email"));    //profileとemailの情報を取得
                Log.d("TEST", "LoginManager.getInstance() end");
            }
        });

        callbackManager = CallbackManager.Factory.create();
        LoginManager.getInstance().registerCallback(callbackManager,
            new FacebookCallback<LoginResult>() {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    //ログイン成功
                    Log.d("TEST", "success");
                }
                @Override
                public void onCancel() {
                    //キャンセル
                    Log.d("TEST", "cancel");
                }

                @Override
                public void onError(FacebookException exception) {
                    //ログイン失敗
                    Log.d("TEST", "error");
                    Log.e("TEST", exception.toString());
                }
            });
        return view;
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        Fragment parent =  this.getParentFragment();
        if (parent != null) {
            parent.startActivityForResult(intent, requestCode);
        } else {
            super.startActivityForResult(intent, requestCode);
        }
    }

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

        Log.d("TEST", "onActivityResult ABC");
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onStart(){
        super.onStart();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
```

このソースで試したところ、
facebook認証画面が表示され、
ID、パスワードを入力しログインボタンを押すと認証には成功するのですが、
Facebookから成功後の結果を取得できませんでした。
エラーログも表示されず・・・。
いろいろな箇所にデバッグコードを埋め込み、調べたところ、
このfragmentを生成しているActivityのonActivityResultに結果が送信されていました。
これをどうやってfragmentに渡すかさらに調べたところ、
実に簡単でした。

logInWithReadPermissionsの引数をActivityからfragmentに変えるだけです。

```lang:java
LoginManager.getInstance().logInWithReadPermissions(getActivity(), Arrays.asList("public_profile", "email"));
```

```lang:java
LoginManager.getInstance().logInWithReadPermissions(topFragment, Arrays.asList("public_profile", "email"));
```

変えた部分の引数はfacebookからの引数をどのインスタンスで受け取るかを示す値でした。

https://developers.facebook.com/docs/reference/android/current/class/LoginManager/

公式ドキュメントは読んだ方がいいです。
あと、最初使っていたfacebook SDKのバージョンは4.7だったのですが、
それだと正しく動かず、最新の4.10に変えたら動きました。
頻繁にバージョンアップが行われているので最新のを利用するのもおすすめします。