capacitor-community / sqlite

⚡Capacitor plugin for native & electron SQLite databases.
MIT License
496 stars 118 forks source link

CapacitorSQLPlugin: Protocol message contained in invalid tag (zero) #363

Closed carlos-claveria closed 1 year ago

carlos-claveria commented 1 year ago

Hi,

This problem occurs when I run the app on a physical device (Android 12). On emulators (Pixel) it works fine.

Searching in the web I found someone with the same problem.

Can somebody help me?

Thank

jepiqueau commented 1 year ago

@carlos-claveria which version of the plugin are you using. Can you share the link of your search on the web. Can you share your package.json file. Is it a new app? which framework are you using ? which gradle SDK ? ...

carlos-claveria commented 1 year ago

It is a new application write in IONIC 6 (gradle SDK 7.2.1)

The error message appears in an alert window after initializing the plugin on a device (android 12). On emulators and browse it seems to work fine.

I found another reference at https://stackoverflow.com/questions/74994479/capacitorsqliteplugin-protocol-message-contained-an-invalid-tag-zero.

My package.json: package.json.txt

Thanks.

protendai commented 1 year ago

Hi, im also facing the same issue on Ionic 6 [Physical Device]. The plugin worked i think for two days and when i updated my app i started having that error when i try to initiate the plugin and create a database let me share my package.json as well package.json.txt

lexedh commented 1 year ago

Me too, please help me

jepiqueau commented 1 year ago

@carlos-claveria @protendai @lexedh Can you send the complete message error printed by android with the lines code error. Can one of you share its app on github so i can reproduce the issue

protendai commented 1 year ago

When i run on Android Studio I captured the log from when i tried to create a connection to the db called app-db

V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 26174901, pluginId: CapacitorSQLite, methodName: createConnection V/Capacitor: callback: 26174901, pluginId: CapacitorSQLite, methodName: createConnection, methodData: {"database":"app-db","encrypted":false,"mode":"no-encryption","version":1,"readonly":false} D/Capacitor: Handling local request: http://localhost/388.d23aef83944a1665.js V/com.getcapacitor.community.database.sqlite.RetHandler: *** ERROR CapacitorSQLitePlugin: Protocol message contained an invalid tag (zero). D/Capacitor: Handling local request: http://localhost/svg/home.svg D/Capacitor: Sending plugin error: {"save":false,"callbackId":"26174901","pluginId":"CapacitorSQLite","methodName":"createConnection","success":false,"error":{"message":"CapacitorSQLitePlugin: Protocol message contained an invalid tag (zero)."}}

E/Capacitor/Console: File: http://localhost/main.f599926d592548c0.js - Line 1 - Msg: ERROR Error: Uncaught (in promise): Error: CapacitorSQLitePlugin: Protocol message contained an invalid tag (zero). Error: CapacitorSQLitePlugin: Protocol message contained an invalid tag (zero). at returnResult (http://localhost/:741:32) at win.androidBridge.onmessage (http://localhost/:716:21)

protendai commented 1 year ago

I think @carlos-claveria can share his app since it's a new one

carlos-claveria commented 1 year ago

Hi,

I have updated the Gradle plugin to 7.3.1 but the problem persists.

I have prepared a simplified version of my application but it also reproduces the error.

You can see it in more detail in the file read.me

Hope this can help.

https://github.com/carlos-claveria/sqlite-cap-error.git

jepiqueau commented 1 year ago

@carlos-claveria @protendai @lexedh I assume that you have the issue when running npm run dist which i have never used. Running with the standard procedure

npm run build
npx cap sync
npx cap copy
npx cap open android

and finish the build in Android Studio i do not see the issue.

jepiqueau commented 1 year ago

@carlos-claveria @protendai running with npm run disp having change the IP address to the one of my Mac it is running just fine so i could not reproduce the error. I assume you are working under Windows

jepiqueau commented 1 year ago

@carlos-claveria Can you remove

      const v = await this.database.getVersion();

and tell me if you still have the issue When i run with Android Studio i see this

2023-01-12 10:24:38.537 9831-9923/io.ionic.starter W/Capacitor/Plugin: getArray calls without a default value will return null in Capacitor 5 instead of an empty array to match iOS behavior
2023-01-12 10:24:38.549 9831-9831/io.ionic.starter I/Capacitor/Console: File: http://localhost/main.0cace0cf2a3ec886.js - Line 1 - Msg: SQLite SQLite 3.34.1 plugin ok

So may be under Windows they may have anticipated this?

carlos-claveria commented 1 year ago

The issue persists. In fact, it occurs before the call to getVersion.

if (!Capacitor.isNativePlatform()) {
      this.isWeb = true;
      const res = await customElements.whenDefined('jeep-sqlite');
    }
    try {
      await this.database.initializePlugin(); // ---------- the exception throw here

      console.log('SQLite Initialize Plugin');
      // const v = await this.database.getVersion();
      // console.log(`SQLite ${v} plugin ok`);
    } catch (error : any) {
      console.error('ERROR: ',error.message);
    }
jepiqueau commented 1 year ago

@carlos-claveria Are you running under Windows ?

jepiqueau commented 1 year ago

@carlos-claveria Can you replace

      this.db = await this.sqlite.createConnection(
        this.dbName,
        false,
        'no-encryption',
        1,
        false
      );

      await this.db.open();

with

      this.db = await this.openDatabase(this.dbName,false,'no-encryption',1,false);

and add the function

  async openDatabase(dbName:string, encrypted: boolean, mode: string, version: number, readonly: boolean): Promise<SQLiteDBConnection> {
        let db: SQLiteDBConnection;
        const retCC = (await this.sqlite.checkConnectionsConsistency()).result;
        let isConn = (await this.sqlite.isConnection(dbName, readonly)).result;
        if(retCC && isConn) {
          db = await this.sqlite.retrieveConnection(dbName, readonly);
        } else {
          db = await this.sqlite
                    .createConnection(dbName, encrypted, mode, version, readonly);
        }
        await db.open();
        return db;
  }

and tell me if it is fixed

carlos-claveria commented 1 year ago

The issue persists:

 async openDatabase(dbName:string, encrypted: boolean, mode: string, version: number, readonly: boolean): Promise<SQLiteDBConnection> {
    console.log('OPEN DATABASE');
    let db: SQLiteDBConnection;

    const retCC = (await this.sqlite.checkConnectionsConsistency()).result;
    console.log({retCC});  // <--------------------------- never execute ---------------------------------
    let isConn = (await this.sqlite.isConnection(dbName, readonly)).result;
    console.log({isConn});
    if(retCC && isConn) {
      db = await this.sqlite.retrieveConnection(dbName, readonly);
      console.log('OK RETRIEVE');

    } else {
      db = await this.sqlite
                .createConnection(dbName, encrypted, mode, version, readonly);
      console.log('OK CREATE');

    }
    await db.open();
    return db;
}
jepiqueau commented 1 year ago

@carlos-claveria I do not have any glue on what is going on as i cannot replicate the issue with the app you sent which is working fine. Could you remove the android folder as well the www folder of your app and redo

npx cap add android
npm run build
npx cap sync
npx cap copy
npx cap open android

once in Android Studio go to Preferences->Build, Execution, Deployment ->Build Tools -> Gradle and set the Gradle JDK to 11 and Apply go to File-> Project Structure -> Project -> Android Gradle Plugin Version set to 7.2.2

then Build -> Clean Project File -> Sync Project with Gradle Files Build -> Rebuild Project Launch the App Launch

and tell me if it works if not you have to debug it yourself and tell me on which line is the error

carlos-claveria commented 1 year ago

I have followed your instructions, still getting the error. I don't know android studio or java well but I think I found where the exception occurs. I send you a screen copy. cap-sqlite-error

jepiqueau commented 1 year ago

@carlos-claveria seems they anticipate capacitor 5 i will have a look but i can't do anything before Sunday thanks for your debugging

carlos-claveria commented 1 year ago

Thank you for your excellent work and dedication to the project. We will wait for version 5.

jepiqueau commented 1 year ago

@carlos-claveria i am back home to night looking on my computer screen (not on my mobile screen) .What it strange is that you go to that line mean that the implementation is null which it should not. So can you in Android Studio place a break point in line 47 and 51 of CapacitorSQLitePlugin.java and run-> debug app the execution should stop on the first or the second break point and in the debug console press step over once ,twice and look at the value Can you send me that value Can you also put a break point in RetHandler class line 22 and give me the value for TAG and message Thanks for helping as i could not reproduce the error.

carlos-claveria commented 1 year ago

I have synced, cleaned and rebuilt the project following your instructions above.

In the first execution I have put the break points in lines 47 and 51. The exception occurred in line 51:

cap-sqlite-2

In the second execution I removed the previous breakpoints and put it in line 22 of the RetHandler, with the following result:

cap-sqlite-1

On Monday I will test the application with other devices in case there is any relationship with the android version. At the moment I have detected it in an OPPO ColorOS 12.1 (Android 12).

jepiqueau commented 1 year ago

@carlos-claveria can you try to modify the capacitor.config.ts as follow

const config: CapacitorConfig = {
  appId: 'com.jeep.app.ionic.angular.sqlite',
  appName: appName,
  webDir: 'www',
  bundledWebRuntime: false,
  //  hideLogs: true,
  plugins: {
    CapacitorSQLite: {
      androidIsEncryption: false,
      androidBiometric: {
        biometricAuth : false,
        biometricTitle : "Biometric login for capacitor sqlite",
        biometricSubTitle : "Log in using your biometric"
      },
    }
  }
};
jepiqueau commented 1 year ago

@carlos-claveria it seems that it is caused by the masterKeyAlias so if you are not using encryption the modification on the capacitor.config.ts should make the deal. This is also why this happen on some device and not on some others (i have a Samsung running Android13) or on emulators depending on how they have implemented this feature. May be your OPPO device needs some upgrades?

jepiqueau commented 1 year ago

@carlos-claveria this is what i got from the web. may be you could try

Uninstalling and reinstalling didn't work but going into app settings and clearing data (cache was already empty) actually solved it. Will this then happen to all users when upgrading? – 
[Mathias Rönnlund](https://www.raguice.com/?_=%2Fusers%2F457123%2Fmathias-r%25c3%25b6nnlund%23DaWY0SIBOdFHVTBB0lGf%2FuDSnXCYs9R6eA%3D%3D)
 Sep 29, 2022 at 18:13
1
I believe I had as similar issue to do with this. Android backed up the some preference information pertaining to Enrypted Preferences library between installs. If android restores this data/key from backup it won't work with the newly installed app. Try adding android:allowBackup="false" to your manifest and android:dataExtractionRules="@xml/data_extraction_rules" for Android 12 excluding prefs from backup info on data extraction rules - [developer.android.com/guide/topics/data/…](https://www.raguice.com/?_=%2Fguide%2Ftopics%2Fdata%2Fautobackup%23DaWY0SIBOdFQRCdH1VGZ%2FuCakHGL79h8cWd5EA0%3D#include-exclude-android-12). I cannot say for sure whether updating an app will have issues – 
[Mark](https://www.raguice.com/?_=%2Fusers%2F4252352%2Fmark%23DaWY0SIBOdFHVTBB0lGf%2FuDSnXCYs9R6eA%3D%3D)
 Sep 29, 2022 at 19:05

look at this dataextractionrules-in-android12

jepiqueau commented 1 year ago

@carlos-claveria look also here autobackup

jepiqueau commented 1 year ago

@carlos-claveria the shared preference files are stored under data/data/com.YOURPACKAGE/shared_prefs/ with in your case com.YOURPACKAGE = io.ionic.starter. the file i used to store the masterKeys is sqlite_encrypted_shared_prefs.xml

hope all this will help you to sort out your problem.

carlos-claveria commented 1 year ago

I made the modifications in capacitor.config.ts and now it works! Thank you very much for your help.

jepiqueau commented 1 year ago

@carlos-claveria I am glad that we finally find the solution. May be this error will come back for one using database encryption but for the time being i didn't here anything. So i will close the issue

metalsadman commented 1 year ago

@carlos-claveria can you try to modify the capacitor.config.ts as follow

const config: CapacitorConfig = {
  appId: 'com.jeep.app.ionic.angular.sqlite',
  appName: appName,
  webDir: 'www',
  bundledWebRuntime: false,
  //  hideLogs: true,
  plugins: {
    CapacitorSQLite: {
      androidIsEncryption: false,
      androidBiometric: {
        biometricAuth : false,
        biometricTitle : "Biometric login for capacitor sqlite",
        biometricSubTitle : "Log in using your biometric"
      },
    }
  }
};

how to do this with capacitor.config.json, I"m using cap4, was working then suddenly on new build I'm getting this message. nvm, this worked for me:

"plugins": {
    "CapacitorSQLite": {
      "androidIsEncryption": false,
      "androidBiometric": {
        "biometricAuth": false,
        "biometricTitle": "Biometric login for capacitor sqlite",
        "biometricSubTitle": "Log in using your biometric"
      }
    }
  }