Firebaseの匿名認証(Android)

※この記事は2017年05月29日にqiitaに投稿した内容です。

環境

Unity5.6.1f1 firebase_unity_sdk_3.0.3

概要

Firebaseに匿名認証でアクセスし、データベースにユーザーデータを保存、取得します

Firebaseコンソールの設定

https://console.firebase.google.com/

Androidの設定

・「プロジェクトの追加」を押し、プロジェクトを作成する  ・プロジェクト名と国を設定(例:Testfirebase2, 日本)  ・testfirebase2-bc737となった ・「Android アプリに Firebase を追加」を押す  ・Android パッケージ名を入れる(例:com.example.testfirebase2)  ・アプリの登録を押す  ・「ダウンロードgoogle_services.json」でjsonを保存する  ・続行を押す  ・終了を押す

匿名認証の設定

・左側のメニューの「Authentication」を押す ・上側にある「ログイン方法」を押す ・「匿名」を押し、「有効にする」をONにして保存する

エディタ用の権限の追加

・左側のメニューの「Overview」の横の歯車アイコンを押し、「権限」を押す ・左側のメニューの「サービスアカウント」を押す ・上側にある「サービスアカウントを作成」を押す  ・「サービスアカウント名」を設定(例:UnityEditor)  ・「役割」をProject>オーナーに設定  ・「新しい秘密鍵の提供」にチェック    ・「キーのタイプ」をP12にする  ・作成を押す   ・p12ファイルが自動的にパソコンに保存され、ダイアログにパスワードが表示される

Unityプロジェクトの設定

・Unityを起動し、プロジェクトを作成する(例:TestFirebase2)  ・Androidにスイッチし、バンドルIdをコンソールで設定したものにする(例:com.example.testfirebase2) ・SDKをダウンロードする  ・https://firebase.google.com/docs/unity/setup ・zip内に含まれている「FirebaseAuth.unitypackage」,「FirebaseDatabase.unitypackage」をインポートする ・ダウンロードした「google_services.json」をAssets内のどこかに入れる(例:Assets/google_services.json) ・ダウンロードされたp12ファイルを「Editor Default Resources」に入れる

プログラム

SetEditorDatabaseUrl SetEditorP12FileName SetEditorServiceAccountEmail SetEditorP12Password はコンソールで作成したものを設定する DatabaseUrlはコンソールの「Database」で確認できる

エディタで試すと毎回ユーザーが作られる(そういうものなのか、どこか設定が足りないのか…) 仕方がないので拡張でGetUserId()という関数を追加し、ID固定になるようにしています Android実機だと問題ないです

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Auth;
using Firebase.Database;
using System.Collections;
using System;

//typedef
using UnityObject = UnityEngine.Object;
using UnityRandom = UnityEngine.Random;

public class TestFirebase : MonoBehaviour
{
    [SerializeField] private Text _textUserData = null;
    [SerializeField] private ScrollRect _scrollRectUserData = null;
    [SerializeField] private GameObject _listItemUserDataPrefab = null;

    private FirebaseAuth _auth = null;
    private DatabaseReference _databaseReference = null;


    private IEnumerator Start()
    {
        FirebaseApp.DefaultInstance.SetEditorDatabaseUrl( "https://testfirebase2-bc737.firebaseio.com/" );
        FirebaseApp.DefaultInstance.SetEditorP12FileName( "TestFirebase2-3e858070b1cd.p12");
        FirebaseApp.DefaultInstance.SetEditorServiceAccountEmail( "unityeditor@testfirebase2-bc737.iam.gserviceaccount.com" );
        FirebaseApp.DefaultInstance.SetEditorP12Password( "notasecret" );
        FirebaseApp.DefaultInstance.SetEditorAuthUserId( "UnityEditor" );

        _auth = FirebaseAuth.GetAuth( FirebaseApp.DefaultInstance );//FirebaseAuth.DefaultInstance;
        _auth.StateChanged += OnAuthStateChanged;
        _databaseReference = FirebaseDatabase.DefaultInstance.RootReference;

        Signin();
        yield return null;
    }

    private void OnDestroy()
    {
        _auth.StateChanged -= OnAuthStateChanged;
    }

    private void OnAuthStateChanged( object sender, EventArgs eventArgs )
    {
        Debug.Log( "OnAuthStateChanged" );
        if( _auth.CurrentUser != null )
        {
        }
    }

    private void Signin()
    {
        var  user = _auth.CurrentUser;
        if( user == null )
        {
            _auth.SignInAnonymouslyAsync().ContinueWith( task =>
            {
                Debug.Log( "OnAuth" );
                if( task.IsCanceled == true )
                {
                    Debug.Log( "Canceled" );
                }
                else if( task.IsFaulted == true )
                {
                    Debug.Log( "Faulted" );
                }
                else if ( task.IsCompleted == true )
                {
                    Debug.Log( "Completed" );
                    FirebaseUser newUser = task.Result;
                    OnCreateUser( newUser );
                }
            });
        }
        else
            OnSignin();
    }

    private void OnCreateUser( FirebaseUser newUser )
    {
        var  user = _auth.CurrentUser;
        if( user.GetUserId() != newUser.GetUserId() )
            Debug.LogError( user.GetUserId() + "/" + newUser.GetUserId() );

        //ユーザーデータがすでにあるかチェック
        _databaseReference.Child( "userDatas" ).Child( newUser.GetUserId() ).GetValueAsync().ContinueWith( task =>
        {
            Debug.Log( "OnCreateUser" );
            if ( task.IsFaulted == true || task.Result.Exists == false )
            {
                Debug.Log( "Faulted" );
                //通常こっち
                CreateUserData( newUser, OnSignin );
            }
            else if ( task.IsCompleted == true )
            {
                Debug.Log( "Completed" );
#if UNITY_EDITOR
                OnSignin();
#else
                Debug.LogError( "Error! UserData" );
#endif
            }
        });
    }

    private void CreateUserData( FirebaseUser newUser, UnityAction onResult )
    {
        //ユーザーデータ作成
        UserData userData = new UserData();
        userData.userId = newUser.GetUserId();
        userData.score = UnityRandom.Range( 0, int.MaxValue );
        string json = JsonUtility.ToJson( userData );

        _databaseReference.Child( "userDatas" ).Child( newUser.GetUserId() ).SetRawJsonValueAsync( json ).ContinueWith( task =>
        {
            Debug.Log( "OnCreateUserData" );
            if ( task.IsFaulted == true )
            {
                Debug.Log( "Faulted" );
            }
            else if ( task.IsCompleted == true )
            {
                Debug.Log( "Completed" );

                if( onResult != null )
                    onResult.Invoke();
            }
        });
    }

    private void OnSignin()
    {
        var user = _auth.CurrentUser;
        Debug.Log( user.DisplayName + ":" + user.GetUserId() );

        if( _textUserData != null )
            _textUserData.text = user.DisplayName + "/" + user.GetUserId();

        //ユーザーデータリスト取得
        GetUserDatas();
    }

    private void GetUserDatas()
    {
        Debug.Log( "GetUserDatas" );

        if( _scrollRectUserData != null )
        {
            var content = _scrollRectUserData.content;
            for( int i = 0; i < content.childCount; i++ )
            {
                var child = content.GetChild( i );
                DestroyObject( child );
            }
            content.DetachChildren();
            _listItemUserDataPrefab.SetActive( false );
        }

        _databaseReference.Child( "userDatas" ).GetValueAsync().ContinueWith( task =>
        {
            Debug.Log( "OnGetUserDatas" );
            if ( task.IsFaulted == true )
            {
                Debug.Log( "Faulted" );
            }
            else if ( task.IsCompleted == true )
            {
                DataSnapshot snapshot = task.Result;
                Debug.Log( snapshot.ToString() );
                foreach( var child in snapshot.Children )
                {
                    var userData = JsonUtility.FromJson<UserData>( child.GetRawJsonValue() );
                    Debug.Log( "Key:" + child.Key + "/" + userData.ToString() );

                    if( _scrollRectUserData != null )
                    {
                        var content = _scrollRectUserData.content;
                        var item = Instantiate<GameObject>( _listItemUserDataPrefab );
                        item.GetComponentInChildren<Text>().text = userData.userId + "\n" + userData.score;
                        item.SetActive( true );
                        item.transform.SetParent( content, false );

                        var user = _auth.CurrentUser;
                        if( userData.userId == user.GetUserId() )
                        {
                            var image = item.GetComponent<Image>();
                            image.color = Color.green;
                        }
                    }
                }
            }
        });
    }
}

//拡張
public static class FirebaseExtensions
{
    public static string GetUserId( this FirebaseUser user )
    {
#if UNITY_EDITOR
        return "UnityEditor";
#else
        return user.UserId;
#endif
    }
}

//ユーザーデータ
public class UserData
{
    public string userId;
    public int score;
}