3

I am currently testing a hybrid Cordova/Android app with AdMob test ads. The app uses one custom - i.e. in-house - plugin from which I access the Google Play Services AdMob API. The relevant bits of the plugin.xml file are as follows

<platform name="android">
 <preference name="PLAY_SERVICES_VERSION" default="17.2.0"/>
 <preference name="ADMOB_APP_ID" default="ca-app-pub-...."/>

 <framework src="com.android.support:appcompat-v7:27.1.0" />
 <framework src="com.google.android.gms:play-services-ads:17.2.0"/>

The config.xml file for the app declares the following

 <preference name="android-minSdkVersion" value="23" />
 <preference name="android-targetSdkVersion" value="28" />

The Java code to load and show rewarded video ads follows the discussion here.

While this works what bothers me here is that I am using a rather ancient play-services-ads API. The problem is that if I try to upgrade to the latest API according to the instructions shown here. My modified plugin.xml file reflecting the changes needed to use the latest APIs

<platform name="android">
  <preference name="PLAY_SERVICES_VERSION" default="18.3.0"/>
  <preference name="ADMOB_APP_ID" default="ca-app-pub-..."/>

  <framework src="com.android.support:appcompat-v7:28.0.0" />
  <framework src="com.google.android.gms:play-services-ads:18.3.0"/>

The problem is that I am no longer able to compile the app. Cordova CLI reports a string of issues which I show below

iled with exit code 1 Error output: Note: path\to\app\platforms\android\CordovaLib\src\org\apache\cordova\engine\SystemCookieManager.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. path\to\app\platforms\android\app\src\main\AndroidManifest.xml:22:18-86 Error: Attribute application@appComponentFactory value=(androidx.core.app.CoreComponentFactory) from [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 is also present at [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 value=(android.support.v4.app.CoreComponentFactory). Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:4:5-21:19 to override.

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ':app:processDebugManifest'.

    Manifest merger failed : Attribute application@appComponentFactory value=(androidx.core.app.CoreComponentFactory) from [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 is also present at [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 value=(android.support.v4.app.CoreComponentFactory). Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:4:5-21:19 to override.

I narrowed down the problem to gms:play-services-ads which appears to pull in androidx libraries that are not compatible with the old style android libraries. The helpful suggestion from Gradle above - ** add tools:replace="android:appComponentFactory ** did not help since the tools:replace attribute of the application node was not recognized.

The solution I have implemented that has worked is as follows

  • I created a build-extras.gradle file under path/to/myapp/platforms/android with the lines

    android.useAndroidX=true android.enableJetifier=true

  • As a stopgap I used this plugin which deals with the incompatibilities between androidx and android libraries. While this works I am not too keen on using additional plugins. I suspect all this plugin does is ensure that the AndroidManifest.xml is correct but I am unable to see how. I'd be most grateful to anyone who might be able to explain what needs to be done to get things to work without additional plugins.

DroidOS
  • 8,530
  • 16
  • 99
  • 171

4 Answers4

10

Just read that : https://cordova.apache.org/announcements/2020/06/29/cordova-android-9.0.0.html

To be sure :

  • Clear your gradle cache directory (in home/.gradle/caches)
  • Remove and add the android platform
  • Check your requirement following the above article ones

Then :

Add the following in your config.xml :

<preference name="AndroidXEnabled" value="true" />
<preference name="GradlePluginKotlinEnabled" value="true" />
<preference name="GradlePluginKotlinCodeStyle" value="official" />
<preference name="GradlePluginKotlinVersion" value="1.3.50" />

(AndroidXEnabled preference add jetifyer and androidX in the gradle.properties)

And your build should now works

Lucas
  • 169
  • 2
  • 8
  • for all the solution out there, this is the only one that works. But for me, I just added https://www.npmjs.com/package/cordova-plugin-androidx-adapter plugin and it works like a charm – dev-jim May 06 '21 at 06:11
3

For the benefit of anyone who runs into this thread - if you have a Cordova app with several third party plugins you are probably better off using the dpa99 androidx adapter that I mention above. If, like me, you only rely on your own plugin switching to using AndroidX in place of the old style Android support libraries is easy.

Step 1

In path/to/project/platforms/android create a file named build-extras.gradle and edit it to contain the following

android.useAndroidX=true
android.enableJetifier=false

The first line is self explanatory. To understand enableJetifier consider first this statement

The standalone Jetifier tool migrates support-library-dependent libraries to rely on the equivalent AndroidX packages instead.

in the Google documentation. Given that you are considering spinning your own because you do not use other, external, Cordova plugins you do not need to enable Jetifier.

Step 2

With this done all that is left to do is to replace

<framework src="com.android.support:appcompat-v7:28.0.0" />

in your own plugin.xml file with

<framework src="androidx.appcompat:appcompat:1.0.0" />

Step 3

Finally proceed to replace any older native Android libraries - e.g. Play Services Ads - that you are currently using with the latest versions which now use AndroidX. Now run cordova build android and you have completed the transition!

DroidOS
  • 8,530
  • 16
  • 99
  • 171
  • As expected, the androidx-adapter plugin is quite useless. Adding the androidx framework as you pointed out to a plugin.xml solved the build problems, thank you sir. – andreszs Apr 16 '22 at 00:34
  • I am surprised that there are still people using Cordova. Cordova was good in its time but has lost steam now. There are far better options – DroidOS Apr 18 '22 at 09:57
0

What that plugin does is to search all plugins in node_modules and patch all the plugin code usages and dependencies to use the Android X equivalent.

So you can update all the plugins you use that use old android support libraries instead of android X, or use a tool such as jetifier that does the same the plugin does, or keep using the plugin.

jcesarmobile
  • 51,328
  • 11
  • 132
  • 176
0

Here's the short and easy way of doing it

"To prevent build failures caused by including different versions of Play Services library components." https://github.com/dpa99c/cordova-android-play-services-gradle-release

"This Cordova/Phonegap plugin enables AndroidX in a Cordova project" https://github.com/dpa99c/cordova-plugin-androidx

"If your Cordova project contains plugins/libraries which reference both the Android Support Library and AndroidX, your Android build will fail because the two cannot live side-by-side in an Android build." https://github.com/dpa99c/cordova-plugin-androidx-adapter

Ps: i'm not the maintainer

Eric
  • 9,870
  • 14
  • 66
  • 102