collectMultidex task looking in wrong place for manifest.xml - android

When trying to enable multi-dexing for an application over 65K, following the guidelines specified by the android developer page here
While in my application build.gradle I specify:
android.applicationVariants.all{
variant -> variant.outputs.each {
output ->
output.processResources.manifestFile = file('AndroidManifest.xml')
output.processManifest.enabled=false
}
}
Upon running build I receive this error,
Error: A problem was found with the configuration of task ':myapp:collectDebugMultiDexComponents'.
File 'C:\Android Projects\myappapp\build\intermediates\manifests\full\debug\AndroidManifest.xml' specified for property 'manifest' does not exist.
Open to any suggestions or advice to properly direct multi dex task to actual AndroidManifest.xml path. When removing the library that causes the application to cross the 64k limit and removing multidexing the application builds fine.

Related

Gradle task for Sentry not compiling

I have to add the Analytics tool Sentry to our Android project. In order to make it work, one needs to create mappings for the obfuscated code (from Proguard/R8) and upload it later to Sentry.
On the website https://docs.sentry.io/platforms/android/ it is even described how to do that.
There it is written that one needs to create a gradle task looking like this:
gradle.projectsEvaluated {
android.applicationVariants.each { variant ->
def variantName = variant.name.capitalize();
def proguardTask = project.tasks.findByName(
"transformClassesAndResourcesWithProguardFor${variantName}")
def dexTask = project.tasks.findByName(
"transformClassesWithDexFor${variantName}")
def task = project.tasks.create(
name: "processSentryProguardFor${variantName}",
type: Exec) {
workingDir project.rootDir
commandLine *[
"sentry-cli",
"upload-proguard",
"--write-properties",
"${project.rootDir.toPath()}/app/build/intermediates/assets" +
"/${variant.dirName}/sentry-debug-meta.properties",
variant.getMappingFile(),
"--no-upload"
]
}
dexTask.dependsOn task
task.dependsOn proguardTask
}
}
This shall wait until Proguard is finished, than copy this properties file to the assets. However, when I add this to my Android gradle script I get the error:
Could not create task
':app:processSentryProguardForPlayStoreStagingDebug'.
No signature of method: java.util.ArrayList.multiply() is applicable for argument types: (ArrayList) values: [[sentry-cli, upload-proguard,
--write-properties, {Application-Path}/app/build/intermediates/assets/playStoreStaging/debug/sentry-debug-meta.properties,
...]] Possible solutions: multiply(java.lang.Number),
multiply(java.lang.Number)
I assume there is something wrong with the multiplication symbol * before the commandLine array. But when I remove it I get the error
Could not create task
':app:processSentryProguardForPlayStoreStagingDebug'.
Cannot cast object 'sentry-cli' with class 'java.lang.String' to class 'int'
So I tried to test this with only that line
commandLine "sentry-cli", ...
Which gave me another error
What went wrong: Cannot invoke method dependsOn() on null object
Thus I assume something went really wrong with that gradle script since it seems the dependend task can't be found. Does anyone have any idea how to fix this (or optionally have any other idea how to copy that sentry-debug-meta.properties file to my assets in another way, once Proguard/R8 is finished)?
Thanks!
-------- EDIT --------
I noticed something important.
The gradle tasks are defined in a different name than what was defined in the manual. Looking at my tasks I have them named
transformClassesAndResourcesWithR8For...
and
transformClassesWithDexBuilderFor...
However, I print the variantName then for checking but it seems my tasks are incomplete.
In my tasks list there exist
transformClassesAndResourcesWithR8ForPlayStoreStagingDebug
but not
transformClassesAndResourcesWithR8ForPlayStoreStagingRelease
and thus the task can't be found. I think that is the real problem here. So where are these gradle tasks defined?
------- EDIT 2 --------
Okay I noticed something strange here. Some variants don't have tasks. It makes sense that DEBUG tasks don't have R8 tasks but I found this here:
Variant: PlayStoreStagingRelease DexTask is null
Variant: PlayStorePreviewRelease DexTask is null
Variant: HockeyAppRelease DexTask is null
Variant: LocalServerRelease DexTask is null
Variant: PlayStoreProductionRelease DexTask is null
So how can this be?
I'd recommend using the Sentry Gradle integration (Gradle plugin) which is described here https://docs.sentry.io/platforms/android/#gradle-integration
The official Android Gradle plugin changed its task names over versions, Gradle version also affects those code snippets.
Google also replaced Proguard with R8 and it also affected those code snippets.
Is there a reason why not using the Sentry Gradle integration? if so, We'll be looking into updating them.
Thanks.
java.util.ArrayList.multiply() hints for that * in front of the [ ] list, which looks strange to me. Try removing the *[ ], only keeping List<String> (there's no ArrayList expected, to begin with):
commandLine "sentry-cli", "upload-proguard", "--write-properties", "${project.rootDir.toPath()}/app/build/intermediates/assets/${variant.dirName}/sentry-debug-meta.properties", variant.getMappingFile(), "--no-upload"
You'd have to look up how your tasks are actually being called, but it should be something alike:
def r8Task = project.tasks.findByName("transformClassesAndResourcesWithR8For${variantName}")
def d8Task = project.tasks.findByName("transformClassesWithDexBuilderFor${variantName}")
With a null check, because not every variant might have minifyEnabled true set:
if(r8Task != null) {
d8Task.dependsOn task
task.dependsOn r8Task
}
Maybe even a previous null check is required, because variant.getMappingFile() needs R8.
And that some flavors have no D8 task might be based upon the absence of code (nothing to do).
Here's a summary of the steps that I followed for integrating Sentry with my Android app. These steps are to ensure the sentry gradle plugin works as expected and automatically uploads the proguard mapping files, without you having to worry about uploading using cli. I assume you would have setup the Sentry SDK as described here:
https://docs.sentry.io/platforms/android/#integrating-the-sdk
Ensure you have Android Studio gradle plugin 3.5.0 (Not 3.6.x, that seems to break the sentry plugin. I observed that the sentry proguard or native symbol upload tasks are not configured or executed at all). This value should be in your root project's build.gradle in dependencies block
Provide a sentry.properties file the root folder of your project. The sentry.properties file should have the following values at minimum:
defaults.project=your_sentry_project_name
defaults.org=your_sentry_org_name
auth.token=sentry_project_auth_token
You can get info about generating auth tokens here: https://sentry.io/settings/account/api/auth-tokens/
(Optional: If you have build flavors) In my case, I have different flavors for my app. So, I had to put the sentry.properties inside my flavor specific folder in /app/src/ folder. Then, I wrote a gradle task to copy the flavor specific sentry.properties file into the project's root folder during gradle's configuration phase. Example:
task copySentryPropertiesTask {
if (getBuildFlavor() != null && !getBuildFlavor().isEmpty()) {
println("Copying Sentry properties file: ${getBuildFlavor()}")
copy {
from "src/${getBuildFlavor()}/"
include "sentry.properties"
into "../"
}
}
}
def getBuildFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if (tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find())
return matcher.group(1)
else {
println "NO MATCH FOUND"
return ""
}
}
Note 1: You can place this task in your app/build.gradle anywhere (I had placed it at the end).
Note 2: If you followed step 3 for build flavors, you can also add the root folder's sentry.properties in .gitignore. Since, it will be copied everytime you create a build.
Sentry should now be able to upload the proguard files for any release builds (or if you set minifyEnabled=true for any buildType).

Is there a way to change the gradle.properties file in Unity

Unity has a default gradle.properties file that gets added during the build process. While its possible to change the build.gradle and the settings.gradle files as mentioned
here https://docs.unity3d.com/Manual/android-gradle-overview.html
there is no mention of being able to change gradle.properties within the unity docs. The file also gets recreated every build attempt so editing it within the temp/gradleOut after a build and building again doesn't work. I know exporting the project is possible as well, but I'm looking for a solution where the project can be run directly from unity.
Btw this question is NOT a duplicate of this question How to use Gradle in Unity
The answer here has nothing to do with modifying the gradle.properties file.
This is a duplicate of this question that got incorrectly marked as a duplicate how to change default gradle.properties of Unity?
Maybe my answer is a bit outdated but in Unity 2020 you can do it in:
Player Settings -> Tab Android (with robot obviously) -> Publishing Settings -> Custom Gradle Properties Template (checkbox).
After enabling the checkbox you will see the path to gradleTemplate.properties (usually it appears in Assets/Plugins/Android directory) file which will be merged with final gradle.properties.
Everything you need you can write to the end of file after **ADDITIONAL_PROPERTIES** string.
Example:
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
org.gradle.parallel=true
android.enableR8=**MINIFY_WITH_R_EIGHT**
**ADDITIONAL_PROPERTIES**
android.useAndroidX = true // I added this property to fix error: This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. Set this property to true in the gradle.properties file and retry.
Also on screenshot:
This was something that was slightly hard to discover. I was going to do a regular post build processor like I had for my iOS build, but as I was searching for a manner to load and determine where the properties file was, I ran across the following interface in the documentation : IPostGenerateGradleAndroidProject.
According to the documentation:
Implement this interface to receive a callback after the Android
Gradle project is generated.
So below is my initial brute force implementation for turning on androidX and jetifier.
public class AndroidPostBuildProcessor : IPostGenerateGradleAndroidProject
{
public int callbackOrder
{
get
{
return 999;
}
}
void IPostGenerateGradleAndroidProject.OnPostGenerateGradleAndroidProject(string path)
{
Debug.Log("Bulid path : " + path);
string gradlePropertiesFile = path + "/gradle.properties";
if (File.Exists(gradlePropertiesFile))
{
File.Delete(gradlePropertiesFile);
}
StreamWriter writer = File.CreateText(gradlePropertiesFile);
writer.WriteLine("org.gradle.jvmargs=-Xmx4096M");
writer.WriteLine("android.useAndroidX=true");
writer.WriteLine("android.enableJetifier=true");
writer.Flush();
writer.Close();
}
}
Theoretically you should be able to manipulate the generated gradle project in any manner to your choosing during the post build processor. Some additional tools might be helpful, like the PBXProject support on iOS, but until then, this will do.
IPostGenerateGradleAndroidProject is a new Interface added after Unity2018.
As my project based on Unity2017, it's not a good solution. Then I found this. A solution with Gradle.
([rootProject] + (rootProject.subprojects as List)).each {
ext {
it.setProperty("android.useAndroidX", true)
it.setProperty("android.enableJetifier", true)
}
}
Although this is not a perfect solution, you can use the "Export Project" option.
Build Settings
After exporting the project, you can modify gradle.properties and build using AndroidStudio or command line.
In the newer Unity versions (2019.4+) it is possible to generate a custom gradle properties template by going to Project Settings > Player > (Android Tab) > Other Settings > and marking "Custom Gradle Properties Template".
After selecting that a gradleTemplate.properties file is generated at "Assets/Plugins/Android/gradleTemplate.properties".
This is the best way of generating the file since it is git friendly and preserves other settings.

Grade Plugin 3-alpha1 outputFile causes error

I'm trying to update a project to Android Studio 3.
The following snippet is no longer accepted in a build.gradle file.
applicationVariants.all { variant ->
variant.outputs.each { out ->
def oFile =out.outputFile // This line causes failure
//...
}
}
The error is a simple "Not Valid" yet the intellisense suggests it is as it autocompletes fine.
Checking the idea.log shows the following exception:
Caused by: java.lang.RuntimeException: Not valid.
at com.android.ide.common.build.ApkData.getMainOutputFile(ApkData.java:136)
at com.android.build.gradle.internal.api.BaseVariantOutputImpl.getOutputFile(BaseVariantOutputImpl.java:60)
at com.android.build.gradle.internal.api.ApkVariantOutputImpl_Decorated.getOutputFile(Unknown Source)
at org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.getProperty(BeanDynamicObject.java:228)
at org.gradle.internal.metaobject.BeanDynamicObject.tryGetProperty(BeanDynamicObject.java:171)
at org.gradle.internal.metaobject.CompositeDynamicObject.tryGetProperty(CompositeDynamicObject.java:55)
at org.gradle.internal.metaobject.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:59)
at com.android.build.gradle.internal.api.ApkVariantOutputImpl_Decorated.getProperty(Unknown Source)
I can find no documentation on Gradle 4. Would this be a bug or a function that is deprecated perhaps?
Also filed at: https://issuetracker.google.com/issues/38408231
Update: Fix for APK renaming:
Use all iterators instead of each:
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
Previous answer, still valid: It's a known problem with the new plugin:
This build error occurs because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times. As an alternative, we will introduce new APIs to provide similar functionality.
We need to wait for an alternative way of doing that, according to the Migration Guide.
If your failing plugin support explicitly setting file path, it might be a work around.
I had problems with Fabrics crashlyticsUploadDistributionRelease task, giving me the same stack trace as above. I fixed it by explicitly setting the output file path property in app/build.gradle:
ext.betaDistributionApkFilePath = "app/build/outputs/apk/release/app-release.apk"

Gradle Skip Test

I am looking for a way to skip tests from one of the projects in a multi-build project. I don't want to use gradle build -x test because then it will skip test for all sub - projects.
Root
Sub P1
build.gradle
Sub P2
build.gradle
Sub P3
build.gradle
build.gradle
settings.gradle
I want to skip tests only for "Sub P3"
Can i configure my project(Sub P3) build file to skip tests?
Due to official user guide, there are 3 ways to skip some task in gradle.
The first 2, are: using predicate and exception throwing. Predicates are resolved during the configuration phase and may not pass to your requirements. StopExecutionExeptionthrowing could be added to the doFirst of every test and be throwed according to some condition. Bit that seems to be not very clear, because you have to modify both root script to set the condition and subroject sripts test tasks.
And the 3rd one is - disabling the tasks. Every task, has a enabled property (default is true), which is preventing task execution, if it was set to false. Only thing you have to do is to set this property for test task in your subproject. This can be done in sub projects buil script root, as:
test.enabled = false
This will work, if you didn't specify custom test tasks, if you did, you can disable all test by task type, as:
project(':subProject').tasks.withType(Test){
enabled = false
}
Previews 2 configurations must be included to the build script of the subproject, but since you have a root project, you can configure subprojecst from it's build script, via project() providing subproject's name:
project(':subProject').tasks.withType(Test){
enabled = false
}
For android there is no test task available in gradle
To skip unit tests in android you have to do this
android {
.
.
.
testOptions {
unitTests.all {
enabled false
}
}
}

Why are my Android gradle variant customisations not working?

1- Why is the following:
android.buildVariants.each { variant ->
... my code
}
giving me the following error?
Could not find property 'buildVariants' on com.android.build.gradle.AppExtension_Decorated#1bf6bde6.
2- Why is the following silently not executing "... my code"?
android.applicationVariants.each { variant ->
... my code
}
The Android Build System now uses "applicationVariants" instead of "buildVariants". However, "android.applicationVariants.each" will also not work, see below.
Since the Android Build System 0.5.5 release you must use "android.applicationVariants.all" instead of "android.applicationVariants.each", as applicationVariants will remain empty with a call to each.

Categories

Resources