I made a cross matching words Unity game for Android devices. Currently I am using an SQLite Database in StreamingAssets folder for the words in the game and everything works great.
The problem is that my database in StreamingAssets folder is easily accessible to anyone.
Is there any way to move and access my database from other folder except StreamingAssets?
I am using the code below to access my database on Android:
string databaseName = "/MyDatabase.db";
StartCoroutine(SetDatabase(databaseName));
return Path.Combine("URI=file:" + Application.persistentDataPath + databaseName);
private IEnumerator SetDatabase(string databaseName)
{
string path = Path.Combine("jar:file://" + Application.dataPath + "!/assets" + databaseName);
UnityWebRequest unityWebRequest = UnityWebRequest.Get(path);
yield return unityWebRequest.SendWebRequest();
if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
AppHelper.Dbg("SetDatabase()", this + ": " +unityWebRequest.error);
/// Retrieve results as binary data.
byte[] data = unityWebRequest.downloadHandler.data;
/// Writes the DB in the persistent memory.
File.WriteAllBytes(Path.Combine(Application.persistentDataPath + databaseName), data);
}
Attached a screenshot of my .apk file showing my database in StreamingAssets folder.
So I found a solution to the problem I had. I add my database in Resources folder and then use the code below to copy it in persistent memory and therefore the database is not visible in the .apk file.
private void CopyDefinitionsDatabaseFromResources()
{
string RESOURCES_DATABASE_NAME = "words.bytes";
string DATABASE_NAME = "words.db";
TextAsset db = Resources.Load<TextAsset>(Path.GetFileNameWithoutExtension(RESOURCES_DATABASE_NAME));
byte[] data = db.bytes;
// copy the database file from resources to persistent app path
string destination = Path.Combine(Application.persistentDataPath, DATABASE_NAME);
// writing file
File.WriteAllBytes(destination, data);
}
Related
I am trying to create a pdf document and write my data in that file. The data is a list of int or uint type. Able to do the same for images but not pdf or doc file. All permissions are given and it works for images. My code is below -
Future <File> createDocFile(Uint8List fileData, String type) async
{
File file = new File(".pdf");
if(await PermissionHandler.checkPermission(Permission.storage)!=true){
Url.toastShow("Storage permission not found.");
await Permission.storage.request();
}
else {
await file.writeAsBytes(fileData);
print("PDF SAVED IN DEVICE");
Url.toastShow("PDF saved in device",Colors.green);
}
}
Whenever you create a new file the device can't automatically find it. You'd have to manually tell the device to refresh for the files. Before you'd have to refresh all the files in the device for it to get updated which was very inefficient, but now you could just send the path of the file that you want to get updated. You can use the media_scanner plugin to do so.
Or If you wanna do it yourself with kotlin then here's the code,
private fun broadcastFileUpdate(path: String){
context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(File(path))))
}
I have a routine that copies a local SQLite database (from the Android Studio Assets folder) to the phone's document directory.
The problem I have is that this code is not very good. Sometimes the database is copied completely, and sometimes it is copied partially, or not at all. Its very buggy and I have no idea on how to improve on it.
Many times I get an error saying that certain tables cannot be found.
Here is the code that Im using:
copyDB() async
{
// Construct a file path to copy database to
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, DBAssistanceClass.databaseName);
print('The DB path is: '+ path);
// Only copy if the database doesn't exist
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound)
{
try
{
print('Copying DB...');
// Load database from asset and copy
ByteData data = await rootBundle.load(
join('assets', DBAssistanceClass.databaseName));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// Save copied asset to documents
await File(path).writeAsBytes(bytes);
}
catch (error)
{
print(error);
}
}
}
This is for flutter, and I cannot find anything at all in dart documentation to assist.
I think if it is important to flush when you write the file. There is an Opening an asset database document in sqflite with a complete example.
I am trying to connect SQLite DB file to my unity project where db file is present in downloads folder but I am unable to get data from tables. How can I connect download folder contain DB file to unity project SQLite. My requirement is able to run a project with downloaded db file which is present in the downloads folder. Please suggest any idea. Thanks in advance. Here is the code I am using for connecting db file to SQLite.
Sample code :
Debug.Log("Call to OpenDB:" + databaseName);
var tempdbPath = Path.GetFullPath("log -29-10-2018 - .db");
var tempdbbytes = File.ReadAllBytes(tempdbPath);
var _filePath = tempdbPath;
ApplicationContext.CurrentDatabasePath = _filePath;
//open db connection
_connectionString = "URI=file:" + _filePath;
(where _filePaht = /Users/deepak/Projects/testproject/test/log -29-10-2018 - .db)
ApplicationContext.TempConnectionString = _filePath;
ApplicationContext.ConnectionString = _connectionString;
Debug.Log("Stablishing connection to: " + _connectionString);
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}
When I connect persistence folder contain db file it's working well, I am getting a problem when I am trying to connect db file present in the downloads folder.
I have a preloaded db file, which is present in c drive in my system. If I connect that db file to unity project and try to get data from tables it didn't get any data and I am not getting any exceptions also. If I open this db file (which is present in c drive) with sqlite admin software it shows data in tables. Please suggest any idea, what I am missing. Here is the code I am using for connecting database to my unity project.
Public void OpenDatabase()
{
var dbfileName = "Testuser.db"
var _filePath = File.GetFullPath(dbfileName);
var _connectionString = "URI=file:" + _filePath;
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
When I am trying to create and read db file in the following manner working well.
Working code :
Public void OpenDatabase()
{
var _filePath = Application.PersistanceDataPath + "/" + "owndbfile.db";
if (!File.Exists(_filePath))
{
WWW loadDB = new WWW("jar:file://" + Application.PersistanceDataPath + "!/assets/" + "owndbfile.db");
while (!loadDB.isDone) { }
// then save to Application.persistentDataPath
File.WriteAllBytes(_filePath, loadDB.bytes);
}
var _connectionString = "URI=file:" + _filePath;
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
Please suggest any idea for reading data from tables, if db file is present in one of the drive in a system instead of a present in "application persistance" path.
Using code to Preserve access to a StorageFolder stolen from Karl Erickson
public static async Task<StorageFolder> GetOrPickAndRememberFolderAsync(string key)
{
if (StorageApplicationPermissions.FutureAccessList.ContainsItem(key))
{
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(key);
}
var picker = new FolderPicker();
picker.FileTypeFilter.Add("*");
StorageFolder folder = await picker.PickSingleFolderAsync();
if (folder != null)
{
StorageApplicationPermissions.FutureAccessList.AddOrReplace(key, folder);
}
return folder;
}
our UWP app is able to browse to and remember the location of a SQLite database chosen by a user. This should give read/write permissions on that folder.
The dbContext is instantiated like this
public dbContext(string dbPath)
{
databasePath = dbPath;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=" + databasePath);
}
This code works if the user chooses the default local storage location for the app.
var picker = new FolderPicker();
picker.FileTypeFilter.Add("*");
StorageFolder folder = await picker.PickSingleFolderAsync();
StorageFolder dbFolder = await GetOrPickAndRememberFolderAsync("LocalDbFolder");
string dbPath = Path.Combine(dbFolder.Path, "MySQLite.db");
using (var db = new dbContext(dbPath))
{
db.Database.Migrate();
}
However if the user chooses any other location (such as their Documents folder) the app fails with the error "SQLite Error 14: 'unable to open database file'."
Why would that be, given the user has given the app explicit permissions on the selected location through the picker?
You can't.
SQLite requires native file access. To use the native file access, you should put the sqlite .db file to the application local folders - Windows.Storage.ApplicationData.Current.LocalFolder or tempfolder.
If you use the file/folder picker, you can get the storagefolder item. But, if the folder is outside of your application, ALL of file accesses are done with OS's broker process. SQLite can't access the such of folders.