apache/cordova-android

android-targetSdkVersion preference not honoured

breautek opened this issue ยท 21 comments

Bug Report

Problem

Using the android-targetSdkVersion preference does not work.

What is expected to happen?

The project should use the desired android sdk version as defined in the preference, or fallback to the platform default if not set.

What does actually happen?

The preference is not considered, and the target sdk always gets set to 28.

Information

The code that appears to gets the desired target can be found here:

// Get valid target from framework/project.properties if run from this repo
// Otherwise get target from project.properties file within a generated cordova-android project
module.exports.get_target = function () {
function extractFromFile (filePath) {
var target = shelljs.grep(/\btarget=/, filePath);
if (!target) {
throw new Error('Could not find android target within: ' + filePath);
}
return target.split('=')[1].trim();
}
var repo_file = path.join(REPO_ROOT, 'framework', 'project.properties');
if (fs.existsSync(repo_file)) {
return extractFromFile(repo_file);
}
var project_file = path.join(PROJECT_ROOT, 'project.properties');
if (fs.existsSync(project_file)) {
// if no target found, we're probably in a project and project.properties is in PROJECT_ROOT.
return extractFromFile(project_file);
}
throw new Error('Could not find android target in either ' + repo_file + ' nor ' + project_file);
};

Originally discovered after I suggested to use the android-targetSdkVersion preference on #830

Command or Code

This is the full config.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.breautek.cordova.api29" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>HelloCordova</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
    <preference name="android-targetSdkVersion" value="29" />
</widget>

Environment, Platform, Device

Ubuntu
Android

Version information

Cordova 9.0.0 (cordova-lib@9.0.1)
cordova-android 8.1.0
Ubuntu 18.04

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
erisu commented

@breautek I believe placing <preference name="android-targetSdkVersion" value="29" /> in the global scope is not read.

In the code, the platform is explicitly passed in as a parameter so it tries to find it inside <platform name="android"> element.

There is a conditional on the return where it would check in the global scope if nothing was returned, but maybe something is being returned and causes the conditional to skip and not check global.

I would recommend testing to verify if it at least works inside the <platform name="android"> element.

I would recommend testing to verify if it at least works inside the element.

I'll try this, but should it also work as a child of <widget> as well? Every other preference I've used does.

erisu commented

Theoretically, it probably should not because it is explicitly an Android only configuration that would never be share to other platforms. It could but this would be more of an implementation discussion.

Anyways, if it works, we could either update the docs to be more clear where it should be declared or decide if it should be acceptable as a child element to widget.

If it still doesn't work, even in the platform android element, then we could decide on if it should work in both and then fix it based on that information.

I have confirmed moving the preference tag to a child of the android platform tag does appear to fix the issue.

I see cdvTargetSdkVersion=29 in my gradle.properties file, and for good measure I added a printout to also confirm that gradle runtime contains a value of 29 for target SDK.

I can agree on adjusting the documentation to make this clear that the platform-specific preferences needs to be a child of the respective <platform> tag.

Sadly, still not working for me even with that preference inside platform:

Checking the license for package Android SDK Platform 28 in /opt/android-sdk-linux/licenses
License for package Android SDK Platform 28 accepted.
Preparing "Install Android SDK Platform 28 (revision: 6)".
Warning: Failed to read or create install properties file.

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Failed to install the following SDK components:
      platforms;android-28 Android SDK Platform 28
  Install the missing components using the SDK manager in Android Studio.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 3m 22s
Command finished with error code 1: /app/platforms/android/gradlew :app:bundleRelease,-b,/app/platforms/android/build.gradle
/app/platforms/android/gradlew: Command failed with exit code 1 Error output:
FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Failed to install the following SDK components:
      platforms;android-28 Android SDK Platform 28
  Install the missing components using the SDK manager in Android Studio.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

My config.xml:

.....
<platform name="android">
        <preference name="android-minSdkVersion" value="19" />
        <preference name="android-targetSdkVersion" value="29" />
        <config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml" xmlns:android="http://schemas.android.com/apk/res/android">
            <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification" />
        </config-file>
        <allow-intent href="market:*" />
        <resource-file src="google-services.json" target="google-services.json" />
        <resource-file src="resources/android/icon/drawable-mdpi-icon.png" 
        ....
    </platform>
....

@almothafar if you run cordova requirements android

You should see the following output:

Requirements check results for android:
Java JDK: installed 1.8.0
Android SDK: installed true
Android target: installed android-29,android-28
Gradle: installed /usr/share/gradle/bin/gradle

Can you confirm if android-29 is listed? If it's missing then there might be something wrong with the android sdk installation.

When I do sdkmanager --list I get:

Installed packages:=====================] 100% Computing updates...             
  Path                 | Version | Description                    | Location             
  -------              | ------- | -------                        | -------              
  build-tools;29.0.2   | 29.0.2  | Android SDK Build-Tools 29.0.2 | build-tools/29.0.2/  
  platform-tools       | 29.0.4  | Android SDK Platform-Tools     | platform-tools/      
  platforms;android-29 | 3       | Android SDK Platform 29        | platforms/android-29/
  tools                | 26.1.1  | Android SDK Tools 26.1.1       | tools/   

After that I ran ionic cordova requirements android:

โœ” Creating ./www directory for you - done!
> cordova requirements android

You have been opted out of telemetry. To change this, run: cordova telemetry on.

Requirements check results for android:
Java JDK: installed 1.8.0
Android SDK: installed true
Android target: not installed 
Please install Android target / API level: "android-28".

Hint: Open the SDK manager by running: /opt/android-sdk-linux/tools/android
You will require:
1. "SDK Platform" for API level android-28
2. "Android SDK Platform-tools (latest)
3. "Android SDK Build-tools" (latest)
Gradle: installed /usr/share/gradle/bin/gradle
Some of requirements check failed

First, why it still ask for for API level android-28 not for API level android-29?

Second point, actually, as I understand ionic cordova requirements android should be reading from platforms after it is added, in the directory, while I still building it, in ionic project, no platforms and plugins folder generated yet, and I run the command ionic cordova build android --no-interactive --confirm --prod --aot --minifyjs --minifycss --optimizejs --release --buildConfig=build.json -- -d immediately.

In your example I see android-28 in the list, could you please remove it, run build again, see if that added again?

because if I add platforms;android-28 I still get the same sdkmanager --list && ionic cordova requirements android result, but the build continues!

Edit: false alarm, I was reading wrong console log, when I add android-28 actually I get target listed:

Installed packages:=====================] 100% Computing updates...             
  Path                 | Version | Description                    | Location             
  -------              | ------- | -------                        | -------              
  build-tools;29.0.2   | 29.0.2  | Android SDK Build-Tools 29.0.2 | build-tools/29.0.2/  
  platform-tools       | 29.0.4  | Android SDK Platform-Tools     | platform-tools/      
  platforms;android-28 | 6       | Android SDK Platform 28        | platforms/android-28/
  tools                | 26.1.1  | Android SDK Tools 26.1.1       | tools/   
....

> cordova requirements android

You have been opted out of telemetry. To change this, run: cordova telemetry on.

Requirements check results for android:
Java JDK: installed 1.8.0
Android SDK: installed true
Android target: installed android-28
Gradle: installed /usr/share/gradle/bin/gradle

Note all these tests with <preference name="android-targetSdkVersion" value="29" /> in config.xml.

First, why it still ask for for API level android-28 not for API level android-29?

In some text it will ask for android-28 because that is the minimum SDK target required for that particular cordova-android version, and the version that cordova-android has been tested against.

In your example I see android-28 in the list, could you please remove it, run build again, see if that added again?

I can only do this later tonight as I'm at my workplace right now. But I have confirmed that it uses android-29 by adding gradle print outs.

I can only do this later tonight as I'm at my workplace right now.

This is going to sound weird, but I can't seem to uninstall android-28...

I mean I use the SDK Manager gui and it tells me its uninstalled and I look inside my $ANDROID_HOME platforms, build-tools, and everything and there is no 28.x folders, or android-28 folder... But sdkmanager --list/cordova requirements android still lists android-28 as an installed platform.

Additionally I can't use the sdkmanager command line to uninstall or install packages. It looks like it errors out but it doesn't produce any meaningful feedback. Only the GUI works for me, or at least it appears to work.

edit: Argh... my android sdk from my work profile is bleeding into my personal profile...

Ok @almothafar I've reproduced your issue.

Android definitely fails to find a target if it is missing the "minimum" target cordova-android requires, even if a target of a higher version is installed.

We are trying to use Android SDK 29.

config.xml

    <platform name="android">
        <preference name="android-minSdkVersion" value="19" />
        <preference name="android-targetSdkVersion" value="29" />
    </platform>

sdkmanager --list:

  Path                 | Version | Description                    | Location
  -------              | ------- | -------                        | -------
  build-tools;28.0.3   | 28.0.3  | Android SDK Build-Tools 28.0.3 | build-tools/28.0.3/
  build-tools;debian   | 27.0.1  | Android SDK Build-Tools        | build-tools/debian/
  platform-tools       | 29.0.5  | Android SDK Platform-Tools     | platform-tools/
  platforms;android-29 | 3       | Android SDK Platform 29        | platforms/android-29/
  tools                | 25.0.0  | Android SDK Tools              | tools/

cordova build android --prod

FAILURE:
Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
>
Failed to install the following SDK components:
      platforms;android-28 Android SDK Platform 28
  The SDK directory is not writable (/usr/lib/android-sdk)

The SDK directory is not writable (/usr/lib/android-sdk)

@freescout-helpdesk You're issue appears to be caused by /usr/lib/android-sdk not being writable. I'm not sure why it should be writable to begin with, so you should raise a new issue

The question is why it is looking for Platform 28 while android-targetSdkVersion is set to 29 and platforms;android-29 is installed.

The question is why it is looking for Platform 28 while android-targetSdkVersion is set to 29 and platforms;android-29 is installed.

That will be resolved in #849

Hi, I'm having the same problem. Do you have an estimate of when it will be available?

Hi, I'm having the same problem. Do you have an estimate of when it will be available?

There is no concrete release date. The next release will be a major version, and there are still some open PRs we would like to see merged in. In the meantime, you can access this via the cordova platform add android@nightly or from installing from github's master branch via cordova platform add https://github.com/apache/cordova-android.git.

These are the small bugs that make a developer question their existence.

In my case, using Ionic 5 - I moved my declarations into the Android platform section, ie

<widget ...>
    <platform name="android">
        <preference name="android-targetSdkVersion" value="29" />
    </platform>
</widget>

Followed by:

ionic cordova build android --release --prod

Then go into the platforms/android folder and run

./gradlew bundle

Now you're all bundled up, ready for signing and uploading.

IMPORTANT NOTE -- Make sure your cordova is the latest version:

npm uninstall -g cordova
npm install -g cordova

It seems this issue is still here!

I got <preference name="android-targetSdkVersion" value="30" /> but still looking for 29:

#13 394.1 Checking the license for package Android SDK Platform 29 in /opt/android-sdk-linux/licenses
#13 394.1 License for package Android SDK Platform 29 accepted.
#13 394.1 Preparing "Install Android SDK Platform 29 (revision: 5)".
#13 394.1 Warning: Failed to read or create install properties file.
#13 394.2
#13 394.2 FAILURE: Build failed with an exception.
#13 394.2
#13 394.2 * What went wrong:
#13 394.2 Could not determine the dependencies of task ':app:bundleReleaseResources'.
#13 394.2 > Failed to install the following SDK components:
#13 394.2       platforms;android-29 Android SDK Platform 29
#13 394.2   Install the missing components using the SDK manager in Android Studio.

It seems this issue is still here!

I got <preference name="android-targetSdkVersion" value="30" /> but still looking for 29:

#13 394.1 Checking the license for package Android SDK Platform 29 in /opt/android-sdk-linux/licenses
#13 394.1 License for package Android SDK Platform 29 accepted.
#13 394.1 Preparing "Install Android SDK Platform 29 (revision: 5)".
#13 394.1 Warning: Failed to read or create install properties file.
#13 394.2
#13 394.2 FAILURE: Build failed with an exception.
#13 394.2
#13 394.2 * What went wrong:
#13 394.2 Could not determine the dependencies of task ':app:bundleReleaseResources'.
#13 394.2 > Failed to install the following SDK components:
#13 394.2       platforms;android-29 Android SDK Platform 29
#13 394.2   Install the missing components using the SDK manager in Android Studio.

We should create a new issue otherwise this will get lost. You can link to this closed issue for context, but the form should still be filled out.

It seems this issue is still here!

I got <preference name="android-targetSdkVersion" value="30" /> but still looking for 29:

#13 394.1 Checking the license for package Android SDK Platform 29 in /opt/android-sdk-linux/licenses
#13 394.1 License for package Android SDK Platform 29 accepted.
#13 394.1 Preparing "Install Android SDK Platform 29 (revision: 5)".
#13 394.1 Warning: Failed to read or create install properties file.
#13 394.2
#13 394.2 FAILURE: Build failed with an exception.
#13 394.2
#13 394.2 * What went wrong:
#13 394.2 Could not determine the dependencies of task ':app:bundleReleaseResources'.
#13 394.2 > Failed to install the following SDK components:
#13 394.2       platforms;android-29 Android SDK Platform 29
#13 394.2   Install the missing components using the SDK manager in Android Studio.

have you found any solution on this ? i try all posible solution but still its asking for 29 and even cordova 9 only support android 29 sand in website they showing latest version 10.X so is there is any way to install cordova 10 ?

@krunalsk007 the workaround for this depends on your situation, so personally, I did a hook with NodeJS to replace the value of platforms in the generated files before doing the build, in this repo (develop branch) and you can see specifically in this commit