Search Unity

Resolved Firebase Storage GetFileAsync works on every platform except iPhones.

Discussion in 'Scripting' started by EOMedvis, Jan 15, 2021.

  1. EOMedvis

    EOMedvis

    Joined:
    Feb 19, 2019
    Posts:
    93
    We're using Firebase to store asset bundles which is then pulled down when the add needs them using Storage's GetFileAsync() method. This has worked on every platform we've tested on, Android, Windows Editor, mac Editor, except not the iPhone. The storage error exception were also not helpful since all it says is "Unknown Error"

    Here is the following relevant code:

    Firebase reference:

    Code (CSharp):
    1. public class FirestoreController : MonoBehaviour
    2. {
    3.     public static FirebaseFirestore firestoreInstance; //Firestore reference.  
    4.     public static FirebaseStorage firebaseStorage;
    5.     public static Firebase.Auth.FirebaseAuth firebaseAuth;
    6.     public static StorageReference storageRef;
    7.  
    8.     private void Awake()
    9.     {
    10.         firestoreInstance = FirebaseFirestore.DefaultInstance;
    11.         firebaseStorage = FirebaseStorage.DefaultInstance;
    12.         firebaseAuth = Firebase.Auth.FirebaseAuth.DefaultInstance;
    13.         storageRef = firebaseStorage.GetReferenceFromUrl("gs://<Storage Bucket>/");
    14.     }
    15. }
    After the App signs-in anonymously (this has been tested to work properly). A GetFileAynch is called:


    Code (CSharp):
    1. public async Task GetFile3(string _file) //generic download script for firebase storage.
    2.     {                    
    3.         string localPath = Application.persistentDataPath + "/" + _file; //save file into that folder.
    4.         string platform = string.Empty;
    5.  
    6.         //checks platform. Windows uses the android bundle (editor-only).
    7.         if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
    8.         {
    9.             platform = "android/";
    10.             //Debug.Log("Device is running on Android or Windows");
    11.         }
    12.         else if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor)
    13.         {
    14.             platform = "ios/";
    15.             //Debug.Log("Device is running on iPhone or Mac");
    16.         }
    17.  
    18.         if (CheckConnectivity()) //if the device is connected to the internet, initiate download.
    19.         {
    20.             Debug.Log("Initiating download of: " + platform + _file);
    21.  
    22.             await FirestoreController.storageRef.Child("bundles").Child(platform).Child(_file).GetFileAsync(localPath).ContinueWith(task =>
    23.             {
    24.                 if (!task.IsFaulted && !task.IsCanceled) //if download is successful.
    25.                 {
    26.                     Debug.Log("file saved as " + localPath);
    27.                 }
    28.                 else //otherwise report error.
    29.                 {
    30.                     Debug.Log(task.Exception.ToString());
    31.                 }
    32.             });
    33.         }
    34.         else //otherwise don't bother.
    35.         {
    36.             Debug.Log("Cannot Download file due to lack of connectivity!");
    37.         }
    38.     }
    The code stops work on iPhones at: FirestoreController.storageRef.Child("bundle").Child(platform).Child(_file).GetFileAsync(...)

    The path to the file is correct, and it works and downloads and saves the correct file on the unity Editor on a Mac. Not sure why it doesn't on an iPhone. The file is also accessible from there on.

    I'm not sure why the iPhone is giving me trouble because the only error message i get from Firebase.Storage is this:


    Code (CSharp):
    1. Device is running on iPhone or Mac
    2.  
    3. <>c__DisplayClass5_0:<GetFile3>b__0(Task)
    4.  
    5. System.Array:UnsafeStore(T[], Int32, T)
    6.  
    7. FirebaseStorageGetter:GetFile3(String)
    8.  
    9. AppUpdateChecker:.ctor()
    10.  
    11. System.Array:UnsafeStore(T[], Int32, T)
    12.  
    13. AppUpdateChecker:CheckForUpdates()
    14.  
    15. <>c:<GooglePlayChecker>b__2_0(Task`1)
    16.  
    17. System.Threading.ContextCallback:Invoke(Object)
    18.  
    19. System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
    20.  
    21. System.Runtime.CompilerServices.MoveNextRunner:Run()
    22.  
    23. System.Action:Invoke()
    24.  
    25. System.Threading.ContextCallback:Invoke(Object)
    26.  
    27. System.Threading.Tasks.AwaitTaskContinuation:RunCallback(ContextCallback, Object, Task&)
    28.  
    29. System.Threading.Tasks.Task:FinishContinuations()
    30.  
    31. System.Threading.Tasks.Task`1:TrySetResult(TResult)
    32.  
    33. System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:Create()
    34.  
    35. <>c:<SignInAnon>b__0_0(Task`1)
    36.  
    37. System.Threading.ContextCallback:Invoke(Object)
    38.  
    39. System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
    40.  
    41. System.Runtime.CompilerServices.MoveNextRunner:Run()
    42.  
    43. System.Action:Invoke()
    44.  
    45. System.Threading.SendOrPostCallback:Invoke(Object)
    46.  
    47. UnityEngine.UnitySynchronizationContext:Exec()
    48.  
    49. UnityEngine.UnitySynchronizationContext:Exec()
    50.  
    51.  
    52. (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    53.  
    54.  
    55. System.AggregateException: One or more errors occurred. ---> Firebase.Storage.StorageException: An unknown error occurred
    56.  
    57.    --- End of inner exception stack trace ---
    58.  
    59. ---> (Inner Exception #0) Firebase.Storage.StorageException: An unknown error occurred<---
    I'm not sure if the the app can't see the file on Firebase Storage, or it can't write to Application.PersistentDataPath because I'm using the wrong format for iOS.

    Things we've already checked for:

    1) Building the iOS app on .NET4.x, required for the Firebase packages we used.
    2) All firebase packages is at the latest version 7.0.2, confirmed from the Package Manager.
    3) The app is build on Arm7 and Arm64, with IL2CPP.
    4) Write permission is set to Internal.

    Are there anything specific to iPhones build settings that I might be overlooking?
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The only Firebase feature I've used before is push notifications, but I seem to remember I had a confusing issue where a feature wasn't working when I copied a debug build directly from my dev machine onto the test device, but suddenly worked fine if I distributed the app through TestFlight (and, later, the app store). I imagine iOS must have some special hooks that are only enabled if you use an "official" install path. (I had no analogous problem on Android.)

    No idea whether that would be relevant for your problem, but if you haven't tried that, it might be worth checking.
     
    EOMedvis likes this.
  3. EOMedvis

    EOMedvis

    Joined:
    Feb 19, 2019
    Posts:
    93
    Hm, can't hurt to try it. Thanks! :D

    EDIT: Problem solved. For iOS i needed to add "file://" before the Application.PersistentDatapath for the save location. :p
     
    Last edited: Jan 15, 2021
  4. tjPark

    tjPark

    Joined:
    Mar 19, 2015
    Posts:
    13
    Thanks for your solution. You saved my tens of hours. Love your mushroom man.
    It would be better mentioned about "file://" thing in Application.PersistentDatapath document or firebase document. How could none of them did that?!
     
    EOMedvis likes this.
  5. ysookim

    ysookim

    Joined:
    Apr 24, 2019
    Posts:
    1
    Thank you !!
    I love mushroom man too.
     
    EOMedvis likes this.
  6. stilkin

    stilkin

    Joined:
    Jan 6, 2021
    Posts:
    4
    I still ran into some ill-defined problems when using the file:// before the Application.PersistentDatapath.

    One should only use it when passing paths to the Firebase library, but not when using regular System.IO methods.

    I also updated all the Firebase libraries to the latest version (8.0.0 at the moment) because there are some initialization fixes in the 7.x patches. Hope that helps someone!
     
    keithAtPlay and EOMedvis like this.
  7. mesmes123

    mesmes123

    Joined:
    Oct 11, 2021
    Posts:
    9
    When you say working "on every platform" do you mean it is working on WebGL editor and build as well ?
     
  8. EOMedvis

    EOMedvis

    Joined:
    Feb 19, 2019
    Posts:
    93
    No only on Android and Android devices. We've yet to try compiling to WebGL, since that wasn't our target. Firebase doesn't work on Windows standalone, so that's also out of the question.
     
  9. WeiWuDe

    WeiWuDe

    Joined:
    Nov 3, 2020
    Posts:
    26
    Thank you, you saved me :)