Firebaseのストレージアクセス

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

環境

Unity5.6.1f1 firebase_unity_sdk_3.0.3

認証等のコンソール設定を済ませてある状態 Firebaseの匿名認証(Android)

概要

テクスチャのデータをPNG化し、ストレージに保存、取得します

コンソールの設定

・以下にアクセスし、作成済みのプロジェクトを開く(例:TestFirebase2)  https://console.firebase.google.com/ ・左側メニューの「Storage」を押す ・「GET STARTED」を押す  「gs://your-firebase-storage-bucket」が確認できる(例:gs://testfirebase2-bc737.appspot.com)

エディタ用のルール設定

・エディタ用にサービスアカウントを設定しても、認証が通らなかった為、仕方ないので公開設定にする ・Android実機のみで動作させる場合は必要ない

・上部にある「ルール」を選択 ・//を追加して公開状態にする  allow read, write//: if request.auth != null;

Unityエディタの設定

・Unityプロジェクトを起動する(例:TestFirebase2) ・SDKをダウンロードする  ・https://firebase.google.com/docs/unity/setup ・zip内に含まれている「FirebaseStorage.unitypackage」をインポートする

プログラム

Signout()を最初に実行することで、Androidでも毎回アカウントが変わるようにしてあります。

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Auth;
using Firebase.Database;
using Firebase.Storage;
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 StorageReference _storageReference = 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;
        _storageReference = FirebaseStorage.DefaultInstance.GetReferenceFromUrl( "gs://testfirebase2-bc737.appspot.com" );

        Signout();
        yield return null;
    }

    private void OnApplicationQuit()
    {
        OnDestroy();        
    }

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

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

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

        var user = _auth.CurrentUser;
        if( user != null )
        {
            _auth.SignOut();
            Debug.Log( "DeleteAsync" );
            user.DeleteAsync().ContinueWith( task =>
            {
                if( task.IsCanceled == true )
                {
                    Debug.Log( "Canceled" );
                }
                else if( task.IsFaulted == true )
                {
                    Debug.Log( "Faulted" );
                    Signin();
                }
                else if ( task.IsCompleted == true )
                {
                    Debug.Log( "Completed" );
                    Signin();
                }
            });
        }
        else
            Signin();
    }

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

        var  user = _auth.CurrentUser;
        if( user == null )
        {
            Debug.Log( "SignInAnonymouslyAsync" );
            _auth.SignInAnonymouslyAsync().ContinueWith( task =>
            {
                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;
                    CreateUser( newUser );
                }
            });
        }
        else
        {
            OnSignin();
        }
    }

    private void CreateUser( FirebaseUser newUser )
    {
        Debug.Log( "OnCreateUser" );
        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( "GetValueAsync" );
            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" );

                CreateUserImage( onResult );
            }
        });
    }

    private void OnSignin()
    {
        Debug.Log( "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() );

                    GameObject item = null;
                    if( _scrollRectUserData != null )
                    {
                        var content = _scrollRectUserData.content;
                        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;
                        }
                    }
                    GetUserImage( userData.userId, item );
                }
            }
        });
    }
    //----------------------------------------------------------------------------
    //ストレージ
    //----------------------------------------------------------------------------
    private void CreateUserImage( UnityAction onResult )
    {
        Debug.Log( "CreateUserImage" );
        var user = _auth.CurrentUser;
        if( user == null )
            return;
        var imageRef = _storageReference.Child( "images/" + user.GetUserId() + ".png" );

        var texture = new Texture2D( 64, 64, TextureFormat.ARGB32, false );
        var colors = new Color32[ 64 * 64 ];
        var color = new Color32( (byte)UnityRandom.Range( 0, 256 ), (byte)UnityRandom.Range( 0, 256 ), (byte)UnityRandom.Range( 0, 256 ), 255 );
        for( int y = 0; y < 64; y++ )
            for( int x = 0; x < 64; x++ )
                colors[ ( y * 64 ) + x ] = color;

        texture.SetPixels32( colors );
        var pngBytes = texture.EncodeToPNG();

        Debug.Log( "PutBytesAsync" );
        imageRef.PutBytesAsync( pngBytes ).ContinueWith( task =>
        {
            if ( task.IsFaulted == true || task.IsCanceled == true )
            {
                Debug.Log( task.Exception.ToString() );
            }
            else
            {
                StorageMetadata metadata = task.Result;
                var downloadUrl = metadata.DownloadUrl;
                Debug.Log("downloadUrl = " + downloadUrl );

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

        });
    }

    private void GetUserImage( string userId, GameObject item )
    {
        var imageRef =  _storageReference.Child( "images/" + userId + ".png" );

        const long maxDownloadSize = 64 * 1024; //64k
        imageRef.GetBytesAsync( maxDownloadSize ).ContinueWith( task =>
        {
            if ( task.IsFaulted == true || task.IsCanceled == true )
                Debug.Log( task.Exception.ToString() );
            else
            {
                var pngBytes = task.Result;
                var texture = new Texture2D( 64, 64, TextureFormat.ARGB32, false );
                texture.LoadImage( pngBytes );
                if( item != null )
                {
                    var rawImage = item.GetComponentInChildren<RawImage>();
                    rawImage.texture = texture;
                }
            }
        });
    }
}

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