Android Firebase Authentication(Facebook認証)の手取り足取りメモ

# はじめに
Android Firebase Authentication(Facebook認証)の手取り足取りメモです．
確実に自分用ですが，参考になると幸いです．
IDEはAndroid Studio とします．

# 参考文献
googleログイン認証の方法
http://qiita.com/Sert/items/1fbdbf68dd087201a57b
google,Facebook,Twitter,email&password認証の方法
http://qiita.com/ronnnnn/items/dddf57a0369f780d8ac2

こちらを参考にさせて頂きました．
またFacebook専門の記事がなかったようなのでメモしときます．

# Facebook for developersに登録
## アカウント登録
これは割愛です．
## 認証させたいAndroidアプリケーション登録

![SnapCrab_NoName_2017-7-2_22-30-45_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/46d13b8c-eaa5-6fa1-b347-cf62eaed7ac7.png)

新しいアプリを追加を押します．

![SnapCrab_NoName_2017-7-2_22-33-18_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/7b5b133d-577b-3377-13b4-12ad3f5209fd.png)

そして，表示名になんか適当な名前を入れます．
そしたらセキュリティチェックがでてくるので，そこを突破します．
そしたら画面が遷移するので，Facebookログインを押して，その次のAndroidを押します．

![SnapCrab_NoName_2017-7-2_22-37-49_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/c1a3919f-f855-a0cc-cdbb-0b08f155f867.png)

こんな画面になったでしょうか？
ではこの通りにします．
Android Studioの場合は
1.Android用Facebook SDKを飛ばします．次へを押してください．

2.Facebook SDKをインポートします．
`build.gradle(project)`を

```java:build.gradle(project)
buildscript {
    repositories {
        jcenter()
        mavenCentral()//ここを追加
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
    }
}
allprojects {
    repositories {
        jcenter()
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}
```

`build.gradle(app)`を

```java:build.gradle(app)
...

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.facebook.android:facebook-android-sdk:[4,5)'//ここに追加
}
```

これで終了です．

3.Androidプロジェクトの情報を入力する．
これはパッケージ名とAcitivityのクラス名を記述します．
今回はパッケージ名はmanifest.xmlのpackage="..."を追加し，
LoginActivity→MainActivityとしたいのでデフォルトをLoginActivityにするので，`パッケージ名.LoginActivity`と記述してください．

次に
Save→このパッケージ名を使用する
とクリックしてください．
これで3は終了です．

4.開発キーハッシュとリリースキーハッシュを追加する
今回は非公開前提なので，開発キーハッシュだけを生成します．

私は，Windowsなので，

```
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
```
をクリックして貼り付けます．
ちなみに私は，Windows bashを用いてますのでkeytoolコマンドを用いることが出来ます．コマンドプロンプトでは不可能でした．
Windows Bashは便利なのでインストールしておきましょう．

Windows Bash インストール
http://qiita.com/Aruneko/items/c79810b0b015bebf30bb
そしてきれいな端末にするために
https://www.sa-sa-ki.jp/blog/2016/12/bash-on-ubuntu-on-windows-wsl-terminal/
このようなツールを用いるのもいいですね:sunny:

でコマンド結果を貼り付けます．
Save→次へ

5.アプリのシングルサインオンを有効にする
飛ばします．

6.FacebookアプリIDを追加する
記述通りにします．

7.AndroidManifest.xmlにFacebookActivityを追加する
これも記述通り．
8.Chromeカスタムタブを有効にする
これも記述通り

でこんな感じになります．

```xml:Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.app.oomae.hisaki.facebook">

    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.facebook.FacebookActivity"
            android:configChanges=
                "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />
        <activity
            android:name="com.facebook.CustomTabActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>
    </application>
</manifest>
```

さて，まだまだです．

# Firebaseに登録
次に，Firebaseにアプリを登録して，Facebook使いますよ～という宣言をします．
Projectの追加→プロジェクト名(任意の名前)→プロジェクトの追加→AndroidアプリにFirebaseを追加

![SnapCrab_NoName_2017-7-2_23-16-50_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/ed0ecf67-5d36-6ec3-4297-ea6d5e9886b5.png)

こんな感じになっているので，
Androidパッケージ名：先ほどFacebook for developersで入力したものと同様の物

アプリのニックネーム：省略

デバッグ用の署名証明書SHA-1（オプション）：
これは

```
keytool -exportcert -list -v \
-alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore
```
これをWindows Bashに貼り付けます．
そしてEnterし，パスワード"android"を入力すると

![SnapCrab_NoName_2017-7-2_23-23-52_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/50acacb2-8bfd-24bc-2b5a-08a7957dba19.png)

こんな感じに出力されるので，SHA1：hogehogelldpksvopd

のhogehogelldpksvopdこの部分だけを貼り付けて，アプリ登録をしましょう．
次にgoogle-services.jsonを記述通りのPATHに入れてください．
次に，build.gradleを記述通りにいじります．

```java:build.gradle(project)

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.google.gms:google-services:3.1.0'//追加
    }
}
allprojects {
    repositories {
        jcenter()
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

```

```java:build.gradle(app)
...

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.facebook.android:facebook-android-sdk:[4,5)'
}
apply plugin: 'com.google.gms.google-services'//追加

```

![SnapCrab_NoName_2017-7-2_23-35-15_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/39502bbd-c062-7510-a9d5-52afc20c856b.png)

次はAuthenticationの設定です．

使ってみる(Authentication)→ログイン方法→Facebook
ここで，アプリケーションIDとシークレットIDを求められます．
再びFacebook for developersを開いて，ダッシュボードを確認してください．

![SnapCrab_NoName_2017-7-2_23-37-24_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/2e77940e-d192-b885-3ad8-abb93f8622a0.png)

これです．:muscle:

そして再びFirebaseに移動しまして，入力し， OAuth リダイレクト URI をコピーします．

また，Facebook for developersを開いて，

![SnapCrab_NoName_2017-7-2_23-44-43_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/129578/fe306b54-bd7e-5bfb-eb25-53a71fc4709b.png)

左のFacebookログインを押し，有効なOAuthリダイレクトURIに先ほどコピーしたURLを貼り付けます．そして右下の変更を保存を押します．

再び，Firebaseに移動しまして，保存します．これで，Firebase側も完了です．


#実装

以上を利用して，Firebaseで認証を行う場合のLoginActivityでログイン→遷移→MainActivityでログアウト→遷移→...のようなアプリを作成いたします．

まずbuild.gradle(app)をいじります

```build.gradle
compile 'com.google.firebase:firebase-core:11.0.1'
compile 'com.google.firebase:firebase-auth:11.0.1'
```

次にManifest.xmlでLoginActivityが先に呼び出されるようにします．

```xml:Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.app.oomae.hisaki.facebook_authentication_sample">

    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity">
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        </activity>
        <activity android:name="com.facebook.FacebookActivity"
            android:configChanges=
                "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />
        <activity
            android:name="com.facebook.CustomTabActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>
    </application>
</manifest>
```

次にActivityを作成します．
遷移元の`LoginActivity.java`と遷移先の`MainActivity.java`です．

```java:LoginActivity.java
package ;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuth;

public class LoginActivity extends AppCompatActivity {

    private FirebaseAuth firebaseAuth;
    private CallbackManager callbackManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // get firebase instance
        firebaseAuth = FirebaseAuth.getInstance();
        FacebookSdk.sdkInitialize(getApplicationContext());
        setContentView(R.layout.activity_login);

        // initialize facebook login button
        callbackManager = CallbackManager.Factory.create();
        FacebookCallback<LoginResult> facebookLoginCallback = new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                firebaseAuthWithFacebook(loginResult.getAccessToken());
            }

            @Override
            public void onCancel() {
            }

            @Override
            public void onError(FacebookException error) {
                if (error != null) {
                    DialogManager.createDialog(LoginActivity.this, error).show();
                }
            }
        };
        LoginButton facebookLoginButton = (LoginButton) findViewById(R.id.login_button);
        facebookLoginButton.setReadPermissions("email", "public_profile");
        facebookLoginButton.registerCallback(callbackManager, facebookLoginCallback);
    }

    private void firebaseAuthWithFacebook(AccessToken token) {
        AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        firebaseAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            changeActivity();
                        } else {
                            Toast.makeText(LoginActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void changeActivity() {
        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
        startActivity(intent);
    }
    //FaceBook
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
    }
}

```

```java:MainActivity.java

package ;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.facebook.login.LoginManager;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.logoutButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                LoginManager.getInstance().logOut();
                Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        });
    }
}
```

ダイアログを管理するファイルを作成します．

```java:DialogManager.java
package ;

import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;

public class DialogManager {
    static AlertDialog createDialog(Context context, String message) {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setMessage(message);
        alertDialog.setPositiveButton("dialog close", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int id) {
                dialogInterface.dismiss();
            }
        });
        return alertDialog.create();
    }

    static AlertDialog createDialog(Context context, Throwable throwable) {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setMessage(throwable.getMessage());
        alertDialog.setPositiveButton("dialog close", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int id) {
                dialogInterface.dismiss();
            }
        });
        return alertDialog.create();
    }
}
```

つぎはレイアウトをファイルです．

```xml:activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <com.facebook.login.widget.LoginButton
        android:id="@+id/login_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp" />

</LinearLayout>
```

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="15dp"
    android:paddingLeft="15dp"
    android:paddingRight="15dp"
    android:paddingTop="15dp"
    tools:context=".LoginActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login success!"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="48dp"
        android:textSize="32dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Logout"
        android:id="@+id/logoutButton"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:textSize="26dp" />
</RelativeLayout>
```

以上で完成です．
最後まで見てくれてありがとうございました！！
是非質問やご意見お待ちしております．:point_up:

GitHub：https://github.com/hisakioomae/Firebase_Authentication_Facebook_Sample