I am coding a Xamarin Android application, and am getting an error when trying to create a SQLite database.
Here is my code:
string applicationFolderPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "CanFindLocation");
string databaseFileName = System.IO.Path.Combine(applicationFolderPath, "CanFindLocation.db");
SQLite.SQLite3.Config(SQLite.SQLite3.ConfigOption.Serialized);
var db = new SQLiteConnection (databaseFileName);
Here is the error that I am getting:
SQLite.SQLiteException: Could not open database file: /data/data/com.xamarin.docs.android.mapsandlocationdemo2/files/CanFindLocation/CanFindLocation.db (CannotOpen)
I have the same code working in another Xamarin application and would like to know if the exception has something to do with the name of the package?
Thanks in advance
Does the path folder path that you are providing to SQLite exist? If you haven't created the CanFindLocation folder then opening a connection to that path will fail.
Try:
string applicationFolderPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "CanFindLocation");
// Create the folder path.
System.IO.Directory.CreateDirectory(applicationFolderPath);
string databaseFileName = System.IO.Path.Combine(applicationFolderPath, "CanFindLocation.db");
SQLite.SQLite3.Config(SQLite.SQLite3.ConfigOption.Serialized);
var db = new SQLiteConnection (databaseFileName);
My problem is related to added the option of "SQLiteOpenFlags.Create" during the initialization.
SQLiteAsyncConnection database = new SQLiteAsyncConnection(dbPath, SQLiteOpenFlags.Create);
Related
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 am trying to implement an offline map feature in an android WebView-based app:
Using DownloadManager, I download an sqlite database file (of a structure like .mbtiles) from our webserver, which contains blobs of the map tile images (the "offline map") and store it in the android external storage through
public void downloadMap() {
downloadManager = (DownloadManager) getActivity().getSystemService(Activity.DOWNLOAD_SERVICE);
DownloadManager.Request r = new DownloadManager.Request(Uri.parse("http://sry.youtoknow.idontwant/map.sqlite"));
r.setDestinationInExternalFilesDir(getContext(), "map", "map.sqlite");
downloadManager.enqueue(r);
}
The Download seems to work perfectly well.
I register a BroadcastReceiver to receive DownloadManager.ACTION_DOWNLOAD_COMPLETE and store the path to "map.sqlite" using SharedPreferences.
To access the database from JavaScript for using the tile images in the WebView, I intercept XHRequests by checking for a custom fictive schema name customhttp: in the URL:
webView.setWebViewClient(new WebViewClient() {
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
if (!url.startsWith("customhttp:")) {
return null;
} else {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SQLiteDatabase db = SQLiteDatabase.openDatabase(preferences.getString("map_uri", Environment.getExternalStorageDirectory().getPath() + "berlin.sqlite"), null, SQLiteDatabase.OPEN_READONLY);
}
}
});
My problem is that I seem to implement openDatabase() in a wrong way as I get the following unpleasant error with the corresponding line, but can't figure out why:
E/SQLiteLog(#####): (14) cannot open file at line ##### of [##########]
E/SQLiteLog(#####): (14) os_unix.c:#####: (2) open(//file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite) -
E/SQLiteDatabase(#####): Failed to open database 'file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite'.
E/SQLiteDatabase(#####): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
[...]
The file exists, is not corrupt and its path seems to be correct. I was able to open the file using an SQLite viewing app.
Question: Why does my Code not work; how can I make it work?
I am aware that there exist at least three very similar questions with the above error message here, but they are not that specific, detailed and/or do not exactly fit my needs. I also didn't manage to solve the problem after reading this article:
http://blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/.
Thank you very much for your help!
UPDATE:
I tried creating a new database using SQLiteDatabase.openOrCreateDatabase() in external storage in order to compare it to the original database. It was not created - instead I surprisingly confronted the same error message (could not open database).
Then I tried again to open a new database, this time in RAM, using SQLiteDatabase.openOrCreateDatabase(":memory:", null) and it did not throw any error.
Thus I begin to think that the problem is some access restriction to external storage or a mistake when addressing external storage rather than the database file itself.
I finally managed to find the mistake, a quite sobering one.
I received DownloadManager.ACTION_DOWNLOAD_COMPLETE and stored the URI to the downloaded database in SharedPreferences for later reference inside the shouldInterceptRequest method using:
...
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
if (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
editor.putString("map_uri", c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
editor.commit();
}
}
c.close();
In shouldInterceptRequest I then called
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SQLiteDatabase db = SQLiteDatabase.openDatabase(preferences.getString("map_uri", Environment.getExternalStorageDirectory().getPath() + "map.sqlite"), null, SQLiteDatabase.OPEN_READONLY);
and thereby passed the URI to openDatabase, not the Path alone.
I now Uri.parse(preferences.getString("map_uri", ...)).getPath() and everything works. The map loads.
Thank you very much for your help!
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..
To open prepopulated db in cordova project, you need to do 3 steps:
Copy .db file into main www directory
Install this plugin and use copy method(this will copy the .db file
to the specified directory for your os/device)
Use this plugin to open the .db file
Thats it... :)
Hello I got the solution for this question.
while opening the database in the folling code
var db = window.sqlitePlugin.openDatabase({ name : "test_db.db" });
Add a parameter like this
var db = window.sqlitePlugin.openDatabase({ name : "test_db.db", createFromLocation : 1 });
Then it will take the database which you have kept in the www folder.
I want to access a hsqldb database using android, but i get this error everytime java.sql.SQLException: Database lock acquisition failure: lockFile: org.hsqldb.persist.LockFile#dc61f9b4[file =/home/user/db/jade.lck,
this is my connexion class:
private static final String BDD_DRIVER = "org.hsqldb.jdbcDriver";
private static final String BDD_URI = "jdbc:hsqldb:file:home/user/db/jade;shutdown=true";
private static final String BDD_LOGIN = "sa";
private static final String BDD_PASS = "";
and this is how i get the connection:
Class.forName(BDD_DRIVER).newInstance();
connexion = DriverManager.getConnection(BDD_URI, BDD_LOGIN, BDD_PASS);
thank you for helping me.
When you get the error that you reported, it means the hsqldb.jar is present and an attempt was made to connect to the database. You must report the full error because after the file name, it includes the reason why there was a failure.
The full error means the directory indicated by jdbc:hsqldb:file:home/user/db/ does not exist, or it is a read-only directory where the .lck file cannot be created.
In order to narrow down the cause, you should find the correct absolute path by trying to list the existing .script file using a Java file method. An absolute path starts with the / character. You can then try to open the database as readonly, which does not create a .lck file. If this is successful, you can try to open the database normally.
i have xxx.db (SQLite file) where i want to add him to my android app
in my android app under src i open new directory where i add "test.db"
then in my app what should i write in order to get the db ?
String myPath = "com.countryCityGame/databases/test.db";
SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
i am sure mypath is spelled wrong ' what is the current position of the dp file once the app is inside the emulator .
should i insert the db into the manifest or somehing else ?
thanku
All databases that stored on phone not on SDCard are located in /data/data/com.PackageName/databases/test.db
See this tutorial for using your own database in Android