Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[+use case: auto-reset of permissions] Overriding compileSDK version has been removed #1373

Closed
3 tasks done
shankari opened this issue Oct 29, 2021 · 8 comments · Fixed by #1431
Closed
3 tasks done

Comments

@shankari
Copy link

shankari commented Oct 29, 2021

Bug Report

Problem

Overriding compileSDK version has been removed in cordova-android@10.x
#1310 (comment)

I see that this was an intentional change, but @breautek said that

The stance that we took is "We'll make the change, release it, and if it becomes a problem, then we'll bring back the independent settings". So I'd like to understand your use case better.

Here's the use case. I wasn't sure if this was a bug since the change was intentional, but it is arguably a regression, and is inconsistent with the documentation, so I went ahead and chose "bug" instead of "feature request".

What is expected to happen?

I can include

+    <framework src="androidx.core:core:$ANDROIDX_CORE_VERSION"/>
+    <preference name="ANDROIDX_CORE_VERSION" default="1.7.0"/>

in my plugin

What does actually happen?

When I add that plugin and compile the app, I get the error

Execution failed for task ':app:checkDebugAarMetadata'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
   > The minCompileSdk (31) specified in a
     dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
     is greater than this module's compileSdkVersion (android-30).
     Dependency: androidx.core:core:1.7.0.
     AAR metadata file: /Users/kshankar/.gradle/caches/transforms-3/553b5caab8c99faefbf90799c7dc70a3/transformed/core-1.7.0/META-INF/com/android/build/gradle/aar-metadata.properties.

Information

Starting in December, android will start resetting permissions of apps that have not been brought into the foreground "for a while". This will happen irrespective of the phone's android version (https://developer.android.com/topic/performance/app-hibernation).

It only applies to apps whose target SDK is Android 11+ (API 30+), but the google play min API requirements are 30+ now for new apps and will be 30+ for app updates in November (https://developer.android.com/distribute/best-practices/develop/target-sdk)

If such a new or updated app reads location in the background, even if it is installed on an Oreo phone, it will stop working "soon after" December.
https://developer.android.com/topic/performance/app-hibernation#effects

If the app use case requires background location access, it can ask users to explicitly authorize such access. The recommended authorization method involves using new functionality in PackageManagerCompat and IntentCompat (https://developer.android.com/topic/performance/app-hibernation#handle-hibernation-android10-lower).

This new functionality is introduced in version 1.7.0 of the androidx core libraries
https://developer.android.com/jetpack/androidx/releases/core#1.7.0

However, it looks like v1.7.0 of the core libraries have a minCompileSdk of 31. The default cordova SDK_VERSION is 30.

So, when I compile my app after upgrading the androidx dependency in my plugin, I get

Execution failed for task ':app:checkDebugAarMetadata'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
   > The minCompileSdk (31) specified in a
     dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
     is greater than this module's compileSdkVersion (android-30).
     Dependency: androidx.core:core:1.7.0.
     AAR metadata file: /Users/kshankar/.gradle/caches/transforms-3/553b5caab8c99faefbf90799c7dc70a3/transformed/core-1.7.0/META-INF/com/android/build/gradle/aar-metadata.properties.

Command or Code

  1. To any plugin.xml add
+    <framework src="androidx.core:core:$ANDROIDX_CORE_VERSION"/>
+    <preference name="ANDROIDX_CORE_VERSION" default="1.7.0"/>
  1. add the plugin to a cordova app
  2. cordova build android

I could not find a way to override the compileSDK version. Per the cordova documentation, using cdvCompileSdkVersion should work, but it doesn't seem to.

$ npx cordova run android -- --gradleArg=-PcdvCompileSdkVersion=31
...
* What went wrong:
Execution failed for task ':app:checkDebugAarMetadata'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
   > The minCompileSdk (31) specified in a
     dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
     is greater than this module's compileSdkVersion (android-30).
     Dependency: androidx.core:core:1.7.0.
     AAR metadata file: /Users/kshankar/.gradle/caches/transforms-3/553b5caab8c99faefbf90799c7dc70a3/transformed/core-1.7.0/META-INF/com/android/build/gradle/aar-metadata.properties.
...
BUILD FAILED in 790ms

I'm going to try and workaround this by mucking around with gradle files, but as the documentation says
"In general, it is discouraged that you edit the contents of this folder because it is easy for those changes to be lost or overwritten."

Environment, Platform, Device

  • OSX 11.6
  • android
  • build fails, so Device is N/A

Version information

  • OSX 11.6
  • Android Studio 2020.3.1 Patch 3
  • cordova-android 10.1.0
Output of cordova info
Cordova Packages:

    cli: 10.0.0
        common: 4.0.2
        create: 3.0.0
        lib: 10.1.0
            common: 4.0.2
            fetch: 3.0.1
            serve: 4.0.0

Project Installed Platforms:

    android: 10.1.0
    ios: 6.2.0

Project Installed Plugins:

    @havesource/cordova-plugin-push: 2.0.0
    cordova-plugin-advanced-http: 3.2.2
    cordova-plugin-androidx-adapter: 1.1.3
    cordova-plugin-app-version: 0.1.12
    cordova-plugin-badge: 0.8.8
    cordova-plugin-customurlscheme: 5.0.2
    cordova-plugin-device: 2.0.3
    cordova-plugin-em-datacollection: 1.6.0
    cordova-plugin-em-jwt-auth: 1.6.4
    cordova-plugin-em-server-communication: 1.2.3
    cordova-plugin-em-serversync: 1.2.5
    cordova-plugin-em-settings: 1.2.2
    cordova-plugin-em-transition-notify: 1.2.6
    cordova-plugin-em-unifiedlogger: 1.3.3
    cordova-plugin-em-usercache: 1.1.3
    cordova-plugin-email-composer: 0.9.2
    cordova-plugin-file: 6.0.2
    cordova-plugin-inappbrowser: 5.0.0
    cordova-plugin-ionic-keyboard: 2.2.0
    cordova-plugin-ionic-webview: 5.0.0
    cordova-plugin-ionic: 5.5.1
    cordova-plugin-local-notification: 0.9.0-beta.3
    cordova-plugin-x-socialsharing: 6.0.3
    es6-promise-plugin: 4.2.2
    phonegap-plugin-barcodescanner: 8.1.0

Environment:

    OS: macOS 11.6 (20G165) (darwin 20.6.0) x64
    Node: v14.18.1
    npm: 6.14.15

android Environment:

    android:
ERROR: Command failed with ENOENT: android list target
spawn android ENOENT


ios Environment:

    xcodebuild:
Xcode 13.1
Build version 13A1030d


Project Setting Files:

    config.xml:
<?xml version='1.0' encoding='utf-8'?>
<widget android-versionCode="42" id="edu.berkeley.eecs.emission" ios-CFBundleVersion="42" version="3.1.0" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>emission</name>
    <description>
        A commute pattern tracker and carbon footprint estimator.
    </description>
    <author email="shankari@eecs.berkeley.edu" href="https://e-mission.eecs.berkeley.edu">
        E-Mission Team
  </author>
    <content src="index.html" />
    <access origin="*" />
    <hook src="hooks/before_prepare/download_translation.js" type="before_prepare" />
    <preference name="webviewbounce" value="false" />
    <preference name="UIWebViewBounce" value="false" />
    <preference name="DisallowOverscroll" value="true" />
    <preference name="android-minSdkVersion" value="22" />
    <preference name="BackupWebStorage" value="none" />
    <preference name="emSensorDataCollectionProtocolApprovalDate" value="2016-07-14" />
    <preference name="GradlePluginGoogleServicesEnabled" value="true" />
    <preference name="GradlePluginGoogleServicesVersion" value="4.3.3" />
    <config-file parent="/manifest/application" target="AndroidManifest.xml">
        <meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
        <meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
        <meta-data android:name="google_analytics_ssaid_collection_enabled" android:value="false" />
        <meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />
    </config-file>
    <config-file parent="FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED" target="*-Info.plist">
        <true />
    </config-file>
    <config-file parent="GOOGLE_ANALYTICS_IDFV_COLLECTION_ENABLED" target="*-Info.plist">
        <false />
    </config-file>
    <config-file parent="GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS" target="*-Info.plist">
        <false />
    </config-file>
    <feature name="StatusBar">
        <param name="ios-package" onload="true" value="CDVStatusBar" />
    </feature>
    <platform name="ios">
        <hook src="hooks/after_platform_add/ios/ios_copy_locales.js" type="after_platform_add" />
        <resource-file src="GoogleService-Info.plist" />
        <preference name="WKWebViewOnly" value="true" />
        <preference name="WKSuspendInBackground" value="false" />
        <preference name="AutoHideSplashScreen" value="true" />
    </platform>
    <platform name="android">
        <hook src="hooks/before_build/android/android_copy_locales.js" type="before_build" />
        <preference name="android-minSdkVersion" value="22" />
        <preference name="android-targetSdkVersion" value="30" />
        <preference name="AndroidXEnabled" value="true" />
        <resource-file src="google-services.json" target="app/google-services.json" />
        <hook src="hooks/before_build/android/android_set_provider.js" type="before_build" />
        <config-file parent="/manifest/application" target="AndroidManifest.xml">
            <uses-library android:name="org.apache.http.legacy" android:required="false" />
        </config-file>
    </platform>
    <icon src="resources/icon.png" />
</widget>

    package.json:
--- Start of Cordova JSON Snippet ---
{
  "platforms": [
    "android",
    "ios"
  ],
  "plugins": {
    "@havesource/cordova-plugin-push": {
      "ANDROID_SUPPORT_V13_VERSION": "28.0.0",
      "FCM_VERSION": "18.+",
      "IOS_FIREBASE_MESSAGING_VERSION": "~> 6.32.2"
    },
    "cordova-plugin-ionic-keyboard": {},
    "cordova-plugin-app-version": {},
    "cordova-plugin-file": {},
    "cordova-plugin-device": {},
    "cordova-plugin-customurlscheme": {
      "URL_SCHEME": "emission",
      "ANDROID_SCHEME": " ",
      "ANDROID_HOST": " ",
      "ANDROID_PATHPREFIX": "/"
    },
    "cordova-plugin-email-composer": {
      "ANDROID_SUPPORT_V4_VERSION": "27.+"
    },
    "cordova-plugin-x-socialsharing": {
      "PHOTO_LIBRARY_ADD_USAGE_DESCRIPTION": "This app requires photo library access to share photos on social media.",
      "PHOTO_LIBRARY_USAGE_DESCRIPTION": "This app requires photo library access to share photos on social media."
    },
    "cordova-plugin-inappbrowser": {},
    "cordova-plugin-local-notification": {},
    "cordova-plugin-ionic": {
      "APP_ID": "e0d8cdec",
      "CHANNEL_NAME": "Production",
      "UPDATE_METHOD": "none",
      "UPDATE_API": "https://api.ionicjs.com",
      "MAX_STORE": "2"
    },
    "cordova-plugin-advanced-http": {},
    "cordova-plugin-ionic-webview": {
      "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
    },
    "cordova-plugin-em-jwt-auth": {
      "AUTH_VERSION": "19.2.0"
    },
    "cordova-plugin-em-server-communication": {},
    "cordova-plugin-em-serversync": {},
    "cordova-plugin-em-settings": {},
    "cordova-plugin-em-transition-notify": {},
    "cordova-plugin-em-unifiedlogger": {},
    "cordova-plugin-em-usercache": {},
    "cordova-plugin-androidx-adapter": {},
    "phonegap-plugin-barcodescanner": {},
    "cordova-plugin-em-datacollection": {
      "LOCATION_VERSION": "18.0.0",
      "ANDROIDX_CORE_VERSION": "1.7.0"
    }
  }
}
--- End of Cordova JSON Snippet ---

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@shankari
Copy link
Author

I can confirm that removing those lines from the plugin and then readding it made the build successful.

$ npx cordova build android
BUILD SUCCESSFUL in 9s

@shankari
Copy link
Author

tried to hack around this by changing platforms/android/app/build.gradle to

        compileSdkVersion 31

Causes the error

> Task :app:compileDebugJavaWithJavac FAILED
An exception has occurred in the compiler (1.8.0_252). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.AssertionError: annotationType(): unrecognized Attribute name MODULE (class com.sun.tools.javac.util.UnsharedNameTable$NameImpl)

@breautek
Copy link
Contributor

breautek commented Oct 29, 2021

Setting android-targetSdkVersion preference will set both the target and compile sdk version.

Using API 31 tooling has known issues and requires some breaking changes. So API 31 is not something cordova currently supports.

@shankari
Copy link
Author

shankari commented Oct 29, 2021

I understand that setting the targetSDKVersion preference will set both target and compile SDKs. However, I don't want to bump up to target SDK 31 prematurely. Google doesn't require it, and it has significant breaking changes for my app.

Notably:

  • "motion sensor rate limiting"
  • foreground service launch restrictions

I just want to compile against API 31 so I can use the new version of the androidx library, but still target API 30

@shankari
Copy link
Author

For the record, I also looked into re-implementing the Compat implementations instead of using the androidx library, but they seem non-trivial. In particular:
https://developer.android.com/reference/androidx/core/content/IntentCompat#createManageUnusedAppRestrictionsIntent(android.content.Context,%20java.lang.String)

SDK 23 through 29, this method will generate an intent with action Intent.ACTION_AUTO_REVOKE_PERMISSIONS and the package as the app with the Verifier role that can resolve the intent.

I'm not sure what that app is in all of the older versions.

@shankari
Copy link
Author

shankari commented Oct 30, 2021

Upgrading to Java 11 fixes the error above. I can now compile and run.

$ echo $JAVA_HOME
/Applications/Android_Studio.app/Contents/jre/Contents/Home

$ $JAVA_HOME/bin/java --version
openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
OpenJDK 64-Bit Server VM (build 11.0.10+0-b96-7281165, mixed mode)

$ npx cordova build android
> Configure project :app
Adding classpath: com.google.gms:google-services:4.3.3
WARNING:: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed in version 7.0 of the Android Gradle plugin.
For more information, see http://d.android.com/r/tools/update-dependency-configurations.html.
WARNING:: Using flatDir should be avoided because it doesn't support any meta-data formats.

> Task :CordovaLib:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :app:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

BUILD SUCCESSFUL in 22s
49 actionable tasks: 8 executed, 41 up-to-date
Built the following apk(s):
	.../native_code_upgrade/platforms/android/app/build/outputs/apk/debug/app-debug.apk

shankari added a commit to shankari/e-mission-data-collection that referenced this issue Oct 30, 2021
This will enable us to call methods in the androidx compat libraries
that give users the option to turn off "auto-reset" of permissions for apps
that are not used very often.

Auto-reset permission background:
https://developer.android.com/topic/performance/app-hibernation

The most recent version of the androidx libraries requires API 31
e-mission/e-mission-docs#680 (comment)

This is a workaround to use API 31 in cordova now
apache/cordova-android#1373
@shankari
Copy link
Author

shankari commented Oct 30, 2021

cordova android team, as you can see, I have fixed this for my individual plugin by introducing a custom gradle file.

But given that @breautek said:

The stance that we took is "We'll make the change, release it, and if it becomes a problem, then we'll bring back the independent settings".

and

Isn't these libraries independent of the compile SDK? Looking at the android docs at a variety of different androidx packages, I don't ever recall (nor can I find anything that states you need a specific compileSdk) to use them.

I hope that this concrete use case of an androidx package that requires a specific compileSdk helps you revisit your original decision.

I'd even be open to making the change myself and submitting a PR if this is consistent with the long-term vision of the maintainers.

I am not familiar with the innards of the cordova codebase, but I think I found the PR with a similar change (e.g. #1212) so it doesn't sound too terrible (famous last words?!)

@breautek breautek added this to To Do in Release Plan - 11.0.0 via automation Mar 16, 2022
@breautek breautek moved this from To Do to Discussion in Release Plan - 11.0.0 Mar 16, 2022
@breautek breautek moved this from Discussion to In Progress in Release Plan - 11.0.0 May 16, 2022
@breautek breautek added this to the 11.0.0 milestone May 16, 2022
@breautek
Copy link
Contributor

We are looking to re-introduce the independent setting. The details will be in the PR at #1431 (currently WIP, but pretty stable).

It may work slightly different than the setting that was in cordova-android 9.x.

Namely we are looking to default the compile SDK to whatever what the target SDK is, unless explicitly configured otherwise.

In otherwords:

  • If the target & compile sdk is not configured, it will default to the cordova-android default.
  • If the user sets the target sdk, the compile SDK will match.
  • If the user sets both the target sdk & compile sdk, cordova will accept those values as is.
  • If the user only sets compile, cordova will default target to the cordova-androi default, but will accept the user configured compile sdk.

In all cases where cordova accepts a user-defined value, cordova will accept is as is, including if the configured values produces invalid settings, such as a target sdk > compile sdk.

Feedback is welcome on the PR #1431.

Release Plan - 11.0.0 automation moved this from In Progress to Done May 18, 2022
shankari added a commit to shankari/e-mission-data-collection that referenced this issue Aug 19, 2023
In android 10, the cordova team removed support for `compileSdkVersion`
However, in order to support auto-reset of permissions, we needed to use a
later SDK than the target.

After filing an issue in the cordova-android repo, we added this grade file as
a workaround. However, they have now reintroduced it in android 11
apache/cordova-android#1373 (comment)
*and* our compile and target SDKs have caught up anyway

So we can remove the workaround.

More detail at:
e-mission/e-mission-phone#1016 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants