storesafe/cordova-sqlite-storage

Update to work with cordova-android@7.0.0

tombell opened this issue ยท 43 comments

The android platform directory changed structure with 7.0.0, so some things like the libs/ directory is ending up in the wrong place. Even if I copied the libs into the right directory, there were additional errors of things not being found, when trying to build.

Marked as a bug, thanks for reporting. Hoping to resolve this in the near future. Until then cordova-android@7 should NOT be considered supported.

P.S. The fundamental issue is a problem with adding JAR and NDK library files due to wrong plugin.xml tag used.

Awesome, thanks!

Should be like this?
https://github.com/freakypie/card.io-phonegap/blob/master/plugin.xml#L16-L20

@NeoLSN that looks right to me. For reference: https://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#lib-file

I will investigate further when I get a chance. I wonder if it would work to use arch="*" to mean use library regardless of emulator or device.

Thanks for the hint!

@NeoLSN that looks right to me. For reference: https://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#lib-file

I will investigate further when I get a chance. I wonder if it would work to use arch="*" to mean use library regardless of emulator or device.

Looks like there is a better solution at https://stackoverflow.com/questions/34115571/add-external-jar-library-to-build-cordova-plugin-ionic-framework/34129929#34129929: use lib-file element with no arch setting.

Right now, seems this plugin will change the cordova context when installing it. So after this plugin installed, the other plugins would be install unsuccessfully.

Right now, seems this plugin will change the cordova context when installing it. So after this plugin installed, the other plugins would be install unsuccessfully.

I do not follow, can you please explain further?

The installing order of my plugins is like this.

<plugin name="cordova-plugin-zeroconf" spec="^1.3.0" />
<plugin name="cordova-sqlite-storage" spec="^2.1.3" />
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
<plugin name="ionic-plugin-deeplinks" spec="^1.0.15">

After installing cordova-sqlite-storage, ionic-plugin-deeplinks and ionic-plugin-keyboard would not install successs. The error message is like below.

Installing "cordova-sqlite-storage" for android

installing external dependencies via npm
npm install of external dependencies ok
Dependent plugin "es6-promise-plugin" already installed on android.

Installing "ionic-plugin-deeplinks" for android

Failed to install 'ionic-plugin-deeplinks': Error: ENOENT: no such file or directory, open '<project_root>/platforms/android/AndroidManifest.xml'
    at Object.fs.openSync (fs.js:663:18)
    at Object.fs.readFileSync (fs.js:568:33)
    at Object.parseElementtreeSync (<project_root>/app/platforms/android/cordova/node_modules/cordova-common/src/util/xml-helpers.js:180:27)
    at new AndroidManifest (<project_root>p/platforms/android/cordova/lib/AndroidManifest.js:29:20)
    at AndroidProject.getPackageName (<project_root>/platforms/android/cordova/lib/AndroidProject.js:99:12)
    at Api.addPlugin (<project_root>/platforms/android/cordova/Api.js:223:57)
    at handleInstall (/Users/JasonYang/.nvm/versions/node/v9.3.0/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/install.js:594:10)
    at /Users/JasonYang/.nvm/versions/node/v9.3.0/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/install.js:357:28
    at _fulfilled (/Users/JasonYang/.nvm/versions/node/v9.3.0/lib/node_modules/cordova/node_modules/q/q.js:787:54)
    at self.promiseDispatch.done (/Users/JasonYang/.nvm/versions/node/v9.3.0/lib/node_modules/cordova/node_modules/q/q.js:816:30)

Error: ENOENT: no such file or directory, open '<project_root>/platforms/android/AndroidManifest.xml'

But if I remove the cordova-sqlite-storage. It will work fine.

Maybe this issue is from what you mentioned.
P.S. The fundamental issue is a problem with adding JAR and NDK library files due to wrong plugin.xml tag used.
And it breaks the AndroidStudio project structure, so causes other plugins can not be installed well.
https://github.com/apache/cordova-android/blob/master/bin/templates/cordova/Api.js#L65-L93

@NeoLSN : "Error: ENOENT: no such file or directory, open '<project_root>/platforms/android/AndroidManifest.xml'"
In fact this error message is a direct result of the modified directory structure. To overcome this error message I created a set of aliases, which enables old scripts to find the files back again.

cd /<project_root>/platforms/android
ln -s app/src/main/res .
ln -s app/src/main/AndroidManifest.xml .
ln -s app/src/main/java src

It will make this error message disappear, but I was not able to get the cordova-sqlite-ext running using cordova-android@7.0.0. It always reports "error: package io.liteglue does not exist".
I experimented with several combinations of the instruction in plugin.xml, but always got the same error message.
I would be grateful for any hint (even a temporary manual hack) to get this running. Thank you.

@mmp-schmitt Because you are doing wrong thing. What you are doing is just let the 'add plugin' success, but this action also brakes Android project structure.

@NeoLSN: If this is the wrong thing to do, then what is the right thing to do?
When I look at the resulting apk file (created the wrong way), then I can see that the libraries 'sqlite-connector.jar' and 'libsqlc-native-driver.so' have not been embedded. There is no 'lib' folder any more. So how can I add them to the 'apk'?

@mmp-schmitt This issue is trying to figure out a correct way to add this plugin into new Android project via cordova CLI.

If I would adapt plugin.xml according to the patterns discussed above, like this:

diff --git a/plugin.xml b/plugin.xml
index 0442733..eec9c95 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -34,13 +34,13 @@
         <source-file src="src/android/io/sqlc/SQLiteConnectorDatabase.java" target-dir="src/io/sqlc"/>
 
         <!-- Android-sqlite-connector [jar]: -->
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/sqlite-connector.jar" target-dir="libs"/>
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/sqlite-connector.jar" />
         <!-- Android-sqlite-connector native driver [native libs]: -->
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/arm64-v8a/libsqlc-native-driver.so" target-dir="libs/arm64-v8a"/>
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/armeabi/libsqlc-native-driver.so" target-dir="libs/armeabi"/>
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/armeabi-v7a/libsqlc-native-driver.so" target-dir="libs/armeabi-v7a"/>
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/x86/libsqlc-native-driver.so" target-dir="libs/x86"/>
-        <source-file src="node_modules/cordova-sqlite-storage-dependencies/libs/x86_64/libsqlc-native-driver.so" target-dir="libs/x86_64"/>
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/arm64-v8a" />
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/armeabi" />
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/armeabi-v7a" />
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/x86" />
+        <lib-file src="node_modules/cordova-sqlite-storage-dependencies/libs/x86_64" />
     </platform>
 
     <!-- iOS -->
Brodys-MacBook-Pro:cordova-sqlite-common-dev brodybits$ 

it still works on cordova-android@6 but NOT on cordova-android@7.

I discovered someone made the following change in filionf/cordova-sqlite-legacy@74adc97 to support cordova-android@7 as installed by Cordova 8:

diff --git a/plugin.xml b/plugin.xml
index e5cc6f2..f275f6c 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -35,13 +35,13 @@
         <source-file src="src/android/io/sqlc/SQLiteConnectorDatabase.java" target-dir="src/io/liteglue"/>
 
         <!-- Android-sqlite-connector [jar]: -->
-        <source-file src="src/android/libs/sqlite-connector.jar" target-dir="libs"/>
+        <source-file src="src/android/libs/sqlite-connector.jar" target-dir="app/libs"/>
         <!-- Android-sqlite-connector native driver [native libs]: -->
-        <source-file src="src/android/libs/arm64-v8a/libsqlc-native-driver.so" target-dir="libs/arm64-v8a"/>
-        <source-file src="src/android/libs/armeabi/libsqlc-native-driver.so" target-dir="libs/armeabi"/>
-        <source-file src="src/android/libs/armeabi-v7a/libsqlc-native-driver.so" target-dir="libs/armeabi-v7a"/>
-        <source-file src="src/android/libs/x86/libsqlc-native-driver.so" target-dir="libs/x86"/>
-        <source-file src="src/android/libs/x86_64/libsqlc-native-driver.so" target-dir="libs/x86_64"/>
+        <source-file src="src/android/libs/arm64-v8a/libsqlc-native-driver.so" target-dir="app/libs/arm64-v8a"/>
+        <source-file src="src/android/libs/armeabi/libsqlc-native-driver.so" target-dir="app/libs/armeabi"/>
+        <source-file src="src/android/libs/armeabi-v7a/libsqlc-native-driver.so" target-dir="app/libs/armeabi-v7a"/>
+        <source-file src="src/android/libs/x86/libsqlc-native-driver.so" target-dir="app/libs/x86"/>
+        <source-file src="src/android/libs/x86_64/libsqlc-native-driver.so" target-dir="app/libs/x86_64"/>
 
     </platform>
 

Will work but would need a major release since it would not work on earlier versions of cordova-android.

Best solution is probably to use Gradle.

For next major release (#687) the plan is to use builtin sqlite library on Android/iOS/macOS in this plugin version (cordova-sqlite-storage) and to deal with Android NDK library in cordova-sqlite-ext.

I tried the solution above, but the 'apk' is still missing the libraries 'sqlite-connector.jar' and 'libsqlc-native-driver.so'. I cannot see any folder 'app/libs/' or 'libs' in the 'apk'.

waiting for this issue to be resolved with android@7, i am able to save data in db, but when i fetch from db , it hangs. :(

+1 waiting..

@brodybits This problems has opened also other issues on other frameworks and plugins, like ionic

ionic-team/ionic-plugin-keyboard#304

As mentioned, after installing your plugin we can not install any other plugin. Do you thinkg you can resolve this issue as fast as possible?
This has really big impact on the cordova environment.

@brodybits
another exception running it with cordova 8 and cordova-android 7 I got is this

> cordova build android
cp: copyFileSync: could not write to dest file (code=ENOENT):/home/michi/tmp/abc/platforms/android/res/xml/config.xml

Parsing /abc/platforms/android/res/xml/config.xml failed
(node:26482) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, open '/abc/platforms/android/res/xml/config.xml'
(node:26482) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I will need 1-2 days to issue a special major release to resolve this issue by dropping use of Android-sqlite-connector / Android-sqlite-native-driver. Windows platform will likely be dropped from cordova-sqlite-storage at the same time as discussed in #687.

That would be really great! thx!

I solved this issue by bundling the NDK objects in a JAR file and using lib-file tags in config.xml to add the JAR dependencies on Android. This seems to work fine with both cordova-android@6 and cordova-android@7 on Android 4.x / 5.x / 6.x / 7.x / 8.x.

A better solution would be to use Gradle on Android and podspec on iOS to include the sqlite dependency in a more standard way. The SQLCipher project already supports Android Gradle / iOS podspec so it may make sense to do this on cordova-sqlcipher-adapter plugin version first.

It is also desired to make it optional whether or not to include the external sqlite dependencies for Android in the first place, as discussed in #728. Possibilities under consideration:

  • new "express" plugin version that uses the builtin sqlite libraries instead of an additional build on Android/iOS
  • remove additional sqlite build from next release this plugin version ref: #687

P.S. Similar solution will be needed in other plugin versions such as cordova-sqlite-ext, cordova-sqlcipher-adapter, cordova-sqlite-evcore-extbuild-free, etc.

Thank you for your work on this @brodybits, I'll give this a try and upgrade cordova-android to 7.0.0 later. ๐Ÿ‘

@brodybits just finished testing, and works perfectly! ๐Ÿ‘

@brodybits just finished testing, and works perfectly! ๐Ÿ‘

@tombell thanks again for reporting and testing:)

@brodybits I also tested it, it seems to work on cordova-android@6.4.0, for now I can not test on 7.0.0 because there are other plugins which has also problems with latest version.

THX MAN

THX MAN

@mburger81 absolutely and thanks for the feedback. While I would regard some of the error output to be an issue with the tooling (not clear enough) it is definitely better to avoid this kind of problem in the first place.

In case of any further issues with cordova-android@7 please report here or in a new issue.

Hello, thanks for your work. I updated cordova (with cordova-android@7) today and found this issue creating my app.

Should I downgrade cordova? Or could you help me on how to include it using gradle?

Thanks

Hello, thanks for your work. I updated cordova (with cordova-android@7) today and found this issue creating my app.

@Medtrack I already tested and published a solution for this issue. As I stated in a comment above:

I solved this issue by bundling the NDK objects in a JAR file and using lib-file tags in config.xml to add the JAR dependencies on Android. This seems to work fine with both cordova-android@6 and cordova-android@7 on Android 4.x / 5.x / 6.x / 7.x / 8.x.

In case it does not work for you please give https://github.com/brodybits/cordova-sqlite-storage-starter-app a try. I just updated it to reference the latest version of this plugin and it works for me on Android with Cordova CLI 8 / cordova-android@7.0.0.

Should I downgrade cordova?

Possible but you should not have to do this. You should be able to do cordova plugin add android@6 in case this issue continues to persist for any reason.

Or could you help me on how to include it using gradle?

Gradle for Android would be the best solution. I will probably try this on SQLCipher first since they already support Gradle ref: storesafe/cordova-sqlcipher-adapter#64

In case this issue continues to persist for you then I will need some more information to diagnose what may be going wrong. In case you need private or higher priority support please contact sales@litehelpers.net for more information.

Thank you very much @brodybits
In fact I am using the SQLCipher plugin. I downgraded cordova since I have other issues with custom plugins. I will keep an eye on this issue and try to update everything on my side.
Running cordova platform add android@6 works.

Many thanks for your answer.

@Medtrack I also fixed the SQLCipher plugin version to support cordova-android@7 by referencing AAR (ref: storesafe/cordova-sqlcipher-adapter#64).

Hi @brodybits, it's been a while but it is working now :-)

Thank you very much for your work!!!

For some reason, this is still not working:

cordova platform add android@latest
Using cordova-fetch for cordova-android@latest
Adding android project...
Creating Cordova project for the Android platform:
	Path: platforms/android
	Package: com.chanlhealth.app
	Name: Chanl_Health
	Activity: MainActivity
	Android target: android-27
Subproject Path: CordovaLib
Subproject Path: app
Android project created with cordova-android@7.1.0
Android Studio project detected
Android Studio project detected
Installing "cordova-android-support-gradle-release" for android
Subproject Path: CordovaLib
Subproject Path: app
Installing "cordova-plugin-app-event" for android
cordova-android-support-gradle-release : WROTE  /Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/build.gradle  >  26.+
Installing "cordova-plugin-app-version" for android
Installing "cordova-plugin-browsertab" for android
Plugin dependency "cordova-plugin-compat@1.2.0" already fetched, using that version.
Installing "cordova-plugin-compat" for android
Plugin doesn't support this project's cordova-android version. cordova-android: 7.1.0, failed version requirement: 
      <6.3.0
Skipping 'cordova-plugin-compat' for android
Subproject Path: CordovaLib
Subproject Path: app
Installing "cordova-plugin-compat" for android
Plugin doesn't support this project's cordova-android version. cordova-android: 7.1.0, failed version requirement: 
      <6.3.0
Skipping 'cordova-plugin-compat' for android
Installing "cordova-plugin-device" for android
Installing "cordova-plugin-network-information" for android
Installing "cordova-plugin-splashscreen" for android
Installing "cordova-plugin-statusbar" for android
Installing "cordova-plugin-transport-security" for android
Installing "cordova-plugin-whitelist" for android

               This plugin is only applicable for versions of cordova-android greater than 4.0. If you have a previous platform version, you do *not* need this plugin since the whitelist will be built in.
          
Installing "cordova-plugin-youtube-video-player" for android
Installing "cordova-sqlite-storage" for android
installing external dependencies via npm
npm install of external dependencies ok
Failed to install 'cordova-sqlite-storage': Error: ENOENT: no such file or directory, open '/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/AndroidManifest.xml'
    at Object.fs.openSync (fs.js:646:18)
    at Object.fs.readFileSync (fs.js:551:33)
    at Object.parseElementtreeSync (/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/cordova/node_modules/cordova-common/src/util/xml-helpers.js:180:27)
    at new AndroidManifest (/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/cordova/lib/AndroidManifest.js:29:20)
    at AndroidProject.getPackageName (/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/cordova/lib/AndroidProject.js:99:12)
    at Api.addPlugin (/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/cordova/Api.js:223:57)
    at handleInstall (/usr/local/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/install.js:594:10)
    at /usr/local/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/install.js:357:28
    at _fulfilled (/usr/local/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:787:54)
    at self.promiseDispatch.done (/usr/local/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:816:30)
(node:25575) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, open '/Users/rattkin/Documents/Workspaces/WebStorm/chanlhealth-app-ionic2/platforms/android/AndroidManifest.xml'
(node:25575) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I've tried the cordova-sqlite-storage-starter-app and it adds the platform there without any issues. I'm very confused as to where's the difference. Could it be that other plugins are influencing this?

Hi @sebastian-zarzycki-es it is possible that other plugins can influence your results, also possible that your Android platform project is really messed up. I would recommend you try the following:

First completely remove your Android project (rm -rf ..../platforms/android) and then try your cordova platform add android command again.

If that doesn't work then I recommend that you start with a clean project and add one plugin at a time until you can determine what does and does not work.

Yes, my apologies. From that output, it looked like cordova-sqlite-storage was the culprit, where, in fact, it was a plugin right before that - namely, cordova-plugin-youtube-video-player. Removing the plugin fixed the build.

I have found success overriding the cordova lib check using this hook:

https://gist.github.com/joeljeske/68121fa6d643e0937f50458d0172e16e

This avoids being blocked by a potentially bad plugin and waiting for them to upgrade.

Thanks @joeljeske. I am thinking right now this is something that should be fixed on Cordova itself, open to feedback though.

I'm still having this issue for some reason. Is there something I'm missing?

It's happening on a lot of other plugins still, and it's been ~5 months since 7.0 was released

i'm having the issue aswell with android 7.0, any idea why ?
Can't get UPDATE queries to work ...

After much trial and error, I found the libs path for cordova-android@7 has changed to app/src/main/jniLibs/, so you can do something like:

<source-file src="src/android/libs/armeabi-v7a/foo.so" 
    target-dir="app/src/main/jniLibs/armeabi-v7a/" />

I've fixed this in my cordova-plugin-hello-c example plugin and tested it with cordova-android@7.1.1.

Thanks @dpa99c for the input. Personally I would heavily favor using JAR, or AAR from Mavin, to avoid dependency on the generated directory structure.

This issue is now locked as resolved on this plugin.

In case of further issues with Android NDK libraries I would recommend starting with https://github.com/brodybits/cordova-sqlite-storage-starter-app and adding one plugin at a time to discover which still need to be fixed.

I raised apache/cordova-docs#902 to get this documented for other plugins on Cordova itself and would prefer to keep further discussion there.

I also raised storesafe/cordova-sqlite-storage-help#60 in case anyone has any questions about Android NDK (*.so) libraries related to this plugin.

In case anyone can reproduce an issue with Android NDK libraries on this plugin, with a minimal, complete, and verifiable example (https://stackoverflow.com/help/mcve), then a new issue with the mvce would be appreciated.