I am using an Android tablet with a Xamarin/C# application. With this tablet I am trying to access an SQLite database that resides on my Windows 10 machine. I opted to use the USB/Android vs the Android emulator, and the application still resides on the Windows 10 machine. It seems irrelevant, but I've also tried mapping a drive, sharing the folder, and creating a network connection. Project References
This is the code:
using Microsoft.Data.Sqlite;
using System;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace CicoAndroid
{
public partial class MainPage : ContentPage
{
public ICommand TapCommand => new Command(async (url) => await Launcher.OpenAsync(url));
private readonly string db1 = #"Data Source=\LAPTOP-FJUIC9RR\db\db.sqlite";
public MainPage()
{
InitializeComponent();
}
private void LoginClicked(object sender, EventArgs e)
{
int rows;
try
{
Console.WriteLine("DB1: " + db1);
SqliteConnection conn = new SqliteConnection(db1);
conn.Open(); ***This is the line that is throwing the exception.***
using (SqliteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT COUNT(*) FROM [tblUsers] WHERE USERNAME = 'someUser'";
rows = (int)cmd.ExecuteScalar();
Console.WriteLine("ROWS: " + rows);
cmd.Dispose();
}
conn.Dispose();
}
catch (Exception ex)
{
lblAuth.Text = "FUL: a.c.us" + Environment.NewLine + ex.ToString();
return;
}
I am very very new to Xamarin and C#, and I've tried tens of variations with the code and NuGet SQLite packages. Any help will be greatly appreciated.
Thank you
Xamarin.Forms supports database-driven applications using the SQLite database engine, which makes it possible to load and save objects in shared code.
Article Xamarin.Forms Local Databases describes how Xamarin.Forms applications can read and write data to a local SQLite database using SQLite.Net.
Integrate SQLite.NET into mobile apps by following these steps:
Install the NuGet package.
Configure constants.
Create a database access class.
Access data in Xamarin.Forms.
Advanced configuration.
For more details, you can check document:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/data/databases .
And there is also a sample included in above links, you can check and refer to it's code.
Besides, you can also check document Store data in a local SQLite.NET database.
Related
I'm building an Oculus Go app with Unity but I can't figure out how to save a txt file to the Oculus Storage. I have read everything I've found online about it, including using solutions proposed on this website here and here.
I'm trying to create a text file that records which button from a toggle group was selected by the user.
When I build the same thing for PC the code works but I can't find the files inside the Oculus Go. I have edited the OVR android manifest and have a very simple script made from following a couple of tutorials.
Any help would be appreciated, thank you!
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System.IO;
public class SubmitandWriteButtonOVR : MonoBehaviour
{
//GameObject
public ToggleGroup toggleGroup;
public void onClick()
{
string selectedLabel = toggleGroup.ActiveToggles()
.First().GetComponentsInChildren<Text>()
.First(t => t.name == "Label").text;
//Path of the file
string path = Application.persistentDataPath + "/Answers.txt";
//Create file if it doesn't exist
if (!File.Exists(path))
{
File.WriteAllText(path, "Answers");
}
//Content of the file Get the label in activated toggles
string content = "Selected Answers: \n" + System.DateTime.Now + "\n" + selectedLabel;
//Add some text
File.AppendAllText(path, content);
}
}
There are several things that could be the error here:
1) Try to set your rootpath like this
rootPath = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android", StringComparison.Ordinal));
2) Even if your rootpath is set correctly the file might not show up. Try putting Answers.txt manually onto your GO, write something into Answers.txt from inside your App, restart your go and check again in Explorer if it wrote to your file. I read that it has to do with the Android file system not realizing that this file has been created/updated, so it doesn't show.
3) Make sure you have write permissions on externalSD via PlayerSettings
Here is my solution for a StreamWriter on Android:
private void WriteLogToFile()
{
Debug.Log("Starting to Write Logfile");
string path = Path.Combine(rootPath, "Logs.txt");
StreamWriter writer = new StreamWriter(path, true);
writer.WriteLine("TEST");
writer.Close();
Debug.Log("Logging Done");
}
Try if that, in combination with all of the tips above, helps you to reach your goal and let me know.
I have been following this tutorial in its entirety, on how to store data in a local database. On iOS everything works fine, unfortunately on android i get an exception upon creating a table in my database file. The method for creating the table is:
public CalcDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<Calculation>().Wait();
}
And my custom class for getting the database path on Android is as follows:
public class LocalFileHelper : IFileHelper
{
public string GetLocalFilePath(string filename)
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
path = Path.Combine(path, filename);
if(!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
}
This is the error that im getting from SQLite:
Could not open database file: /data/user/0/com.companyname.XX/files/Calculation.db3 (CannotOpen)
I have tried targeting several different APIs, I have tried to clean and rebuild my solution, and I have tried to reinstall the SQLite-net-pcl NuGet packages across the whole solution. Nothing works.
I have read, that it has to do with permissions, still, I do however find it strange that the official Microsoft tutorial doesn't cover this if it was a thing.
You need to check out the Android Permissions declaration (and grants) for Write and Read to external storage on your device or emulator.
It must be enough.
Make sure to delete bin and obj folders, clean and rebuild solution to get rid of any cached data on app compilation.
I am in the process of implementing access to a SQLite database via SQLCipher in my hybrid Cordova app for Android which uses one custom plugin (i.e. written by me). The SQLCipher documentation - as well as other tutorials on using SQLite in Android - keep referring to Context.getDatabasePath. In my plugin code I store other app files and make extensive use of Context.getFilesDir. In what way is getDatabasePath different from getFilesDir. For instance, does it promise a better chance that the database will persist and not somehow get dumped because the OS decides to create "some more room" by deleting some files stored in Context.getFilesDir?
Both are resolved to the same directory. getDatabasePath calls getDatabasesDir.
getDatabasesDir:
private File getDatabasesDir() {
synchronized (mSync) {
if (mDatabasesDir == null) {
if ("android".equals(getPackageName())) {
mDatabasesDir = new File("/data/system");
} else {
mDatabasesDir = new File(getDataDir(), "databases");
}
}
return ensurePrivateDirExists(mDatabasesDir);
}
}
getFilesDir:
#Override
public File getFilesDir() {
synchronized (mSync) {
if (mFilesDir == null) {
mFilesDir = new File(getDataDir(), "files");
}
return ensurePrivateDirExists(mFilesDir);
}
}
Notice the returned File is resolved by ensurePrivateDirExists in both method, which has the same input directory resolved by getDataDir.
getDataDir
Returns the absolute path to the directory on the filesystem where all
private files belonging to this app are stored.
So, there is NO difference in your case.
Do not forget the returned path can change, as the doc says:
The returned path may change over time if the calling app is moved to
an adopted storage device, so only relative paths should be persisted.
I am trying to create a SQLIte database on Internal Storage in my Xamarin application. I am creating a system for an offline environment where at least 3 applications are inter-connected with shared data. So if one application creates some data the other application should be able to read that.
The Database project is a Portable Class Library which I plan to include in all three applications.
My DbHelper is as follows:
public Database()
{
string folder = "/data/data/Anchor.Main";
_dbPath = System.IO.Path.Combine(folder, "Anchor.db");
try
{
if (!System.IO.Directory.Exists(folder))
{
System.IO.Directory.CreateDirectory(folder); //Getting error here
}
_connection = new SQLiteConnection(_dbPath);
_connection.CreateTable<Orders>();
_connection.CreateTable<Items>();
}
catch(Exception ex)
{ }
}
I get error which says
Access to the path "/data/data/Anchor.Main" is denied.
Following is the stack trace
at System.IO.Directory.CreateDirectoriesInternal (System.String path)
[0x0004b] in <3fd174ff54b146228c505f23cf75ce71>:0 at
System.IO.Directory.CreateDirectory (System.String path) [0x00075] in
<3fd174ff54b146228c505f23cf75ce71>:0 at
anchorapp.db.Helper.Database..ctor () [0x0002e]
I understand this is because of the permissions, but what permissions do I need to set in order to write to the Internal storage from a PCL?
You are accessing Android system folder of "/data/data/Anchor.Main".
Your app internal storage will be in
/data/data/#PACKAGE_NAME#/files
You can use the following code to get the folder to store the database:
// Equal to /data/data/#PACKAGE_NAME#/files
var homePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
_dbPath = System.IO.Path.Combine(homePath, "Anchor.db");
_connection = new SQLiteConnection(_dbPath);
Android and iOS does not work that way. Each platform keeps apps in a sandboxed environment. If you want to create and store data in your app you need to create the path like the following sample:
var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
_dbPath = System.IO.Path.Combine(docFolder, "Anchor.db");
Also set the permissions ReadExternalStorage and WriteExternalStorage in your Android project
Instead of writing to a private folder, you could create the database in a public one. To do so the docFolder would change to:
var docFolder = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "YourDirectoryName");
Please be advised, that if you go that way everyone can see and open the database.
I did this by creating a sharedId within my projects and using the SharedContext to access the databases created by other apps
I have an sqlite database test_db.db i have kept in the www folder i am using cordova cli to build android app on my local machine.
when i am trying to open the database it is opening new database instead of accessing the prepopulated.
I tested this using following code.
// Open the existing database
var db = window.sqlitePlugin.openDatabase({ name : "test_db.db" });
db.transaction(function (tx) {
alert("database opened");
var _strQuery = "select * from mst_users;";
tx.executeSql(_strQuery, [], function (tx, res) {
alert("Populated Successfully with " + res.rows.length + " Records.");
}, CommonError);
}, CommonError, DoNothing);
And every time i am getting an error that table mst_users does not exist but it is there in the prepopulated db.
I have tried various things for achieving this but yet stucked. I want access the data in the prepopulated database .
Any help is really appreciated..