Android 12 support
Is your feature request related to a problem? Please describe.
Hi NativeScript maintainers :)
I'm currently trying to target and compile my NativeScript with Android 12 (SDK Platform 31).
Describe the solution you'd like
The ideal would be to have this out of the box, but I thinked it was possible by changing only a few configurations (I was wrong).
Describe alternatives you've considered
Here is what I did so far:
Install latest SDK and build tools
sdkmanager --install "platforms;android-31" "build-tools;31.0.0"
I also removed previous versions for platforms and build-tools.
Change target and compile SDK versions in app.gradle:
project.compileSdk = 31
project.targetSdk = 31
android {
// no change in this object
}
Here is the error I get when trying to compile:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.
I found this related issue: #9639. @rigor789 suggested to uninstall build-tools and reinstall them with version 30. If I do that, I'm still not able to compile. The error is now:
Unable to apply changes on device: 0xxxxxxxxxx4. Error is: The parser encountered some structural problem in the manifest..
I think it's because build-tools 31 are mandatory to compile with platform 31.
I found this related StackOverflow issue: https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted
This issue suggests to rename or add a symlink for two files missing in the latest version (dxand lib/dx.jar). I tested this solution but it does not work. There is also a less upvoted suggestion:
The point is not to downgrade target API level, but to build exactly for API level 31 to prepare and test an app for Android 12!
It looks like DX is removed from SDK in favor of D8.
It looks like that Android Gradle plugin 4.x is not aware of that.
At the moment I see only two solutions:
- To stay with AGP 4.x, one should copy DX from 30.0.3 to 31.0.0
- Upgrade AGP to 7.x
I think this is the correct way to support Android 12 but I don't know if this "Android Gradle Plugin" is part of NativeScript or not. My installed Gradle version is 7.2 so I would say yes.
Anything else?
I would be very happy to help as I have an Android 12 phone with me (it's a custom ROM though).
Also, what are the plans for the official support?
- [X] I have searched the existing issues as well as StackOverflow and this has not been posted before
- [X] I agree to follow this project's Code of Conduct
Apps built with lower level SDK (30 for example) should have no trouble running on Android 12 (sdk 31).
@triniwiz has updated the android-runtime to AGP 7, and released the aplpha version of the runtime, you may be able to test that: npm i --save-dev @nativescript/android@alpha.
Yes you're right, it runs fine if we build with SDK 29 (the default one if I'm right).
The fact is I wanted to implement new Bluetooth Android 12 permissions and submit a PR to ˋ@nativescript-community/ble`.
I will give a try tomorrow at the Android runtime alpha, thanks for the info!
Unfortunately, it still fails with latest @nativescript/android@alpha. Should I open an issue on https://github.com/NativeScript/android-runtime?
I'm also running into the problem as @sebj54 with a brand new nativescript project:
Unable to apply changes on device: <device id>. Error is: The parser encountered some structural problem in the manifest..
I tried adding @nativescript/android@alpha, and I can see the changes in ./platforms/android/build.gradle, using AGP 7.0.2. When I clean and run the project again, I get:
Execution failed for task ':app:processDebugMainManifest'.
Manifest merger failed : android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
If I manually change my single activity in the manifest, adding android:exported="true", the build appears to finish and install on the device. It looks declaring android:exported is required for Android 12:
https://developer.android.com/about/versions/12/behavior-changes-12#exported
You're right, it compiles after running ns clean and adding android:exported="true".
Unfortunately I have another problem with a hook from @nativescript/firebase:
Script '/Users/_____/projets/sample-project/node_modules/@nativescript/firebase/platforms/android/include.gradle' line: 96
A problem occurred evaluating script.
Plugin with id 'com.google.gms.google-services' not found.
I think I'll wait a bit for the Android runtime to get out of alpha.
I'm new to app development and started from zero and have the same issue. Is it correct to add android:exported="true" to the manifest here App_Resources/Android/src/main/AndroidManifest.xml?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="__PACKAGE__"
android:versionCode="10000"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true"
android:exported="true">
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
android:theme="@style/LaunchScreenTheme"
android:hardwareAccelerated="true"
android:launchMode="singleTask">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity"/>
</application>
</manifest>
android:exported="true"
That's exactly where I updated the manifest file as well, however for me, the error message didn't go away even after that
Unable to apply changes on device: emulator-5554. Error is: The parser encountered some structural problem in the manifest..
It needs to be added to the activity not application
It needs to be added to the activity not application
yes that did the trick, nice
We are experiencing the same issue targeting Android 12 / SDK 31:
The parser encountered some structural problem in the manifest
Trying to install the apk gives the following error:
The APK failed to install. Error: INSTALL_PARSE_FAILED_MANIFEST MALFORMED: Failed parse during installPackageLl: /data/app/vmd1969193467.tmp/base.apk (at Binary XML file line #50): com.tns.NativeScriptActivity: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present
After setting android:exported="true" the parser error is gone but the firebase issue occurs:
The APK failed to install. Error. INSTALL_PARSE_FAILED_MANIFEST MALFORMED: Failed parse during installPackageLl: /data/app/vmd111210731.tmp/base.apk (at Binary XML file line #142): org.nativescript.plugins.firebase.MyFirebaseMessagingService: Targeting Si- (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present
Is there a perspective until when the error will be fixed? Currently Android 12 users are completely unable to use our app.
@markusmauch you can use patch-package to add android:exported="true" to the firebase service and rebuild your app: https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/master/src/platforms/android/libraryproject/firebase/src/main/AndroidManifest.xml
@rigor789 Hi! Can you explain how to do this using patch-package?
@sarezjay sure, though after a quick look - seems like the AndroidManifest is packaged into an aar file - so in that case patch-package won't work. But you can still work around this:
-
make a folder in your project where you can store a patched aar - for example
patches/firebase/ -
copy the
firebase-release.aar-disabledfromnode_modules/@nativescript/firebase/platforms/androidintopatches/firebase/ -
open the file (it's basically a zip file, so you can either rename it to .zip and unpack it, or open it with a program that can read zip files - on windows WinRar would work, etc.)
-
Change the AndroidManifest.xml and add the
android:exported="true" -
Repack - it's just a zip file with a different extension...
-
Add a postinstall script to your package.json that copies the file back into
node_modules"scripts": { "postinstall": "cp patches/firebase/firebase-release.aar-disabled node_modules/@nativescript/firebase/platforms/android" }(might need to add a force flag to override the file in node_modules)
Though it would be simpler to open a PR with the fix, and get this published in a patch...
@rigor789 in node_modules/@nativescript/firebase/platforms/android there is firebase-release.aar, I think I need to copy that file not firebase-release.aar-disabled.arr file
correct ?
After doing this when I am making build it give error:
Execution failed for task ':app:javaPreCompileDebug'. error in opening zip file
Do any one has idea about it ?
Could you please share you updated firebase-release.aar file ?
On a fresh install it's firebase-release.aar-disabled but it's renamed to .aar in a postinstall hook, though I don't think it really matters, as long as the final file is named .aar either by the custom postinstall hook, or by firebase's own rename hook.
Odd you are getting that error afterwards, how did you unpack/repack the aar? Should be packed the same way as the original - meaning the files should be at the root of the zip file and not inside a folder.
I've done a test here, I believe it should be correct, but unable to test it myself firebase-release-patched.aar.zip
(I added the .zip extension to be able to upload here, just rename the file to firebase-release.aar without extracting anything.)
Thanks @rigor789 for uploading this zip file. I have managed to fix this issue. Somehow It was not working that time, but when I tried after some time it worked as you explained.
For me it worked with creating the apk with:
ns build android --compileSdk 30
In case someone comes over this error and does not need to compile with 31 yet
For me it worked with creating the apk with:
ns build android --compileSdk 30In case someone comes over this error and does not need to compile with 31 yet
Your tip fixed the issue for me. Many thanks!
You're right, it compiles after running
ns cleanand addingandroid:exported="true".Unfortunately I have another problem with a hook from
@nativescript/firebase:Script '/Users/_____/projets/sample-project/node_modules/@nativescript/firebase/platforms/android/include.gradle' line: 96 A problem occurred evaluating script. Plugin with id 'com.google.gms.google-services' not found.I think I'll wait a bit for the Android runtime to get out of alpha.
For the issue of 'com.google.gms.google-services', I added a classpath line to this file /platforms/android/build.gradle, and it solved it.
The classpath will be added under buildscript -> dependencies, like:
dependencies {
...
classpath "com.google.gms:google-services:4.3.4"
}
Hope if can help solve your issue. :)
I'm hitting this same issue, even after trying all the above suggestions. This is a serious obstacle, as I need to publish my app but right now can't install on Android 12.
@dlcole which error are you currently stuck on ?
@triniwiz yes, I realized as I was going to bed I should have been more specific :-)
Here's my current AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="__PACKAGE__"
android:versionCode="25"
android:versionName="5.0.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="__APILEVEL__" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<!-- See https://github.com/dapriett/nativescript-google-maps-sdk/issues/339 -->
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/nativescript_google_maps_api_key" />
<activity
android:name="com.tns.NativeScriptActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/LaunchScreenTheme"
android:screenOrientation="portrait"
android:exported="true"
android:launchMode="singleTask">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="rrr" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter android:autoVerify="true">
<data android:scheme="https" />
<data android:host="rrr.govia.tech" />
<data android:pathPattern="/.*" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity" />
<!-- See https://github.com/NativeScript/nativescript-geolocation/issues/256 -->
<service
android:name="org.nativescript.geolocation.ForegroundService"
android:enabled="true"
android:stopWithTask="true"
android:exported="false"
android:foregroundServiceType="location" />
</application>
</manifest>
Here's my current app.gradle file:
android {
compileSdkVersion 31 // had been 30
defaultConfig {
generatedDensities = []
applicationId = "tech.govia.rrr"
multiDexEnabled true
minSdkVersion 19
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
project.ext {
googlePlayServicesVersion = "+"
}
And if it matters, here's before-plugins.gradle:
project.ext.googlePlayServicesVersion = "16.+"
dependencies {
// classpath "com.google.gms:google-services:4.3.4"
}
and build script.gradle:
// See https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues/1873
repositories {
google()
jcenter()
}
dependencies {
classpath "com.google.gms:google-services:4.3.4"
}
So, I do have android:exported="true" in the activity section.
The content of these files has evolved over the years as I chase down various issues on SO and GitHub. Probably like a lot of other folks, I'll make changes until things work, sometimes without fully understanding the nature of those changes.
I'd truly welcome any insights here!
Do you have any error message to share with us?
Yes, the resulting error message is,
The parser encountered some structural problem in the manifest
I think your error is caused by a conflict between the <uses-sdk> tag in your manifest and compileSdkVersion defined in your gradle file.
@sebj54 I made these changes:
in app.gradle I added targetSdkVersion to defaultConfig
android {
compileSdkVersion 31 // had been 30
defaultConfig {
generatedDensities = []
applicationId = "tech.govia.rrr"
multiDexEnabled true
minSdkVersion 19
targetSdkVersion 31
}
...
This yields the same error message,
Installing on device emulator-5554...
Unable to apply changes on device: emulator-5554. Error is: The parser encountered some structural problem in the manifest..
so I tried hard-coding the targetSdkVersion in AndroidManifest.xml:
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="31" />
But received the same error message.
There is still a problem because you have minSdkVersion="17" in your manifest and minSdkVersion 19 in your gradle file. I think you should completely remove the <uses-sdk> tag in your manifest and let gradle handle this.
So I commented out the <uses-sdk> section of AndroidManifest.xml but still received the error,
Unable to apply changes on device: emulator-5554. Error is: The parser encountered some structural problem in the manifest..
I should note that this is with @nativescript/android 8.1.1. If I switch to 8.2.2 I don't even get as far and fail with the message,
Script '/Users/david/Documents/NativeScriptProjects/rrr/node_modules/nativescript-danem-google-maps-utils/platforms/android/include.gradle' line: 6
A problem occurred evaluating script.
Could not find method compile() for arguments [com.google.maps.android:android-maps-utils:2.0.3] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
Unable to apply changes on device: emulator-5554. Error is: Command ./gradlew failed with exit code 1.
You need to replace compile in /Users/david/Documents/NativeScriptProjects/rrr/node_modules/nativescript-danem-google-maps-utils/platforms/android/include.gradle to implementation
@triniwiz yep, I've seen that issue before. Upon doing that and rebuilding with @nativescript/android 8.2.2, I'm now back at the same error,
Unable to apply changes on device: emulator-5554. Error is: The parser encountered some structural problem in the manifest..