Home > Software design >  Error when running on device, not in Unity editor
Error when running on device, not in Unity editor

Time:01-15

I am trying to upload a new version of my game to my iPhone via Xcode. With this app this has not been a problem before but now I do have a problem.

So I created a new smaller project to test. It works in the editor but not when upload to my iPhone (IOS).

I am running Unity 2021.2.7f1 Apple Silicon.

The problem is related to some missing module so I cannot open the db from IOS.

I think it looks like something with opening the database but I am not sure. The database is copied to the "Application.persistentDataPath" path for sure.

I am running Unity 2021.2.7f1 Apple Silicon.

"dbconn.Open();" is where it fails on IOS but not the Mac. I have not yet tested on Android.

Here is the full code in my test project:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Mono.Data.Sqlite;
using System.Data;
using System.IO;
using System;

public class TestScript : MonoBehaviour
{
public TMP_Text txt_Output;

private string dbPath;
private string myRecord;
private static string fileName;

private static IDbConnection dbconn;
private static string connection, checkDbPath;
private static IDbCommand dbcmd;
private static string sqlQuery;
private static IDataReader reader;

private int recCounter;

void Start()
{
    //dbPath = Application.dataPath   "/StreamingAssets/TestDB.db";

    dbPath = InitDBLocation();

    txt_Output.text = "NU STARTAR VI!";

    DoTheDB();
}

void DoTheDB()
{
    connection = "URI=file:"   dbPath;                                                  //Path to database.
    dbconn = (IDbConnection)new SqliteConnection(connection);                           //creates database connection
    dbconn.Open();

    //sqlQuery = "SELECT MyTable, Name, answer2, answer3, answer4, lvl from questions WHERE id = '"   _idNr.ToString()   "'";
    sqlQuery = "SELECT Name FROM MyTable;";

    dbcmd = dbconn.CreateCommand();
    dbcmd.CommandText = sqlQuery;
    reader = dbcmd.ExecuteReader();

    while (reader.Read())
    {
        myRecord = reader.GetString(0);
        recCounter  ;
    }

    reader.Close();
    dbconn.Close();
    reader = null;
    dbcmd.Dispose();
    dbcmd = null;
    dbconn = null;

    txt_Output.text = "# RECORDS: "   recCounter.ToString();

 }

public static string InitDBLocation()
{
    fileName = "TestDB.db";



#if UNITY_EDITOR
    Debug.Log("\n #if UNITY_EDITOR \n");
    return Application.dataPath   "/StreamingAssets/TestDB.db";

#elif UNITY_ANDROID
        Debug.Log("\n #elif UNITY_ANDROID \n");
        Debug.Log("========= GET ANDROID PATH =========");
        PlayerPrefs.SetString("DB ERROR", "");

        oldCurrentDbPathVersion = PlayerPrefs.GetInt("currentDbPathVersion");

        Debug.Log("oldCurrentDbPathVersion: "   oldCurrentDbPathVersion   " | currentDbPathVersion: "   currentDbPathVersion);

        if (File.Exists(Path.Combine(Application.persistentDataPath, fileName)) && oldCurrentDbPathVersion == currentDbPathVersion)
        {
            Debug.Log("return Path: "   Path.Combine(Application.persistentDataPath, fileName));
            return Path.Combine(Application.persistentDataPath, fileName);
        }
        else
        {
            Debug.Log("Copy Database");

            if (File.Exists(Path.Combine(Application.persistentDataPath, fileName)))
            {
                File.Delete(Path.Combine(Application.persistentDataPath, fileName));
            }

            PlayerPrefs.SetInt("currentDbPathVersion", currentDbPathVersion);

            // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //
            try
            {
                var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, fileName));

                loadingRequest.SendWebRequest();
                while (!loadingRequest.isDone)
                {
                    if (loadingRequest.isNetworkError || loadingRequest.isHttpError)
                    {
                        break;
                    }
                }

                Debug.Log("Write database to persistent");
                File.WriteAllBytes(Path.Combine(Application.persistentDataPath, fileName), loadingRequest.downloadHandler.data);

                Debug.Log("return Path: "   Path.Combine(Application.persistentDataPath, fileName));
                return Path.Combine(Application.persistentDataPath, fileName);
            }
            catch (Exception e)
            {
                PlayerPrefs.SetString("DB ERROR", e.ToString());
                PlayerPrefs.SetString("dbPath", "");
                Debug.LogError("*** FILECOPY ERROR ***\n\n"   e); //"   exception.Message   "\n"   exception.StackTrace);
                return null;
            }

           

            Debug.Log("========= END ANDROID dbPath=========");

            // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //

        }
       

#elif UNITY_IOS

        Debug.Log("\n #elif UNITY_IOS \n");


        Debug.Log("TEST GENERAL: "   Application.streamingAssetsPath);


        // ========= IOS ========= //
        Debug.Log("========= IOS DB PATH =========");
        if (File.Exists(Path.Combine(Application.persistentDataPath, fileName)))
        {
            Debug.Log("\n>>>> DB File.Exists <<<<<<\n");
            return Path.Combine(Application.persistentDataPath, fileName);
        }
        else
        {
            if (File.Exists(Path.Combine(Application.persistentDataPath, fileName)))
            {
                File.Delete(Path.Combine(Application.persistentDataPath, fileName));
            }

            // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //
            try
            {
                System.IO.File.Copy((Path.Combine(UnityEngine.Application.streamingAssetsPath, fileName)), Path.Combine(Application.persistentDataPath, fileName), true);
                Debug.Log("\n return Path: "   Path.Combine(Application.persistentDataPath, fileName));
                Debug.Log("\n To PATH: "   Application.persistentDataPath   "\"   fileName);
               return Path.Combine(Application.persistentDataPath, fileName);
           }
           catch (Exception e)
           {
               Debug.LogError("*** FILECOPY ERROR ***\n\n"   e); //"   exception.Message   "\n"   exception.StackTrace);
                PlayerPrefs.SetString("DB ERROR", e.ToString());
                PlayerPrefs.SetString("dbPath", "");
                return null;
            }
            Debug.Log("========= END IOS dbPath=========");

            // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //
        }
#endif
    }
}

Here is the Xcode log:

2022-01-08 22:41:04.039955 0100 NewSQLitetest[2350:900169]    Built from '2021.2/staging' branch, Version '2021.2.7f1 (6bd9e232123f)', Build type 'Release', Scripting Backend 'il2cpp'
2022-01-08 22:41:04.040632 0100 NewSQLitetest[2350:900169] MemoryManager: Using 'Default' Allocator.
[UnityMemory] Configuration Parameters - Can be set up in boot.config
"memorysetup-bucket-allocator-granularity=16"
"memorysetup-bucket-allocator-bucket-count=8"
"memorysetup-bucket-allocator-block-size=4194304"
"memorysetup-bucket-allocator-block-count=1"
"memorysetup-main-allocator-block-size=16777216"
"memorysetup-thread-allocator-block-size=16777216"
"memorysetup-gfx-main-allocator-block-size=16777216"
"memorysetup-gfx-thread-allocator-block-size=16777216"
"memorysetup-cache-allocator-block-size=4194304"
"memorysetup-typetree-allocator-block-size=2097152"
"memorysetup-profiler-bucket-allocator-granularity=16"
"memorysetup-profiler-bucket-allocator-bucket-count=8"
"memorysetup-profiler-bucket-allocator-block-size=4194304"
"memorysetup-profiler-bucket-allocator-block-count=1"
"memorysetup-profiler-allocator-block-size=16777216"
"memorysetup-profiler-editor-allocator-block-size=1048576"
"memorysetup-temp-allocator-size-main=4194304"
"memorysetup-job-temp-allocator-block-size=2097152"
"memorysetup-job-temp-allocator-block-size-background=1048576"
"memorysetup-job-temp-allocator-reduction-small-platforms=262144"
"memorysetup-temp-allocator-size-background-worker=32768"
"memorysetup-temp-allocator-size-job-worker=262144"
"memorysetup-temp-allocator-size-preload-manager=262144"
"memorysetup-temp-allocator-size-nav-mesh-worker=65536"
"memorysetup-temp-allocator-size-audio-worker=65536"
"memorysetup-temp-allocator-size-cloud-worker=32768"
"memorysetup-temp-allocator-size-gfx=262144"
-> applicationDidFinishLaunching()
-> applicationDidBecomeActive()
GfxDevice: creating device client; threaded=1; jobified=1
Initializing Metal device caps: Apple A13 GPU
Initialize engine version: 2021.2.7f1 (6bd9e232123f)
2022-01-08 22:41:04.410523 0100 NewSQLitetest[2350:900465] fopen failed for data file: errno = 2 (No such file or directory)
2022-01-08 22:41:04.410600 0100 NewSQLitetest[2350:900465] Errors found! Invalidating cache...
2022-01-08 22:41:04.831038 0100 NewSQLitetest[2350:900465] fopen failed for data file: errno = 2 (No such file or directory)
2022-01-08 22:41:04.831115 0100 NewSQLitetest[2350:900465] Errors found! Invalidating cache...
2022-01-08 22:41:05.052099 0100 NewSQLitetest[2350:900169]  Unbalanced calls to begin/end appearance transitions for  <UnityDefaultViewController: 0x103429f00>.
UnloadTime: 1.043667 ms

#elif UNITY_IOS
TestScript:InitDBLocation()
TestScript:Start()

TEST GENERAL: /private/var/containers/Bundle/Application/2FE4741C-1580-4698-9BC1-9512D578CFF6/NewSQLitetest.app/Data/Raw
TestScript:InitDBLocation()
TestScript:Start()

========= IOS DB PATH =========
TestScript:InitDBLocation()
TestScript:Start()


return Path: /var/mobile/Containers/Data/Application/F3747560-C7AD-4FBC-A1C6-F95843F09906/Documents/TestDB.db
TestScript:InitDBLocation()
TestScript:Start()


To PATH: /var/mobile/Containers/Data/Application/F3747560-C7AD-4FBC-A1C6-F95843F09906/DocumentsTestDB.db
TestScript:InitDBLocation()
TestScript:Start()

MissingMethodException:   System.Runtime.InteropServices.Marshal::SetLastWin32Error(System.Int32)
at System.Runtime.InteropServices.CriticalHandle.Cleanup () [0x00000] in <00000000000000000000000000000000>:0
at Mono.Data.Sqlite.SqliteStatement.Dispose () [0x00000] in <00000000000000000000000000000000>:0
at Mono.Data.Sqlite.SqliteCommand.ClearCommands () [0x00000] in <00000000000000000000000000000000>:0
at Mono.Data.Sqlite.SqliteCommand.set_CommandText (System.String value) [0x00000] in <00000000000000000000000000000000>:0
at Mono.Data.Sqlite.SqliteConnection.Open () [0x00000] in <00000000000000000000000000000000>:0
at TestScript.DoTheDB () [0x00000] in <00000000000000000000000000000000>:0

CodePudding user response:

I finally solved this problem based on the above post, see thread in my comment. Comment from Baydogan:

Finally I have found a workaround until unity fixes this bug.

  1. Don't modify any unity editor file. Just build for iOS as usual.
  2. Search for "// System.Void System.Runtime.InteropServices.CriticalHandle::Cleanup()" on xcode project.
  3. Move a few lines below and comment out the line that starts with : "Marshal_SetLastWin32Error_"
  4. DONE

example:

IL_002b:

{      il2cpp_codegen_runtime_class_init_inline(Marshal_tD976A56A90263C3CE2B780D4B1CADADE2E70B4A7_il2cpp_TypeInfo_var);

//    Marshal_SetLastWin32Error_mC871D8DAC36418FAA95AFD23CD2A3ECC94628D1C(G_B6_0, NULL);        il2cpp_codegen_runtime_class_init_inline(GC_t920F9CF6EBB7C787E5010A4352E1B587F356DC58_il2cpp_TypeInfo_var);

    GC_SuppressFinalize_m3352E2F2119EB46913B51B7AAE2F217C63C35F2A(__this, NULL);

    return;

}
  •  Tags:  
  • Related