Closed bennyvenassi closed 3 years ago
@bennyvenassi I tested it in my code and the json object works fine on Android. To replicate your code i will need to have the full code of the storage service with the import i don't know where
Storage
is defined
okay, no problem:
import { Injectable } from "@angular/core";
import { Plugins, Capacitor } from "@capacitor/core";
import "@capacitor-community/sqlite";
import { HttpClient } from "@angular/common/http";
import { BehaviorSubject } from "rxjs";
import {
JsonSQLite,
SQLiteConnection,
SQLiteDBConnection,
capEchoResult,
} from "@capacitor-community/sqlite";
import { Note } from "./note.model";
const { CapacitorSQLite, Storage } = Plugins;
const DB_SETUP_KEY = "first_db_setup";
const DB_NAME_KEY = "db_name";
@Injectable({
providedIn: "root",
})
export class StorageService {
dbReady = new BehaviorSubject(false);
dbName = "";
sqlite: SQLiteConnection;
db: SQLiteDBConnection;
isService: boolean = false;
platform: string;
constructor(private http: HttpClient) {}
/**
* Plugin Initialization
*/
initializePlugin(): Promise<boolean> {
console.log('starting sqlite initialization...');
return new Promise((resolve) => {
this.platform = Capacitor.platform;
console.log("*** platform " + this.platform);
const sqlitePlugin: any = CapacitorSQLite;
this.sqlite = new SQLiteConnection(sqlitePlugin);
this.isService = true;
console.log("$$$ in service this.isService " + this.isService + " $$$");
this.setupDatabase();
resolve(true);
});
}
/**
* Echo a value
* @param value
*/
async echo(value: string): Promise<capEchoResult> {
console.log("&&&& in echo this.sqlite " + this.sqlite + " &&&&");
if (this.sqlite != null) {
return await this.sqlite.echo(value);
} else {
return null;
}
}
private async setupDatabase() {
console.log('setting up database');
const dbSetupDone = await Storage.get({ key: DB_SETUP_KEY });
if (!dbSetupDone.value) {
this.downloadDatabase();
} else {
this.dbName = (await Storage.get({ key: DB_NAME_KEY })).value;
let db = await this.createConnection();
if (db) {
this.dbReady.next(true);
}
}
}
private async createConnection(): Promise<SQLiteDBConnection | null> {
console.log('setting up db connection');
if (this.sqlite != null) {
this.db = await this.sqlite.createConnection(
this.dbName,
false,
"no-encryption",
1
);
console.log(this.db);
if (this.db != null) {
this.db.open();
return this.db;
} else {
return null;
}
} else {
return null;
}
}
private downloadDatabase(update = false) {
console.log('downloading database');
this.http
.get("../assets/start_db.json")
.subscribe(async (jsonExport: JsonSQLite) => {
const jsonstring = JSON.stringify(jsonExport);
let isValid = false;
try {
const isValidTry = await CapacitorSQLite.isJsonValid({ jsonstring });
console.log(isValidTry)
isValid = isValidTry.result;
} catch (e) {
console.error(e);
}
console.log(isValid);
if (isValid) {
console.log('dbjson is valid');
this.dbName = jsonExport.database;
try {
await Storage.set({ key: DB_NAME_KEY, value: this.dbName });
await this.sqlite.importFromJson(jsonstring);
await Storage.set({ key: DB_SETUP_KEY, value: "1" });
} catch (e) {
console.error(e);
}
console.log('db set');
// Your potential logic to detect offline changes later
let db = await this.createConnection();
if (db) {
this.dbReady.next(true);
if (!update) {
await db.createSyncTable();
} else {
await db.setSyncDate("" + new Date().getTime());
}
}
}
});
}
}
@bennyvenassi i ran it without the storage
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import {HttpClient} from "@angular/common/http";
import { Plugins, Capacitor } from '@capacitor/core';
import '@capacitor-community/sqlite';
import { SQLiteDBConnection, SQLiteConnection, capSQLiteSet,
capSQLiteChanges, capEchoResult, capSQLiteResult,
capSQLiteValues, JsonSQLite} from '@capacitor-community/sqlite';
const { CapacitorSQLite } = Plugins;
const DB_NAME_KEY = "db-name";
const DB_SETUP_KEY = "db-setup";
@Injectable({
providedIn: 'root',
})
export class StorageService {
dbReady = new BehaviorSubject(false);
dbName = "";
sqlite: SQLiteConnection;
db: SQLiteDBConnection;
isService: boolean = false;
platform: string;
// storage: Storage = new Storage();
constructor(private http: HttpClient) {}
initializePlugin(): Promise<boolean> {
console.log('starting sqlite initialization...');
return new Promise((resolve) => {
this.platform = Capacitor.platform;
console.log("*** platform " + this.platform);
const sqlitePlugin: any = CapacitorSQLite;
this.sqlite = new SQLiteConnection(sqlitePlugin);
this.isService = true;
console.log("$$$ in service this.isService " + this.isService + " $$$");
this.setupDatabase();
resolve(true);
});
}
/**
* Echo a value
* @param value
*/
async echo(value: string): Promise<capEchoResult> {
console.log("&&&& in echo this.sqlite " + this.sqlite + " &&&&");
if (this.sqlite != null) {
return await this.sqlite.echo(value);
} else {
return null;
}
}
private async setupDatabase() {
console.log('setting up database');
// const dbSetupDone = await this.storage.get({ key: DB_SETUP_KEY });
// if (!dbSetupDone.value) {
this.downloadDatabase();
/* } else {
this.dbName = (await this.storage.get({ key: DB_NAME_KEY })).value;
let db = await this.createConnection();
if (db) {
this.dbReady.next(true);
}
}
*/
}
private async createConnection(): Promise<SQLiteDBConnection | null> {
console.log('setting up db connection');
if (this.sqlite != null) {
this.db = await this.sqlite.createConnection(
this.dbName,
false,
"no-encryption",
1
);
console.log(this.db);
if (this.db != null) {
this.db.open();
return this.db;
} else {
return null;
}
} else {
return null;
}
}
private downloadDatabase(update = false) {
console.log('downloading database');
this.http
.get("../../assets/start_db.json")
.subscribe(async (jsonExport: JsonSQLite) => {
const jsonstring = JSON.stringify(jsonExport);
let isValid = false;
try {
const isValidTry = await CapacitorSQLite.isJsonValid({ jsonstring });
console.log(isValidTry)
isValid = isValidTry.result;
} catch (e) {
console.error(e);
}
console.log(isValid);
if (isValid) {
console.log('dbjson is valid');
this.dbName = jsonExport.database;
try {
// await this.storage.set({ key: DB_NAME_KEY, value: this.dbName });
await this.sqlite.importFromJson(jsonstring);
// await this.storage.set({ key: DB_SETUP_KEY, value: "1" });
} catch (e) {
console.error(e);
}
console.log('db set');
// Your potential logic to detect offline changes later
let db = await this.createConnection();
if (db) {
this.dbReady.next(true);
if (!update) {
await db.createSyncTable();
} else {
await db.setSyncDate("" + new Date().getTime());
}
}
}
});
}
}
and call it like this in a Page
const ret = await this._store.initializePlugin();
console.log(">>>> in App Store this.initPlugin " + JSON.stringify(ret))
let result: any = await this._store.echo("Hello World from Store");
console.log(" from Echo " + result.value);
if( result.value === "Hello World from Store" ) {
return true;
} else {
return false;
}
and it works fine
Did you run a npx cap sync
before the 'build` when you have move from one version to the other
@bennyvenassi i do not think the Storage is responsible for. so i do not know what to do. i put this
.get("../../assets/start_db.json")
as in my app the service storage.services.ts
is under app/services
folder
@bennyvenassi I add the Storage plugin and removing the commented lines and it works fine
@bennyvenassi In the service that you provided you never close the connection. so i assume that it is something that you start at the launching of your app and after the connection and the database stayed open. So i also assume that after this you are using another service to interface the database and make query, insert ...
Thank you for your answers! I'm using only the storeage.service.ts to interact with the database. The storage service is supposed to insert the json object as the first start is performed. But it stops at the point validating the json object. Therefore I've included so many console.logs.
E.g. the consolelogs from android studio:
2021-04-04 13:17:14.871 8489-8584/io.vulper.doublenote V/Capacitor: callback: 92374607, pluginId: Device, methodName: getInfo, methodData: {}
2021-04-04 13:17:14.879 8489-8584/io.vulper.doublenote V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 92374608, pluginId: Storage, methodName: get
2021-04-04 13:17:14.879 8489-8584/io.vulper.doublenote V/Capacitor: callback: 92374608, pluginId: Storage, methodName: get, methodData: {"key":"db-setup"}
2021-04-04 13:17:14.906 8489-8543/io.vulper.doublenote D/Capacitor: Handling local request: http://localhost/assets/icon/favicon.png
2021-04-04 13:17:15.390 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 81 - Msg: starting sqlite initialization...
2021-04-04 13:17:15.391 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 84 - Msg: *** platform android
2021-04-04 13:17:15.393 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 88 - Msg: $$$ in service this.isService true $$$
2021-04-04 13:17:15.396 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 110 - Msg: setting up database
2021-04-04 13:17:15.399 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 351 - Msg: >>>> in App this.initPlugin true
2021-04-04 13:17:15.406 8489-8489/io.vulper.doublenote I/Choreographer: Skipped 32 frames! The application may be doing too much work on its main thread.
2021-04-04 13:17:16.125 8489-8584/io.vulper.doublenote V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 92374609, pluginId: Device, methodName: getLanguageCode
2021-04-04 13:17:16.126 8489-8584/io.vulper.doublenote V/Capacitor: callback: 92374609, pluginId: Device, methodName: getLanguageCode, methodData: {}
2021-04-04 13:17:16.135 8489-8543/io.vulper.doublenote D/Capacitor: Handling local request: http://localhost/assets/start_db.json
2021-04-04 13:17:16.162 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 144 - Msg: downloading database
2021-04-04 13:17:16.237 8489-8543/io.vulper.doublenote D/Capacitor: Handling local request: http://localhost/assets/i18n/de.json
2021-04-04 13:17:16.277 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/vendor-es2015.js - Line 284 - Msg: isJsonValid [object Object]
2021-04-04 13:17:16.278 8489-8489/io.vulper.doublenote I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 158 - Msg: false
and for comparison from xcode, where the code works fine:
WebView loaded
⚡️ [log] - Angular is running in development mode. Call enableProdMode() to enable production mode.
⚡️ [log] - Ionic Native: deviceready event fired after 319 ms
⚡️ To Native -> App addListener 18384560
⚡️ To Native -> Device getInfo 18384561
⚡️ To Native -> Storage get 18384562
⚡️ [log] - starting sqlite initialization...
⚡️ [log] - *** platform ios
⚡️ [log] - $$$ in service this.isService true $$$
⚡️ [log] - setting up database
⚡️ TO JS {"value":null}
⚡️ [log] - >>>> in App this.initPlugin true
⚡️ To Native -> Device getLanguageCode 18384563
⚡️ TO JS {"value":"de"}
⚡️ [log] - downloading database
⚡️ To Native -> CapacitorSQLite isJsonValid 18384564
⚡️ TO JS {"result":true}
⚡️ [log] - {"result":true}
⚡️ [log] - true
⚡️ [log] - dbjson is valid
⚡️ To Native -> Storage set 18384565
⚡️ TO JS {}
⚡️ To Native -> CapacitorSQLite importFromJson 18384566
databaseName: doublenote-dbSQLite.db
after dropTables retChanges: 0
after dropIndexes retChanges: 0
after dropTriggers retChanges: 0
⚡️ TO JS {"changes":{"changes":0}}
⚡️ To Native -> Storage set 18384567
⚡️ TO JS {}
⚡️ [log] - db set
⚡️ [log] - setting up db connection
⚡️ To Native -> CapacitorSQLite createConnection 18384568
databaseName: doublenote-dbSQLite.db
⚡️ TO JS {"result":true}
⚡️ [log] - >>> in SQLiteDBConnection dbName doublenote-db
⚡️ [log] - {"dbName":"doublenote-db","sqlite":{}}
I also tried to delete the node_modules and android folder and reinstall the packages, unfortunately that doesnt solve the problem.
What do you mean on which point I should close the connection?
I want my code to the followings steps:
On android dbReady never changes to true, because of the functions at the point, that the json is not valid.
@bennyvenassi I do not understand in the android log the following
2021-04-04 13:17:16.237 8489-8543/io.vulper.doublenote D/Capacitor: Handling local request: http://localhost/assets/i18n/de.json
what is that file ?
@bennyvenassi look t https://github.com/jepiqueau/angular-sqlite-app-starter/tree/refactor
testjson102. For me it is working fine.
@bennyvenassi I do not understand in the android log the following
2021-04-04 13:17:16.237 8489-8543/io.vulper.doublenote D/Capacitor: Handling local request: http://localhost/assets/i18n/de.json
what is that file ?
that log is not from sqlite, i'm using a internationalization plugin and this is the log of the device language.
I'll try tomorrow some more testing...
@bennyvenassi Ok look at my code clone it and see if it works it should
@jepiqueau now i'm really clueless. I just copied theexample repo and it's not working either.
It makes no sense to me, I deleted the node_modules and android folder serveral times now, somehow android won't work.
Android console logs of the example repo:
2021-04-05 12:38:04.548 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/testimportjson-testimportjson-module-es2015.js - Line 142 - Msg: %%%% in TestimportjsonPage this._sqlite [object Object]
2021-04-05 12:38:04.550 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/main-es2015.js - Line 262 - Msg: &&&& in echo this.sqlite [object Object] &&&&
2021-04-05 12:38:04.551 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/vendor-es2015.js - Line 161 - Msg: ECHO in Web plugin [object Object]
2021-04-05 12:38:04.552 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/testimportjson-testimportjson-module-es2015.js - Line 160 - Msg: from Echo Hello World
2021-04-05 12:38:04.553 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/vendor-es2015.js - Line 284 - Msg: isJsonValid [object Object]
2021-04-05 12:38:04.553 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/testimportjson-testimportjson-module-es2015.js - Line 168 - Msg: isJsonValid: Not implemented on Web Platform
2021-04-05 12:38:04.554 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/testimportjson-testimportjson-module-es2015.js - Line 153 - Msg: $$$ runTest failed
and the working xcode logs:
[log] - *** platform ios
⚡️ [log] - $$$ in service this.isService true $$$
⚡️ [log] - >>>> in App this.initPlugin true
⚡️ [log] - **** ionViewWillEnter false
⚡️ [log] - %%%% in TestimportjsonPage this._sqlite [object Object]
⚡️ [log] - &&&& in echo this.sqlite [object Object] &&&&
⚡️ To Native -> CapacitorSQLite echo 37460068
⚡️ TO JS {"value":"Hello World"}
⚡️ [log] - from Echo Hello World
⚡️ To Native -> CapacitorSQLite isJsonValid 37460069
⚡️ TO JS {"result":true}
⚡️ [log] - $$$ dataToImport Json Object is valid $$$
⚡️ To Native -> CapacitorSQLite importFromJson 37460070
databaseName: db-from-jsonSQLite.db
database path /Users/benny/Library/Developer/CoreSimulator/Devices/****/data/Containers/Data/Application/****/Documents/db-from-jsonSQLite.db
after dropTables retChanges: 0
after dropIndexes retChanges: 0
after dropTriggers retChanges: 0
⚡️ TO JS {"changes":{"changes":8}}
⚡️ [log] - full import result 8
@bennyvenassi It seems that you did not update your MainActivity.java file. This is still required for capacitor/core@2.4.7. This will not be required in the 3.0.0
package com.jeep.app.ionic.angular;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import com.getcapacitor.community.database.sqlite.CapacitorSQLite;
import java.util.ArrayList;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(CapacitorSQLite.class);
}});
}
}
i saw this int the following log
2021-04-05 12:38:04.553 6414-6414/com.jeep.app.ionic.angular I/Capacitor/Console: File: http://localhost/testimportjson-testimportjson-module-es2015.js - Line 168 - Msg: isJsonValid: Not implemented on Web Platform
Having declare the plugin it should work
Sorry, yes, you are awesome. while changing the plugin version and deleting the android folder I have totally overseen this. Thank you a lot for your help!!
Hi, I switched from sqlite 2.4 to 2.9.14 and I'm trying to implement it in ionic for iOS and Android. I'm facing the issue, that my code works fine on iOS. On android I'm getting the result "false" from CapacitorSQLite.isJsonValid function and the firsttime database setup isn't performed.
I organized the database interactions in a seperate service file.
The code for the firsttime setup from my service:
and my database json:
{ "database": "doublenote-db", "version": 1, "encrypted": false, "mode": "full", "tables": [ { "name": "notes", "schema": [ { "column": "id", "value": "INTEGER PRIMARY KEY NOT NULL" }, { "column": "title", "value": "TEXT NOT NULL" }, { "column": "note", "value": "TEXT NOT NULL" }, { "column": "color", "value": "TEXT NOT NULL" }, { "column": "created", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" }, { "column": "last_modified", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" } ], "values": [ ] }, { "name": "trash", "schema": [ { "column": "id", "value": "INTEGER PRIMARY KEY NOT NULL" }, { "column": "title", "value": "TEXT NOT NULL" }, { "column": "note", "value": "TEXT NOT NULL" }, { "column": "color", "value": "TEXT NOT NULL" }, { "column": "created", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" }, { "column": "last_modified", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" } ], "values": [ ] }, { "name": "archive", "schema": [ { "column": "id", "value": "INTEGER PRIMARY KEY NOT NULL" }, { "column": "title", "value": "TEXT NOT NULL" }, { "column": "note", "value": "TEXT NOT NULL" }, { "column": "color", "value": "TEXT NOT NULL" }, { "column": "created", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" }, { "column": "last_modified", "value": "INTEGER DEFAULT (strftime('%s', 'now'))" } ], "values": [ ] } ] }
thank you in advance!