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.
- Don't modify any unity editor file. Just build for iOS as usual.
- Search for "// System.Void System.Runtime.InteropServices.CriticalHandle::Cleanup()" on xcode project.
- Move a few lines below and comment out the line that starts with : "Marshal_SetLastWin32Error_"
- 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;
}
