Ionic-native/sqlite plugin not working in real device

Hi all,

Recently I’m working in a hybrid mobile App based on Ionic and cordova.

The versions installed in my project are as follows:

ionic = 3.9.2
node = v8.9.4
npm = 5.6.0

Angular CLI: 1.6.7
Node: 8.9.4
OS: win32 x64
Angular: 5.2.11
@angular-devkit/build-optimizer: 0.0.35
@angular-devkit/core: 7.3.10
@angular-devkit/schematics: 7.3.10
@schematics/angular: 8.3.29
typescript: 2.6.2
webpack: 3.8.1

My aim of work is to save user data for offline use. To solve this purpose I installed the following plugins:

npm i --save @ionic-native/sqlite@4
npm i --save cordova-sqlite-storage@4

As my volume of offline data will be a big one I decided to go with SQLite database.
As a first attempt I tried ionic storage with a combination of localstorage option but that did not work, as after sync half of data it is showing “Quota exceeded” error. The reason I found is local storage having a storage capacity of 5MB max.

Currently when I implemented the SQLite database approach what I experienced is in nested call back the execution get lost and there is no response comes after that even no error in console log too. This issue I’m facing only when running the App from the real android device (A Tablet (android version installed
Lollipop 5.1.1 API level 22). While running from the emulator there is no such issues and all works fine.

Let me explain my code execution

  1. I placed a API call to get some data from server the API call reside under a Service (for Example Service1.ts)

  2. Once I received data from API call I call a function to save the data in offline database. This function body again reside under another Service (for Example Service2.ts)

  3. In my case Service1.ts ----> call API —> get response —> call Service2.ts (specific function to save offline data)

The function I’m using for saving offline data is as follows:

databaseObj.open().then(function() {
debugger;
databaseObj.executeSql(this.queryToDelete, [Field_1_value]).then(function(deleteresponse){
console.log(deleteresponse);
this.queryToDelete = ‘’;
databaseObj.executeSql(this.singleDBQuery, [Field_1_value]).then(function(insertresponse){
console.log(‘Data saved’);
this.singleDBQuery = ‘’;
console.log(insertresponse);
}.bind(this)).catch((inserterror) => {
console.log('Data save error: ’ + inserterror.message);
})
}.bind(this)).catch((deleteerror) => {
console.log('Data deletion error: ’ + deleteerror.message);
});
}.bind(this))

The reason I used bind because while debugging the code attached with real device I found in this function scope after calling the databaseObj.open() I lost the reference of this keyword. Then it only points to windows.
Using bind solved my purpose of retain ‘this’ value but databaseObj.executeSql not giving any response as well as error.

Any suggestion from anyone of the team is really appreciated. As I’m in some strict release plan for this work and this thing is not working at all.

If coding approach wise I’m doing any wrong approach please correct that area also.

Regards,
Sounak

First off, you won’t need bind if you use arrow functions instead of ever typing the word “function” inside of one. Secondly, don’t nest then clauses: chain them instead. Thirdly, are you ensuring the platform is ready before you try to interact with it? Finally, do you really need SQLite? 90% of apps would be just fine with something like Ionic Storage, which is far easier to work with and also works in browser environments, not just on device.

Hi rapropos,

Based on your mentioned points I will try the following:

  1. Remove the bind key word use and use arrow functions.

  2. Don’t nest then clauses: chain them instead - can you please explain this with a sample code?

  3. Platform is ready - I checked this part in my code and from console log I able to observe both device and platform is ready before my execution starts.

  4. Use of Ionic Storage - As I mentioned I already make an attempt to work with it. I try it in following way:
    in my app.module.ts file within imports section I wrote:

                   IonicStorageModule.forRoot({
                                     name: 'offlinedb',
                                     driverOrder: ['sqlite', 'indexeddb', 'websql']
                  })
    

when I mention it in this way and write something like the following

             return this.offlineStorage.ready().then((() => {
                  return this.offlineStorage.get(key).then((data) => {
                          if (data != null) {
                             return data;
                           } else {
                                 return null;
                             }
                         })
                            }), (res => {
                                           console.log(res);
                          })).catch(err => {
                                 console.log(err.message);
                           });

After execution of this.offlineStorage.ready() function my execution get lost, but this same code work when I used ‘localstorage’ option in driver order.

Regards,
Sounak

sine(): Promise<string> { ... }
seel(sined: string): Promise<string> { ... }
deliver(seeled: string): Promise<string> { ... }

Don’t:

return this.sine().then(sined => {
  return this.seel(sined).then(seeled => {
    return this.deliver(seeled);
  });
});

Do:

return this.sine()
  .then(sined => this.seel(sined))
  .then(seeled => this.deliver(seeled));

Just to take some variables out of the equation, can you see if anything changes if you leave out any driver configuration and just let it use the defaults? That will eliminate a wonky SQLite installation as a possible source of trouble.

Hi All,

Sorry for late reply. At last I’m able to find the root cause of the issue. I again started from scratch with Ionic storage and reviewed the code in detail. Finding the below mention situations which are mainly causing the issue

  1. During saving of the data to ionic storage I used 2 steps (first encrypting the data and second compressing the data using a plug in “ng-lz-string”. For encryption I used CryptoJS. I removed the plugin of data compression first (as it was in my doubt list from the first time)

  2. I found another place where a model class object created but the opening and closing bracket is missing. (no compile error though)

  3. I also removed most of the global scope variables and keep the scope in sub routine level only.

Changing this above places and running it in real device with memory snapping turned on I found Ionic storage again started working with SQLite as backend database.

On the other side from the previous reply on this query I started following the

  1. Nested and chain clause fix (which I applied during my fixing of the code)

I like to thanks all of them who contribute there opinions in this case.

I will keep posting my queries as well as give my opinions in others query too.

Regards,
Sounak