Why is my SQLite database file not showing any data? - android

Aim -
I am trying to store longitude and latitude data from the geolocation API using React native. I created a .db file put it into the /assets/ folder in android. First, instead of the location data, I am trying to insert or retrieve any kind of data.
ERROR -
It shows that there is no table named Test when I try to console.log() it.
Problem -
Whenever I try to insert data into the database I don't see any new data added and also When I try to read an already populated database I see nothing. Where am I wrong? I am fairly new to this.
What is the response returned by the SQL transaction. I console.log it but couldn't understand.
Where should be the transaction function be located?
I am using DBbrowser for SQLite
OS - MacOS
CODE -
I am using this function to send or receive data.
sendData = () => {
// var SQLite = require('react-native-sqlite-storage')
var db = SQLite.openDatabase({name: 'a', createFromLocation : "~test.sqlite"}, this.openCB, this.errorCB);
db.transaction(txn => {
txn.executeSql(
// "INSERT INTO Test (latitude,longitude) VALUES(?,?)",
'SELECT * FROM Test',
[], //Argument to pass for the prepared statement
(res) => {
// let row = res.rows.(1);
console.log(res);
} //Callback function to handle the result response
);
});
};
// I mapped this button to send data.
<TouchableOpacity onPress={this.sendData} style={styles.button}>
<Text> SEND DATA</Text
</TouchableOpacity>

You won't be able to modify a database stored in the assets folder. The typical method is before ever trying to open the database to insert records, you first check to see if the database exists in your apps data folder (not sure if React has the same folder structures or not). If the database doesn't exist in the data folder, then you copy your clean database from assets to the data folder, then open the database from the data folder. As long as the app isn't deleted off the device, the database in the data folder will persist, along with all of the data you have inserted into it. Once the app has been deleted and reinstalled, the database will have to be copied from assets once again and will be clean, with no new data in it.
I don't know if the same data folder structure applies to React, but in native Android I use:
"/data/data/com.mycompany.myapp/databases/"
OR
DB_PATH = myContext.getFilesDir().getParentFile().getPath() + "/databases/";

Related

Create/Update SQLite database from json file

I'm currently working on an app that maintains a database on device that can be updated via Retrofit at a later date but I'm trying to design a solution that would allow me to cache the current database to put on device when publishing.
Currently this is what happens:
Sqlite database is manually created by hand
Sqlite database is put into assets folder in app
App is run, and database is converted to local database through SQLiteOpenHelper/SQLiteAssetHelper
At a later date, the device syncs with the back-end, grabbing a JSON file and manually updating the newly created database.
I'm trying to replace the first step with something more automated.
Is there a way, say I can create a Gradle task that would call my 'sync' code, grab that JSON, and some way to convert it to a Sqlite database to store within the assets folder?
Or perhaps a way to instead use the JSON directly when building the local database in step 3?
I would rather stay away from any other programs just to keep the project simple to use/update.
Thanks.
If you dont need to cache data page by page( it's mean ur local db save all data from server, and u just need to save current data) just save JSON as String, and on start, parse it again to show offline data, after that, fletch new data if connection is available.
I think you can go with creating the database directly using a JSON file. You can define a JSON file with multiple nodes each corresponding to a version of your database where every node contains all your DDL commands corresponding to that version of your database.
{
"patches": [
{
"version": 1,
"commands": [
"CREATE TABLE User ...",
"CREATE TABLE Login ..."
]
},
{
"version": 2,
"commands": [
"ALTER TABLE User ...",
"DROP TABLE Login ..."
]
}
]
}
This way you would only need to maintain a single JSON file and update that file for every update you publish for your app. If someone installs your app for the first time then all the DDL commands in your JSON file will be executed, otherwise only those commands will be executed that are corresponding to a higher database version than what is already present in the app before the update.
You would also have to update the onCreate and onUpgrade methods of your SQLiteOpenHelper. onCreate method will go through the entire json file and execute all the DDL commands in order(based on version). While onUpgrade will only execute the DDL commands under the nodes that have a higher database version.
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
List<Patch> patches = parseJson(); // Parse the JSON file and get the patches
for (Patch patch : patches) {
int databaseVersion = patch.getVersion();
if (databaseVersion > oldVersion && databaseVersion <= newVersion) {
for (String command : patch.getCommands()) {
database.execSQL(command);
}
}
}
}
If your JSON tree structure will not change often, you can make a PoJo for it with a tool such as jsonschema2pojo. And convert instances using Gson.
You can store this PoJo using Google's new library: Room Persistence Library.
It can save the PoJo for you (You'll need to annotate it with #Entity) in sqlite database, and it can update you on changes in the database.
For more details you can watch the Google I/O presentations.

MySQL to Sqlite sync from PHP to mobile app (iOS/Android)

To sync a mysql database with sqlite database using a PHP web app, I am going to
create a "view" mirror of SQLITE tables in MySQL
select changed data on mirror "view" in MySQL
use mysqldump to dump the sql for sqlite and save it in a file on server
download that file from mobile
import data directly to sqlite
another approach would be not using a middle "view" table and dump data using "SELECT" or mysqldump and parse it on the device or server, so it would be readable by sqlite
is there any disadvantages in creating a mirror "view" for each table that SQLITE needs on client devices? or is there another 'standard 'way to sync these 2 which i did not find on the internet?
Edit: after searching and coding some more finally i decided to go like this:
build "insert into ..." statement for sqlite from PHP on the server and save it to a zipped file
download the file on mobile and insert extracted sql directly to SQLITE
here is the php code for generating mysqldump like output:
/** key [SQLITE column name] => value [MySQL select column] */
$table_structure = array(
'id' => 'id',
'title' => 'title',
'type' => 'COALESCE(type, "")', /** u need to wrap any column that is nullable like this **/
'flags' => 'COALESCE(type, "")', /** u need to wrap any column that is nullable like this **/
'view_field' => 'view_field',
'view_year' => 'view_year',
....
....
'updated_at' => 'UNIX_TIMESTAMP(updated_at)');
$into_query = '';
$into_values = '';
$indexer = 0;
foreach ($table_structure as $sqlite => $mysql) {
$into_query .= (($indexer !== 0)? ',':'').$sqlite;
$into_values .= (($indexer !== 0)? ',",",':'').'"\'",'.$mysql.',"\'"';
$indexer++;
}
$output_filepath = "some where nice";
$query = 'SELECT CONCAT("INSERT INTO '.$table.'('.$into_query.') VALUES(",'.$into_values.',");") FROM '.$table.' ' ... "INTO OUTFILE $output_filepath CHARACTER SET utf8";
I hope it's a good approach and may help someone some day :)
Approach 1: using sqlite db file
whatever step you have mentioned in question is correct. this approach used when you have to send lots of data(many tables) from device to web/php vice versa.
its takes time in slower internet connection as well in 2G. in 3G its fast(its also depends on whatever code you have written at mobile/PHP to upload & download file).
make sure database file size is small if it large then make zip file which include database file.
Approach 2: make using json (SELECT *) parse in device
this one is very long process when you have lost of table which have lots of fields. you have to get data from table one by one, send it to server/php its send back data after process. then you have to again insert data in device table.
this is also depends on INTERNET as well you code. its too slow for devices and take more time.
common things in both approach send/receive data only when its needed or on those which require for devices/PHP. do not send unused data to work fast.

Build SQLite database from JSON file in runtime - is it Good?

I need opinion regarding rendering of data in android app. I have all the data stored in a json file abc.json which is in res > raw folder. i have a class that then reads data from that json file and build SQLite database when the app runs and later on i'm performing all operations like searching the data using sql queries for that database. But i am afraid if thats not a good option and the code is not optimized because code now contains so many functions for adding the items to database.
For example, json file has Authors, books, keywords, references, acknowledgements, subauthors and when the database is built, data is read and a specific function is called for each item. I'm just concerned because of too many functions as one for each item. Like whenever json is parsed for an item, e.g author, it calls addAuthors function to add that to database. Following are 2 of the functions for example.
//Sample function code for adding authors to db
public void addAuthors(Integer id, String Name, String is_corresponding) {
ContentValues value = new ContentValues();
value.put("_id", id);
value.put("NAME", Name);
value.put("IS__CORRESPONDING", is_corresponding);
authors_id = database.insert(TABLENAME_AUTHOR, null, value);
}
//example function for adding keywords to db
public void addKeyWord(String KeyWords, Integer id) {
ContentValues values = new ContentValues();
values.put("KEYWORDS", KeyWords);
values.put("_id ", id);
database.insert(TABLENAME_ABSTRACT_KEY_WORDS, null, values);
}
I need help with optimizing my code. Is there any way to optimize the current code ? Kindly help me with this and suggest some improvements for it. Thanks in advance
I would recommend bundling a sqlite database as an asset in your APK instead of bundling the JSON file and then inserting the data into a database. If your data isn't changing, you can then get rid of all your insert functions. You will also save the cost of creating and populating your database dynamically.
You can use the methods described here to create your database and to copy it from the assets of your APK. Be sure to copy it first before you try to open in in your app -- you can't open it directly as an asset.

Storage of SQLite database using Android and Phonegap

I'm developing a Android Cordova/Phonegap app where I want to use a SQLite database. I used the example from the official documentation.
// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// Populate the database
//
function populateDB(tx) {
tx.executeSql('DROP TABLE IF EXISTS DEMO');
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');
}
// Query the database
//
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
// Query the success callback
//
function querySuccess(tx, results) {
var len = results.rows.length;
console.log("DEMO table: " + len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data = " + results.rows.item(i).data);
}
}
// Transaction error callback
//
function errorCB(err) {
console.log("Error processing SQL: "+err.code);
}
// Transaction success callback
//
function successCB() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(queryDB, errorCB);
}
// device APIs are available
//
function onDeviceReady() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(populateDB, errorCB, successCB);
}
Although this seems to work (the database is created and filled without errors, and I get the written data back with the query), I'm wondering how the database is stored on my device. For debugging I use a hardware phone with Android 4.1.1.
The database is located under /data/data/<myapppackage>/app_database/file__0/0000000000000001.db. Now I wanted to export the database and analyze it manually on my pc with SQLiteManager, but it seems the changes are not written to the db file.
However, when examining the directory /data/data/<myapppackage>/app_database/file__0/ i found the two temporary files 0000000000000001.db-shm and 0000000000000001.db-wal, whose timestamps are changed every time I perform a database operation, but never the db file itself.
My question is, why are the changes never written to the persistent database file? There does not seem to be a way to close a database connection with phonegap, and even killing the app manually doesn't write the changes to the .db file. I'm not sure what I did wrong.
Anyone seeing the problem here?
tx.executeSql('DROP TABLE IF EXISTS DEMO');
This line above deletes the table named DEMO everytime you start your PhoneGap mobile application
And I just wanted to tell you I love your code. It gives a very good clue about "what to do" for anyone's PhoneGap or Cordova application. It will greatly help anyone who is entering the world of SQLite for the first time.
Your code is very clean to read and understand compared to the codes written on Cordova/PhoneGap SQLite plugin official website on GitHub.
My friend, who also works as the CTO of a company, and has a plenty of experience with SQLite, told me that it is not necessary to close a SQLite database connection manually, and also greatly recommended SQLite.
And for anyone else looking for SQLite for PhoneGap/Cordova information -
Let's say you have a table named mytable and want to store values "beautiful" and "dolphin"
When you want to perform an operation on the SQLite of a mobile device, such as a tablet or phone, remember to call it this way
Have the following in your source code
function insertNewLine(tx)
{
tx.executeSql("INSERT INTO mytable (word, meaning) VALUES (?,?)", [ var1 , var2 ]);
}
and store "beautiful" inside var1 and "dolphin" inside var2 and
do the following statement in order to execute the SQL insert statement and then save inside the device.
db.transaction(insertNewLine);
Do not directly call insertNewLine(tx)
Do not directly call tx.executeSql( /* SQL INSERT STATEMENT */ ); in your JavaScript sourcecode
And do not include the values straight into the SQL query statement and then run the SQL statement that includes the values you want to store in the database.
In other words, the following is incorrect
tx.executeSql('INSERT INTO mytable (word, meaning) values (beautiful, dolphin)');
The above is incorrect because the values you want to store, "beautiful" and "dolphin" are included inside the SQL statement. They should be separate.
The following is the correct way to run the INSERT SQL
tx.executeSql("INSERT INTO mytable (word, meaning) VALUES (?,?)", [ var1 , var2 ]);
// Notice that the values you want to store, beautiful and dolphin
// are separate from the SQL INSERT INTO statement
and then perform the entire database transaction by including the following in your JavaScript code
db.transaction(insertNewLine);
not the below code
tx.executeSql("INSERT....."); // this will not save your values onto the device
not the below code either
insertNewLine(tx); // this will not save your values onto the device either.
And to use the SELECT SQL statement, have the following code
// Get all lines in the table
//
function viewthelastglory(tx)
{
tx.executeSql( 'SELECT * FROM CUSTOMTABLE', [], querySuccess, errorcode );
}
// Deal with the lines
//
function querySuccess(tx, results)
{
var len = results.rows.length; var queryresult = "all entries ";
for (var i = 0 ; i < len ; i++)
{
queryresult = queryresult +
" Row - " + i +
" Word - " + results.rows.item(i).word +
" Meaning - " + results.rows.item(i).meaning;
}
// and now, you can use the queryresult variable to use the values
}
function errorcode(errorhaha)
{
alert("Error Code " + errorhaha.code + " Error Message " + errorhaha.message);
}
And then, perform the database transaction
db.transaction(viewthelastglory);
If you are trying to choose one from SQLite, WebSQL and IndexedDB, please remember that I searched around stackoverflow for a while and learned that
Nobody likes IndexedDB because of its complexity
IndexedDB is incompatible with many types and versions of mobile OS
WebSQL has been deprecated by W3C
WebSQL returns 673K results but SQLite returns 1800K results. IndexedDB returns 300K results on Google
Among IndexedDB, SQLite and WebSQL, SQLite is the only one with an official website.
The following command at the command line while you are in the directory of your Cordova project will install the SQLite plugin into your Cordova project
cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin
The solution is : Debug your app with emulator instead of physical device.
Run your app with emulator instead of physical device. You will find your database file in /data/data/YOUR_PACKAGE_NAME/app_database/. You can pull the database file and browse the tables and data.
In WAL mode, any changes are written to the -wal file; the database file itself does not get updated until a checkpoint is done.
If there is a -wal file, you must copy it, too.

what is the exact process of using the Database in phonegap android?

I am new to Phonegap. I am trying to implement an application in Phonegap Android. For the past two days,I am scouting for a proper way of accessing the database and retrieving it from the same.I did not find an answer to my questions
I have learnt that Phonegap does not support SQLLITE but supports the W3C Web SQL Database Specification and W3C Web Storage.
At the same time I noticed few plugins for Phonegap 1.5..which does not exist now. At the same time i found that W3c database provides a limited storage of 5MB for iOS.
I found this SQL Plugin for Phonegap Android PhoneGap-SQLitePlugin-Android Is it advicable to use this or any other method. Please,guide me.
So,if you have any sort of example of accessing the database that can be followed please share it.
I made an app recently that required this, targetting the Android and iOS. You can use a combination of the following ::
1. LocalStorage ::
Check for localStorage
function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}
Set an item into LocalStorage
localStorage.setItem("bar", foo);
or
localStorage["bar"] = foo;
Get an item from LocalStorage
var foo = localStorage.getItem("bar");
or
var foo = localStorage["bar"];
2. SQLite Database (more convenient, more persistive)
Set up your DB
var shortName = 'BHCAppDB';
var version = '1.0';
var displayName = 'BHCAppDB';
var maxSize = 65535;
if (!window.openDatabase){
alert('!! Databases are not supported in this Device !! \n\n We are sorry for the inconvenience and are currently working on a version that will work on your phone');
}
db = openDatabase(shortName, version, displayName,maxSize);
createAllTables(db);
Create your Tables
function createAllTables(db){
db.transaction(function(transaction){
transaction.executeSql("CREATE TABLE IF NOT EXISTS Profile(id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT, gender TEXT,age INTEGER)");
}
Execute an SQL Query
transaction(function(transaction){
var rowCount = 'SELECT * FROM Profile';
transaction.executeSql(rowCount,[],function(transaction,result){
if(result.rows.length == 0){
var sqlString = 'INSERT INTO Profile (name,gender,age) VALUES("自己","Female",18)';
transaction.executeSql(sqlString);
}
});
});
3. Native Storage on all devices
This is the best part of Phonegap. You can call a native plugin class on all the devices using the Phonegap plugin call. During the call, you can pass parameters to the class, and the native class can store your data in the OS itself.
For example :: in iOS, you create a plugin .h & .m class and register it with the Cordova.plist file. Once that's done, you need to send a call to the class from JavaScript using Phonegap. Once the parameters have been received using NSDictionary or any other NSArray type, you can call a CoreData class to store UNLIMITED amounts of data. You'll never run out of memory .
This can be done in a similar fashion for all the rest of the OS's also :)
For Encryption try the following :: SQLCipher
Here is some additional information on working with an existing SQLite database. In this example encrypted.db is that brand new database you create and pragma.
ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'secret'; -- create a new encrypted database
CREATE TABLE encrypted.t1(a,b); -- recreate the schema in the new database (you can inspect all objects using SELECT * FROM sqlite_master)
INSERT INTO encrypted.t1 SELECT * FROM t1; -- copy data from the existing tables to the new tables in the encrypted database
DETACH DATABASE encrypted;

Categories

Resources