Showing posts with label gradle. Show all posts
Showing posts with label gradle. Show all posts

Thursday, October 4, 2018

How to sign android app with platform keys using gradle?

Leave a Comment

I saw couple similar questions like:

but I feel my problem is different.

First of all I use:

android:sharedUserId="android.uid.system"

so I need to sign my app with platform key. I'm able to do that in this way:

cd $ANDROID_ROOT/out/host/linux-x86/framework java -Djava.library.path=$ANDROID_ROOT/out/host/linux-x86/lib64 -jar signapk.jar $ANDROID_ROOT/build/target/product/security/platform.x509.pem $ANDROID_ROOT/build/target/product/security/platform.pk8 $APP_DIR/app/build/outputs/apk/debug/app-debug.apk $APP_DIR/MyApp-signed.apk 

However I want to do signing from gradle, so I have generated jks file in this way:

./keytool-importkeypair -k my_keystore.jks -p my_password -pk8 $ANDROID_ROOT/build/target/product/security/platform.pk8 -cert $ANDROID_ROOT/build/target/product/security/platform.x509.pem -alias platform 

and I've modified app/build.gradle to have:

 signingConfigs {      release {          storeFile file("my_keystore.jks")          storePassword "my_password"          keyAlias "platform"          keyPassword "my_password"      }  }   buildTypes {      release {          minifyEnabled false          proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'           signingConfig signingConfigs.release      }  } 

I've checked that my_keystore.jks has platform alias with:

keytool -list -v -keystore my_keystore.jks | grep Alias Alias name: platform 

but when I try to do:

./gradlew assembleRelease 

or:

./gradlew signingReport 

I get:

Failed to read key platform from store "(...)/my_keystore.jks": Invalid keystore format

Update: I've tried following dr_g tips and I'm able to sign app using Android Studio (Build -> Generate Signed APK), so I guess keystore is ok, but still I get the same error when using assembleRelease. I've also tried generating my own keystore as suggested by deadfish and indeed keystore generated by Android Studio is fine for gradle and assembleRelease works, but it's not platform key, so I can't use it unfortunately.

3 Answers

Answers 1

Please try using the .keystore variant. There could be ways to fix the java keystore (.jks) format but it is likely to take more time.

1) Generate your .keystore file from your separate key files

$ openssl pkcs8 -inform DER -nocrypt -in \   $ANDROID_ROOT/build/target/product/security/platform.pk8 -out platform.key $ openssl pkcs12 -export -in \   $ANDROID_ROOT/build/target/product/security/platform.x509.pem -inkey \   platform.key -name platform -out platform.pem -password pass:password $ keytool -importkeystore -destkeystore platform.keystore -deststorepass \   password -srckeystore platform.pem -srcstoretype PKCS12 -srcstorepass    password 

2) Test your new keystore:

$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore \   platform.keystore -storepass password your-app.apk platform 

3) Deploy keystore in your gradle build:

signingConfigs {  debug {     storeFile     file('debug.keystore')     storePassword 'android'     keyAlias      'androiddebugkey'     keyPassword   'android'  }  release {     storeFile     file('platform.keystore')     storePassword 'password'     keyAlias      'platform'     keyPassword   'password'  }  } 

The above build.gradle is also showing an example of using the android debug keystore as standard for debug builds.

Answers 2

use the .keystore file not the .jks when you generate you app,Android studio will notice you create a keyStore, try this key.

Answers 3

After chat with deadfish and following his suggestions (thanks for help!) I've come up with following workaround in app/build.gradle (inside android {}):

applicationVariants.all { variant ->     variant.assemble.doLast {         exec {             commandLine 'sh', '../mySigningScript.sh'         }     } } 

This will run my script everytime when assembleDebug or assembleRelease is finished. I will not accept my answer because it's not answering my question and it forces me to remove signingConfigs from gradle but at least it's a workaround which potentially could be used if no better solution is proposed.

Read More

Sunday, September 30, 2018

Register a package for the class generated from the proto file in the gradle by default , not in proto file

Leave a Comment

In my android app I use proto files. For example, I have proto file Stats.proto

syntax = "proto3"; package com.me.test;  message Stat {     string a = 1;     string b = 2;     string c = 3;     string d = 4; } 

I need to register package in the each proto file itself, and this is uncomfortable, because I have a lot of files. I want to register default package in gradle, for example, 'package com.me.test', which uses each file that I create. I found solution in javanano

nano {     proto {       // Selects between --java_out and --javanano_out, default is 'java'       mode 'javanano'       // Options added to --java_out or --javanano_out       option 'java_package=src/proto/simple-data.proto|my_package'       option 'java_outer_classname=src/proto/simple-data.proto|OuterName'       // Apply the 'grpc' plugin defined in protobufNativeCodeGenPluginDeps       plugin 'grpc' {         // Options added to --grpc_out         option 'nano=true'       }     } 

But I need to use javalite

protobuf {     protoc {         artifact = 'com.google.protobuf:protoc:3.0.0'     }     plugins {         javalite {             artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'         }     }     generateProtoTasks {         all().each { task ->             task.builtins {                 remove java             }             task.plugins {                 javalite { }             }         }     } } 

And I want to have analogous logic

option 'java_package=src/proto/simple-data.proto|my_package' 

like javanano in javalite

Can I implement that?

1 Answers

Answers 1

According to the doc, and assuming javalite supports the same features than java (it's a long shot as I did not found any trace of documentation on this plugin), just try that :

protobuf {     protoc {         artifact = 'com.google.protobuf:protoc:3.0.0'     }     plugins {         javalite {             artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'         }     }     generateProtoTasks {         all().each { task ->             task.builtins {                 remove java             }             task.plugins {                 javalite {                     option 'java_package=.......'                                  }             }         }     } } 
Read More

gradle: disable creation of the build folder at root in multi-projects application

Leave a Comment

My gradle project is a multi-project structure. It consists of two subprojects. My build.gradle in root project as following:

allprojects {   apply plugin: 'eclipse' }  subprojects {   apply plugin: 'java'   apply plugin: 'maven-publish'    publishing {     repositories {       maven {         name 'myMaven'         def suffix = project.version.endsWith("SNAPSHOT") ? "snapshots" : "releases"         url baseUrl + suffix       }     }      publications {       core(MavenPublication) {         artifactId project.name         artifact jar       }     }   } }  project(':projectA') {   ext {     sharedManifest = manifest {       attributes("Implementation-Title": project.name,                  "Implementation-Version": 1.0 )     }   }   jar {     manifest = project.manifest {       from sharedManifest     }   } }  project('projectB') {   ext {     sharedManifest = manifest {       attributes("Implementation-Title": project.name,                  "Implementation-Version": 2.0 )     }   }   jar {     manifest = project.manifest {       from sharedManifest     }   } } 

After gradle build, I got three build folders. one at the root directory and other two in the respective subprojects. The root project is just an empty folder without any source code, it is just a multi-project container.

Now I need to eliminate the creation of root build folder since it is of no use. I search on the net and in the gradle docs/forum but did not get any hit.

Is there any way so that gradle stop creating build folder at root level?

1 Answers

Answers 1

Who is responsible for the build dir creation ?

According to Mark Vieira, a Gradle core dev, each task is responsible for the creation of the ouput dir as long as it creates output.

So basically, it your root project does have a build dir, it means it's not empty and something is deliberately writing into it.

In my job, I'm managing a big project constituted by a root project, which handles many .gradle files, settings files etc. and many subprojects with the actual code. When I run gradle clean build, all subprojects get their own build dir with libs, binaries etc. but the root project does not end up with any build dir because no task whatsoever writes output in the root build dir.

What can I do to remove the root build dir, whatever task creating it ?

Just set up a buildFinished hook only for the root project

gradle.buildFinished {     project.buildDir.deleteDir() } 
Read More

Saturday, September 22, 2018

Problem with gradle build flavour and packagingOptions

Leave a Comment

I have been developing for a while a library (in aar format) that is compatible with x86, armeabi-v7a and arm64-v8a abis. The library works as expected but, in order to reduce the final size, we want to develop two different libraries: one with arm64-v8a abi and one without it. The library depends on openCV (used in C++ language) and we have the following project structure:

src  |_ main      |_ jniLibs            |    | arm64-v8a            |----| armeabi-v7a                 | x86 

Each abi folder contains libopencv_java3.so.

I have created two product flavours, each one with the abiFilters needed to work properly.

flavorDimensions "default" productFlavors {     v7a {         externalNativeBuild {             cmake {                 abiFilters 'x86', 'armeabi-v7a'             }         }     }     v8a {         externalNativeBuild {             cmake {                 abiFilters 'x86', 'armeabi-v7a', 'arm64-v8a'             }         }     } } 

Now I have two build variants to select and both compile without errors. However, the v7a aar still contains the arm64-v8a folder and library inside it. To solve this, I have added to v7a flavour the following:

packagingOptions {     exclude 'lib/arm64-v8a/libopencv_java3.so' } 

Now, v7a aar does not contain the arm64-v8a folder inside it but when I select v8a flavour, the folder exists but no libopencv_java3.so is placed inside it!

Should not this option only affect to v7a? What am I doing wrong? Any help will be appreciated.

Notes: gradle version tested: 3.1.2 and 3.1.4.

1 Answers

Answers 1

try to split differently, instead of using product favors -

alike this one can load armeabi-v7a assembly on arm64-v8a:

splits {     abi {         enable true         reset()         include "armeabi", "x86"         universalApk true     } } 

this would expect the (32bit version of the) library at armeabi/libopencv_java3.so.

externalNativeBuild only considers the libraries, which are being built (aka "your code"). if you insist on using the packagingOptions, you should not define them globally, but per product flavor.

v7a {     ...     packagingOptions {         exclude 'lib/arm64-v8a/libopencv_java3.so'     } } 
Read More

Tuesday, August 21, 2018

How to build a jar from a multi-module project when using Gradle?

Leave a Comment

I'm working on a multi-module library project which I build with Gradle. I have a dependency to another module of this project in my dependencies section:

dependencies {     compile project(':my-other-module') } 

My problem is that I want to build a .jar file which only contains the local modules in the final file, not its transitive dependencies. I tried this:

jar {     from project(':my-other-module').configurations.compile.collect { zipTree it } } 

but this added all the transitive dependencies as well. I want to create a .jar which only contains my own files, so the users of this library can have their own versions of transitive dependencies. How can I do so?

1 Answers

Answers 1

Gradle has a compile-only dependency concept, similar to Maven's provided scope:

Compile-only dependencies are distinctly different than regular compile dependencies. They are not included on the runtime classpath and they are non-transitive, meaning they are not included in dependent projects.

The dependencies you don't want can be declared in the compileOnly configuration, rather than compile, eg:

dependencies { compileOnly 'javax.servlet:servlet-api:2.5' }

compileOnly is not even visible to unit tests, by default. We change this in a common gradle snippet which we include in each build:

// compileOnly isn't visible to tests by default, add it plugins.withType(JavaPlugin).whenPluginAdded {     sourceSets {         test.compileClasspath += configurations.compileOnly         test.runtimeClasspath += configurations.compileOnly     } } 

For the second part, for which I believe you want to create a single "fat" jar, I would suggest creating your jar using the very good Shadow Plugin, rather than manually extending the jar task. By default, the shadow plugin will not include anything in the compileOnly configuration in the resulting jar.

Read More

Friday, July 27, 2018

Gradle Spring Boot Custom Configuration

Leave a Comment

I have an application which uses a mysql database to persist information. I would like to create a version of this application which uses an embedded database (mariaDB4j) and add it as a service to our CI environment, so when we launch this embedded version with our end-to-end test, the QA team gets a clean database.

I read a lot about this online, and it looks like gradle configurations are the way to go. The closest I found on this was:

sourceSets {     qaci {         java {             srcDir 'src/qa/java'         }         compileClasspath += sourceSets.main.runtimeClasspath         compileClasspath += sourceSets.main.resources     } }  configurations {     qaciCompile.extendsFrom compile }  bootRepackage {     customConfiguration = myCustomConfig } 

Unfortunately, bootRepackage was replaced by bootJar. I'm using gradle spring boot plugin 2.0.1.RELEASE, and when I try to use bootJar.customConfiguration I got an error saying that this is an unknown property.

Also, mariaDB4j requires a configuration class to work properly, I've included it at src/qa/java and created a new source set in order to it be added.

Does anyone knows how to tell the gradle spring boot plugin to use a custom configuration?

2 Answers

Answers 1

Have you thought about using spring profiles?

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

It will allow you to define a different set of values, beans or configuration sets for a handful of profiles (i.e. development, QA, production) and you can use them to run your app with different configurations or different libraries.

@Configuration @Profile("production") public class ProductionConfiguration {} 

This class will load all the values you set for that profile in your .properties or .yml file.

And the to run the app you can pass the profile you want to use as command line parameter

--spring.profiles.active=dev 

The configuration for your mariaDB will be under a particular profile.

For example (if you are using yml ):

spring:   profiles: QA   datasource:     url: jdbc:mariadb://qaserver:1234;databaseName=qaDatabase     username: USER     password: PASSWORD     driverClassName: org.mariadb.jdbc.Driver     //aditional mariadb properties, configs spring:   profiles: production   datasource:     url: jdbc:sqlserver://proddatabase:1433;databaseName=production     username: USER     password: PASSWORD     driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver 

Classes and properties belonging to other profiles will not be processed.

Answers 2

Automatically file system will be created in local path you have provided so you can restore the data while restarting/providing to qa.

-- Location of db files. delete this directory if you need to recreate from scratch

mariaDB4j.dataDir=./data/local 

Default is 3306, so using 3307 just in case it is already running on this machine

mariaDB4j.port=3307 app.mariaDB4j.databaseName=app_alpha spring.datasource.url=jdbc:mariadb://localhost:3307/ spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect 

you can refer this for more information https://objectpartners.com/2017/06/19/using-mariadb4j-for-a-spring-boot-embedded-database/

Read More

Discrepancy building project in Android Studio vs Gradle

Leave a Comment

I have a complex Android project consisting of multiple Java and C++ modules and using several build tools (e.g. CMake, swig). The project builds just fine when built from the command line using ./gradlew clean assembleDebug but fails to build when built from Android Studio. I cleaned, invalidated caches, synced, etc to no avail.

Important to note: this project builds fine in Android Studio too on other systems like Ubuntu (17.* and 18.*) but fails on MacOS (10.13 but also earlier if I remember correctly).

Here is the error reported by Android Studio:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':IndoorsLocator:runSwig'.     at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:84)     at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)     at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)     at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)     at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)     at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)     at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)     at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)     at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)     at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)     at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)     at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)     at org.gradle.internal.Transformers$4.transform(Transformers.java:169)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)     at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)     at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)     at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)     at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)     at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)     at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)     at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)     at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)     at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)     at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)     at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)     at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)     at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)     at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:196)     at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:193)     at org.gradle.internal.Transformers$4.transform(Transformers.java:169)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)     at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:193)     at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)     at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)     at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)     at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:50)     at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)     at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner$1.execute(RunAsBuildOperationBuildActionRunner.java:43)     at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner$1.execute(RunAsBuildOperationBuildActionRunner.java:40)     at org.gradle.internal.Transformers$4.transform(Transformers.java:169)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)     at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)     at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:40)     at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:75)     at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)     at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)     at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)     at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)     at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)     at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:44)     at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:29)     at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)     at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)     at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)     at org.gradle.util.Swapper.swap(Swapper.java:38)     at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)     at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)     at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)     at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)     at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)     at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)     at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)     at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)     at java.lang.Thread.run(Thread.java:745) Caused by: org.gradle.process.internal.ExecException: A problem occurred starting process 'command 'swig''     at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(DefaultExecHandle.java:198)     at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandle.java:329)     at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:86)     ... 5 more Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'swig'     at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)     at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)     at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:68)     ... 5 more Caused by: java.io.IOException: Cannot run program "swig" (in directory "/Users/tom/workspace/indoors-scripts/setup-scripts/workspace-android/IndoorsAndroid/IndoorsLocator"): error=2, No such file or directory     at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)     at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)     ... 7 more Caused by: java.io.IOException: error=2, No such file or directory     at java.lang.UNIXProcess.forkAndExec(Native Method)     at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)     at java.lang.ProcessImpl.start(ProcessImpl.java:134)     at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)     ... 8 more 

build failing in Android Studio

On the command line: build going through via command line (note we are passed "IndoorsLocator:runSwig" already)

Here is what the definition of "runSwig"-task looks like:

task runSwig(type: Exec) {     commandLine 'swig'      doFirst {         coreWrapperDir.mkdirs()     }      def swigFileCore = "${projectDir}/src/" + "swig.i"     def headerFiles = "${projectDir}/include"     def swigWrapFile = 'src/swig_wrap.cxx'      inputs.file swigFileCore     inputs.dir headerFiles     outputs.dir coreWrapperDir.absolutePath     outputs.file swigWrapFile      // this write the generated swig C++ file to "${projectDir}/src"     args '-c++', '-java', '-package', javaPackage, '-noexcept', '-outdir', coreWrapperDir.absolutePath, "-I${headerFiles}", '-o', swigWrapFile, swigFileCore } 

The log indicates that Android Studio is looking for swig in the current working directory instead of looking it up inside $PATH, but I am clueless about how to tell Android Studio where to look instead. Any ideas?

Cannot run program "swig" (in directory "/Users/tom/workspace/indoors-scripts/setup-scripts/workspace-android/IndoorsAndroid/IndoorsLocator") 

3 Answers

Answers 1

Have you added this line in your build.gradle?

tasks.withType(JavaCompile) {     compileTask -> compileTask.dependsOn runSwig } 

Anyway you can refer to this github's project that uses swig: https://github.com/sureshjoshi/android-ndk-swig-example

Answers 2

There is a need for some debugging to get more info about the problem. Add the code below to your build.gradle file of IndoorsLocator module and run it again. This should print the path environment variable and also run a java command which I'm assuming is also within the path. Then perform a gradle sync and compile or run the code. Open the build window as in your first image and when the build stops, find the testPath within the Run tasks list and share it's output. Or more preferably, switch the Build to text view as in the image below and share the complete log. Testing it from the command would also help to make sure that it's running as expected.

tasks.whenTaskAdded { addedTask ->     if (addedTask.name.startsWith("preDebugBuild")) {         addedTask.dependsOn 'testPath'     } }  task testPath {     mustRunBefore 'checkDebugManifest'     doLast {         exec {             commandLine 'echo', '$PATH'         }         exec {             commandLine 'java', '-version'         }     } } 

enter image description here

Update 1

Based on your first comment, this is a weird outcome! Java is supposed to be in the path, so $PATH must've been set somehow yet echo $PATH didn't work. Updated the code to further go down the rabbit hole.

tasks.whenTaskAdded { addedTask ->     if (addedTask.name.startsWith("preDebugBuild")) {         addedTask.dependsOn 'testPath'     } }  task testPath {     doLast {         exec {             commandLine 'printenv'         }         exec {             commandLine 'which', 'java'         }         exec {             commandLine 'which', 'swig'         }     } } 

PS: my mistake on the mustRunBefore, it doesn't exist and I added it accident!

Answers 3

Turns out this is due to a "bug" in OSX: https://github.com/gradle/gradle/issues/5631#issuecomment-401775152

I did not find a way to easily fix it for the latest version of OSX (https://apple.stackexchange.com/questions/106355/setting-the-system-wide-path-environment-variable-in-mavericks) but worked around it by hardcoding the path in build.gradle:

task runSwig(type: Exec) {     // workaround for OSX, see https://stackoverflow.com/q/51383822/198996     File testFile = new File('/usr/local/bin/swig');     if (testFile.isFile()) {         commandLine '/usr/local/bin/swig'     } else {         commandLine 'swig'     } } 

That's an awful workaround if you ask me, so I would be happy to award the bounty to whoever comes up with a cleaner solution.

Read More

Tuesday, June 5, 2018

Why does Gradle ignore sourceSets and/or srcDir when dealing with proto files?

Leave a Comment

My directory structure is src/ps/proto. My build.gradle file is located in the src directory. I've set sourceSets to

sourceSets {     ps {         proto {              srcDir 'ps/proto'         }     } } 

Yet, a gradlew generatePsProto gives me a slew of error, one of which is that my source directory is src/src/ps/proto.

Execution failed for task ':generatePsProto'. > protoc: stdout: . stderr: /home/build/tree/src/src/ps/proto: warning: directory does not exist.   [libprotobuf WARNING google/protobuf/compiler/parser.cc:546] No syntax specified for the proto file: cldb.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)   ps/proto/security.proto: File not found.   ps/proto/common.proto: File not found.   ps/proto/cli.proto: File not found.   ps/proto/volumemirrorcommon.proto: File not found.   ps/proto/metrics.proto: File not found.   cldb.proto: Import "ps/proto/security.proto" was not found or had errors.   cldb.proto: Import "ps/proto/common.proto" was not found or had errors.   mldb.proto: Import "ps/proto/cli.proto" was not found or had errors.   mldb.proto:214:12: "CredentialsMsg" is not defined.   mldb.proto:218:12: "CredentialsMsg" is not defined.   [...]   mldb.proto:3614:12: "Key" is not defined.   mldb.proto:3618:12: "CredentialsMsg" is not defined.   mldb.proto:3619:12: "ServerKeyType" is not defined. 

I don't want the Gradle default of src/ps/proto. I want ps/proto. Can this be done? My goal is to remove the hard coded exec calls to protoc and use the protobuf pluging to compile the *.proto files into their respective *.h, *.cc, and eventually into *.o files.

Gradle 4.7 Build time: 2018-04-18 09:09:12 UTC Revision:
b9a962bf70638332300e7f810689cb2febbd4a6c

Groovy: 2.4.12 Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017 JVM: 1.8.0_144 (Oracle Corporation 25.144-b01) OS: Linux 3.10.0-514.el7.x86_64 amd64

build.gradle

buildscript {     repositories {         mavenCentral()     }     dependencies {         classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'     } }   apply plugin: 'c' apply plugin: 'cpp' apply plugin: 'java' apply plugin: 'com.google.protobuf'  repositories {     mavenCentral() }  dependencies {     compile "com.google.protobuf:protobuf-java:2.4.1" }   sourceSets {     ps {         proto {             srcDir 'ps/proto'         }     } }  protobuf {     protoc {         artifact = 'com.google.protobuf:protoc:2.4.1'     }      generateProtoTasks {         all().each { task ->             task.plugins {                 cpp {}             }         }     } } 

2 Answers

Answers 1

Gradle has a widely applicable convention that collection properties can be configured with methods of the same name. The key difference between setting a property using assignment (=) and using a method is that the latter appends its values.

So, to override the default source directory for the source set you need to use assignment:

sourceSets {     ps {         proto {             srcDirs = ['ps/proto']         }     } } 

I don't really understand why you're getting an error message about src/src/ps/proto, so there may be some other issue. That error seems to be coming from protoc rather than Gradle.

EDIT

To solve your import problem, you should use

import security.proto; 

i.e. without the source directory path. This is because the Protobuf Gradle Plugin appears to add each source directory as an "include directory". protoc only looks in such include directories for imports.

This is at least what I have garnered from the documentation and source code.

Answers 2

You seemed to have typo either for 'fs' or 'ps'.

The problem is the Import. because you have for example

cldb.proto: Import "ps/proto/security.proto"

mldb.proto: Import "ps/proto/cli.proto"

Edited:

you have to put every .proto file in src/yourCustomSourceSetName/proto/ps/proto/ and add

sourceSets {     yourCustomSourceSetName {} } dependencies {     compile ...  // dependencies for compileJava task     yourCustomSourceSetNameCompile ... // dependencies for custom sourceSet     compile sourceSets.yourCustomSourceSetName.output // compileJava uses output of the custom sourceSet } 

Then the import will look for other .proto files in the right place.

Read More

Sunday, May 27, 2018

Gradle: Using setIgnore on a local library based on the apps build.gradle flavor.

Leave a Comment

How do I use setIgnore on a local library either from the apps build.gradle or the library build.gradle based on the apps flavor. I am not sure if I can reference the apps build.gradle flavor/dimension from the library build.gradle. I also don't know if I can reference a library from the apps build.gradle and use lib.setIgnore(true). Any solution to solving this issue?

I am currently only using one dimension for the application and multiple flavors.

This is how it is typically done; but I need to set Ignore on a library based on the apps flavor.

android {     ...     variantFilter { variant ->         if(variant.buildType.name == 'release' && variant.getFlavors().get(0).name == 'vanilla') {             variant.setIgnore(true)         }     } }  

2 Answers

Answers 1

Maybe you can use the library only when you need.

dependencies {    // use "mylib" for debug    debugImplementation project(path: ':mylib')    // all the flavors    implementation "com.android.support:appcompat-v7:28.0.0' } 

Answers 2

You can try to wait for the task graph to be assembled and then removes the undesired name pattern as follows:

gradle.taskGraph.whenReady { graph ->   graph.allTasks.findAll { it.name ==~ /.*vanilla.*/ }*.enabled = false } 
Read More

Tuesday, May 22, 2018

Android Gradle - how to include shared object with specific folder structure?

Leave a Comment

Normally when you use Android Gradle package, you can include individual shared objects (.so's) using configuration parameter jniLibs.srcDirs. .so file gets included in flat manner. But what if I want to include plugins into their own correspondent sub-folders ?

Also taking into account product flavors ?

I have uploaded at least one demo project over here:

https://sourceforge.net/p/syncproj/code/HEAD/tree/sampleScripts/AndroidGradlePackage

(In case if you want to play around by yourself - it's slightly simplified Android java-c++ project).

Currently folder structure is following:

bin\Debug\armeabi-v7a\libnative_lib.so 

I want to add folder structure like this:

bin\Debug\armeabi-v7a\plugins bin\Debug\armeabi-v7a\plugins\test1 bin\Debug\armeabi-v7a\plugins\test1\test1.so 

There exists bug report over here: https://issuetracker.google.com/issues/63707864

with status 'Won't fix' - but if this is not fixed - maybe there are some walkaround to it ?

I have tried at least what is mentioned on that page - plugins folder structure gets created, with *so.recipe files inside, but no .so files for some reason - someone seems to filter .so out of there.

Most interesting thing is that generated file build\native-libs\native-libs.jar indeed contains 1. *.so and 2. *.so.recipe files, but only 2nd gets included.

One of solutions mentioned over here:

https://medium.com/keepsafe-engineering/the-perils-of-loading-native-libraries-on-android-befa49dce2db

Attempts to replace java's 'System.loadLibrary' - but aren't there any simpler solution to this ?

So this solution can include *.so.recipe into .apk package: (Just in case if you want to try to continue with my approach) (Must be applied to project link above after dependencies)

dependencies {         implementation 'com.android.support.constraint:constraint-layout:1.0.2'         // See (*)         compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')     }    // See (*) task nativeLibsToJar(type: Zip) {     destinationDir file("$buildDir/native-libs")     baseName 'native-libs'     extension 'jar'     from fileTree(dir: getCurrentConfigAbiDir() + "/plugins", include: '**/*.so*')     // '/lib/armeabi-v7a' - same folder as in .apk package     into '/lib/' + getCurrentAbiFolder() + "/plugins" }  // // (*) Walk around issue of not being able to add files recursively from sub-folders as well. // https://issuetracker.google.com/issues/63707864 // tasks.withType(JavaCompile) {     compileTask -> compileTask.dependsOn(nativeLibsToJar) }  //------------------------------------------------------------------------------------------------ // Helper functions //------------------------------------------------------------------------------------------------  // //  Gets current Abi folder name, empty if not detected - for example "armeabi-v7a" // String getCurrentAbiFolder() {     String[] props = getCommandLineArgs()     if( props.length != 2 )         return ""      String platform = props[0]     String config = props[1]     String r = ""      android.productFlavors.all { flavour ->         if( flavour.name.toLowerCase() == platform.toLowerCase() )             r = flavour.ndk.abiFilters.first().toLowerCase()     }      // println r     return r }   String getCurrentConfigAbiDir() {     String dirToZip = "DoesNotExists"      String[] props = getCommandLineArgs()     if( props.length != 2 )         return dirToZip      String platform = props[0]     String config = props[1]      android.productFlavors.all { flavour ->         if( flavour.name.toLowerCase() == platform.toLowerCase() )             dirToZip = "bin/" + config + "/" + flavour.ndk.abiFilters.first().toLowerCase()     }      // println dirToZip     return dirToZip } 

0 Answers

Read More

Saturday, May 5, 2018

Overwrite Application Id Outside of Flavors and Build Types

Leave a Comment

I have an application with many flavors (A,B,C) and two build types (debug,release)

In the build type debug I add a suffix to the application ID like so:

debug {     applicationIdSuffix '.debug' } 

This is fine for flavors A and B but I can't append .debug to flavor C's application ID.

I have looked at overriding on the variant like I have for the versionCode but no luck.

    applicationVariants.all { variant ->         def changedVersionCode = variant.versionCode         variant.         variant.outputs.each { output ->             if (variant.buildType.name != "debug") {                 output.setVersionCodeOverride(project.ext.versionCode)                 changedVersionCode = project.ext.versionCode             }          }         changeApkFileName(variant,changedVersionCode)     } 

Is it possible to override a variants application ID depending on the flavor. For example my plan was to do something like this:

variant.buildType.name.replace('.debug','')

1 Answers

Answers 1

Is it possible to override a variants application ID depending on the flavor

Yes it is possible.

The reason you are not able to see the expected id is:

Because Gradle applies the build type configuration after the product flavor, the application ID for the "C" build variant will be "<your-applicaion-id>.debug".

So if you want it to be different for different flavors then you have to segregate the applicationIdSuffix for different flaovors and remove it from debug {} as follows:

android {     defaultConfig {         applicationId "<your-application-id>"     }     productFlavors {         A {             applicationIdSuffix ".debug"         }         B {             applicationIdSuffix ".debug"         }         C {             applicationIdSuffix ""         }     } } 

For more details, refer to official documentation.

Read More

Friday, April 6, 2018

Configuring Gradle to speed up cordova-cli builds

Leave a Comment

I use Cordova CLI to build my hybrid Android app. In my effort to speed up compile times I have moved the entire Android installation to an SSD and upgraded my machine with an extra 8Gb of memory (total of 16Gb). Nevertheless I see zero effect on compile times which are stuck at pretty much the same figure as they were prior to these upgrades. I am starting to suspect that it is not enough to merely provide more resources. Somehow Gradle needs to be told to use them. However, I am not sure how I do this within the context of a hybrid Cordova app.

Acting on the ideas I found in this Reddit thread I created a gradle.properties file in the app/platforms/android folder where I put

org.gradle.parallel=true org.gradle.daemon=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xms2048m -Xmx8096m -XX:PermSize=1024                     -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=1024m 

This did have an effect - it made the build almost 50% slower! The first build with a new Gradle daemon is usually slower so I recompiled. There was a small saving but the build was still slower than before. Clearly, there is more to configuring Gradle than telling it to use tons of memory. However, I have no experience in the domain. Could someone here tell me how I should go about the process in order to get some real performance benefits?

2 Answers

Answers 1

I was recently working on tuning Jenkins pipelines and migrating an app from Maven to Gradle so I hope my knowledge might be useful.

First of all, you can measure difference in execution time in the following way:

  • remove all .gradle folders. It is Gradle's cache folders and it might be accidentally used.
  • execute gradle --stop. It will stop Gradle daemons so that no cache in daemons itself can be used.
  • run gradle clean build

Secondly, the gain that you've got is mostly due to using org.gradle.parallel=true. You may try to remove other things and I bet there will be no significant change in performance. org.gradle.daemon=true is the default value for the option. Also, I would revise JVM flags as e.g. -XX:MaxPermSize is not used in Java 8 (although I understand you're working on Android app)

Thirdly, regarding speeding up the compilation itself, you can use this flags:

GRADLE_OPTS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1" 

It should turn off JVM profiling so it might do the trick for you.

Thirdly, check compile vs implementation. Using of implementation configuration theoretically may speed up compilation and recompilation process because of not using transitive dependencies.

I guess I don't know other ways to speed up compilation of a Gradle project. However, there are things like parallel test execution if you're interested in speeding up the whole build.

The last note: check you plugins. Sometimes they do useless things you don't really need (mine bottleneck was wsdl2java) e.g. copying many unused generated sources.

Hope it helps!

Answers 2

Move your project's build folder to SSD: there are tons of write operations during build and write is always much slower than read.

And configure antivirus software (if any) to exclude all java binaries, project's build folder and ~/.gradle from scanning.

These two actions should be enough to see the difference.

Read More

Monday, March 26, 2018

Add folder to srcDir except for one file in gradle

Leave a Comment

I'm developing an android app with multiple flavors like so:

sourceSets {     main {         res.srcDirs += ["headend/ott/res"]     }      flavor1 {         res.srcDirs += ["src/module1/res-splash"]     }      flavor2 {         java.srcDirs += ["src/module1/java"]         res.srcDirs += ["src/module1/res"]         res.srcDirs += ["src/module2/res"]         assets.srcDirs += ["src/module1/assets"]     }      test {         res.srcDirs += ["src/test/resources"]     }     ... 

My problem is that, in flavor2, some of the module2 resources are supposed to be replacements of ones already present in module1, but with my current approach it causes the build to fail with duplicate resources.

So what I need is a way to add "src/module1/res" to flavor2 but without including one specific file.

I've tried

res{     srcDirs += ["src/module1/res"]     res.srcDirs += ["src/module1/res"]             exclude 'src/module1/res/drawable/specific_file.xml' } 

But to no avail.

Is this possible at all?

2 Answers

Answers 1

After looking at multiple answers like this, the code that you have looks correct to me. However, this bug stating that exclude paths are not implemented is still open.

This alternate approach which references these docs may work for you instead. I suggest adding a resource directory inside your flavour2 directory/module and using it to include a discard file.

sourceSets {     flavor2 {         res {             srcDirs += ["src/module1/res"]             srcDirs += ["src/module2/res"]         }     }  } 

Then add resources_discard.xml to module2/res/raw with the following:

<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"           tools:discard="@drawable/specific_file.xml" /> 

Answers 2

Try doing this. In one of my projects, I was able to exclude java file from compiling by not using the srcDir path in the exclude path. exclude usually works without appending the srcDir path.

res{     srcDirs += ["src/module1/res"]     res.srcDirs += ["src/module1/res"]             exclude 'drawable/specific_file.xml' } 
Read More

Thursday, March 15, 2018

Could not resolve com.android.tools.build.gradle:3.0.1

Leave a Comment

I'm forcing gradle to use http I have modified my gradle-wrapper.properties:

distributionUrl=http\://services.gradle.org/distributions/gradle-4.3-all.zip 

The build.gradle:

buildscript { repositories {     //jcenter()     //google()     maven { url "http://jcenter.bintray.com"}          } dependencies {     classpath 'com.android.tools.build:gradle:3.0.1'      // NOTE: Do not place your application dependencies here; they belong     // in the individual module build.gradle files }}  allprojects { repositories {     jcenter()     maven { url 'http://maven.google.com' }     maven { url "http://jitpack.io" } }} 

As far as I'm aware I should use 3.0.1 but when I check the actual repo on jitpack or maven only up to 2.3.3 is available.

The error message I'm getting is:

> Could not resolve all files for configuration ':classpath'. > Could not find com.android.tools.build:gradle:3.0.1. Searched in the following locations: http://jcenter.bintray.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom http://jcenter.bintray.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.jar Required by:      project :* Try: 

Gradle version is 4.3.1 JVM 9.0.1

What can be done to successfully run 'gradle test' here?

EDIT: uncommenting //google() reveled:

       > Could not get resource 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'.         > Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'. 

When modified the http repo

buildscript { repositories {     //jcenter()     //google()     maven { url "http://jcenter.bintray.com"}     maven { url "http://maven.google.com"}      } 

I got:

      > Could not resolve com.android.tools.build:gradle:3.0.1.      > Could not get resource 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'.         > Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'.            > sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target   > Could not resolve com.android.tools.build:gradle:3.0.1.      > Could not get resource 'http://maven.google.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'.         > Could not GET 'http://maven.google.com/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom'.            > sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

I get the same if I uncomment both jcenter() and google(). Besides, when I check https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/ the link is dead. Now the jcenter repo https://repo1.maven.org/maven2/com/android/tools/build/gradle/ ends on 2.3.3 version which seems to be correct that this error is happening, the question is what is wrong then?

EDIT- Likely solution the issue happenned because you can't run those excluding https completely, it will fail either way.

5 Answers

Answers 1

Could not resolve com.android.tools.build:gradle:3.0.1.

Read Google's Maven repository

Include Google's Maven repository in your top-level build.gradle file:

FYI

allprojects {     repositories {         google()          // If you're using a version of Gradle lower than 4.1, you must instead use:         // maven {         //     url 'https://maven.google.com'         // }         // An alternative URL is 'https://dl.google.com/dl/android/maven2/'     } } 

So, According to your version your build.gradle will

buildscript  {      repositories {         jcenter()         google()         maven { url "http://jcenter.bintray.com"}          }     dependencies {         classpath 'com.android.tools.build:gradle:3.0.1'      } }  allprojects  {     repositories {         jcenter()         maven { url "https://jitpack.io" }         google()     } }  task clean(type: Delete) {     delete rootProject.buildDir } 

Answers 2

What worked for me was to remove jcenter() and revert Gradle to an earlier version.

Unfortunately the latest stable version in bintray is 2.3.3 , but atleast I was able to build successfully.

My build.gradle now looks like this:

buildscript {     repositories {         maven { url "http://jcenter.bintray.com"}     }     dependencies {         classpath 'com.android.tools.build:gradle:2.3.3'          // NOTE: Do not place your application dependencies here; they belong         // in the individual module build.gradle files     } }  allprojects {     repositories {         maven { url "http://jcenter.bintray.com"}     } } 

Answers 3

Try this and make sure your network works well (no proxy ...) :

in gradle-wrapper.properties :

distributionUrl=  https\://services.gradle.org/distributions/gradle-4.1-all.zip 

and in build.gradle:

buildscript {     repositories {         jcenter()          google()     }     dependencies {         classpath 'com.android.tools.build:gradle:3.0.1'     } }  allprojects {     repositories {         jcenter()         google()     }  } 

Answers 4

Not sure but your this error Could not resolve all files for configuration ':classpath'. When your path is not set so Follow below step:

Go to the File -> Setting -> Version Controller

Then you Change VCS to < None >

see below image :

enter image description here

Answers 5

I got the same issue and i solved it by making changes main gradle file, as per suggestion given by android studio

buildscript {     repositories {         jcenter()          google()     }     dependencies {         classpath 'com.android.tools.build:gradle:3.0.1'     } }  allprojects {     repositories {         jcenter()         google()     } }  task clean(type: Delete) {     delete rootProject.buildDir } 

gradle-wrapper.properties :

distributionUrl=  https\://services.gradle.org/distributions/gradle-4.1-all.zip 

my gradle file is like this, make like this in you project it would most probably work.

Thank you.

Read More

Wednesday, January 10, 2018

Compile or build Library’s build.gradle file when we compile or build Main project

Leave a Comment

I am having one Library Project which is developed by me, inside Library, in gradle file I have mentioned one specific task, like show the root project and library project path.

Now when I am adding this Library to my other project and when I build the project, I wanted to build the Library gradle file so that it performs the task which I have mentioned in Library gradle file.

There is one library inside that library, I have one plugin,

// automatic code generation apply plugin: 'jsonschema2pojo'  // automatic code generation buildscript {     repositories {         jcenter()         mavenLocal()      }     dependencies {         classpath 'org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:0.5.1'         //classpath 'org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:latest.integration'      } }  // automatic code generation // Each configuration is set to the default value jsonSchema2Pojo {     generateBuilders = false     usePrimitives = false     source = files("${rootProject.projectDir}/schema/schema/")     targetPackage = 'com.model'     propertyWordDelimiters = [] as char[]     useLongIntegers = false     useDoubleNumbers = true     includeHashcodeAndEquals = true     includeToString = true     annotationStyle = 'gson'     customAnnotator = 'org.jsonschema2pojo.NoopAnnotator'     includeJsr303Annotations = true     sourceType = 'json'     boolean removeOldOutput = true     String outputEncoding = 'UTF-8'     boolean useJodaDates = false     boolean useCommonsLang3 = false     boolean initializeCollections = true }   dependencies {     compile fileTree(include: ['*.jar'], dir: 'libs')     androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {         exclude group: 'com.android.support', module: 'support-annotations'     })      //  code generation     compile 'org.glassfish:javax.annotation:10.0-b28'     compile 'commons-lang:commons-lang:2.6'     compile 'javax.validation:validation-api:1.1.0.CR2'      testCompile 'junit:junit:4.12' } 

Now, I want this code or Gradle to build while I add this library to my other project.

0 Answers

Read More

Friday, December 29, 2017

How to build 1 jar from 3 sub-modules by using gradle

Leave a Comment

I have:

  • Android Studio 3
  • gradle 4.1
  • gradle tools 3: classpath 'com.android.tools.build:gradle:3.0.1'

When I had one module and used gradle tools 2, I used:

task makeJar(type: Copy) {     def releaseFolder = new File('build/intermediates/bundles/release/')     if (releaseFolder.exists()) {         from('build/intermediates/bundles/release/')     } else {         from('build/intermediates/bundles/default/')     }     into('build/outputs/jar/')     include('classes.jar')     rename ('classes.jar', 'MY-Android-SDK.jar') } 

Now have 3 modules:

              MainModule (com.my)                  /   \ (com.my.m1) Module1   Module2 (com.my.m2) 

I want to create MY-Android-SDK.jar file from all 3 modules.

So far I will be able to create 3 jar files per module and somehow merge them but I believe its not right way to do that.

Any ideas?

1 Answers

Answers 1

First of all, if you are creating android libraries, create AARs, not JARs. AAR files follow the android SDK structure and can have manifest files, and therefore, require permissions, and xml resources, among other things.

Second, if you are creating a framework from several different modules (a pretty reasonable approach in fact!), you should create different artifacts (AAR/JAR files). That makes easier to handle transitive dependencies, SDK level conflicts, consuming only what you need (there will be cases when you don't need half of your SDK and in that case discarding a few entries in the gradle files is way easier than fiddling with proguard to delete all the unused classes), providing alternative implementations or pluggable systems (for example, you create a contract module for, let's say, DFP, and a double click module. Then, by Inversion of Control, you fill the contract using double click, next month, they ask you to replace double click with amazon ads. You create a module with amazon ads following the contract module and replace the injected double click reference by amazon.)

Regardless of that, remember transitivity. Depending on how you bring your dependencies, everything can be added to the path by using a single dependency in the build.gradle file. If you use 'api':

api 'com.myname:moduleX:xxx' 

In module com.myname:moduleY, moduleX will be in the path as well. Use the Gradle maven plugin for creating the artifacts in the first place. That will allow you to create an android AAR file using the "install" task and will deploy it to your local maven repo (mavenLocal() in gradle). If you include all the submodules using "api", they will be added to the path. I don't recommend doing that, instead, import only what's necessary in each module and create separate AAR files for each module and consume them in your apps.

Now, if for some reason, you need to create a fat/Uber JAR, well, that process is called "shading". So, you'll need a shade plugin for gradle. Fortunately, there's a few. Just pick the best for your case (or use maven, and the maven shade plugin). Regardless, as someone with some experience developing libraries and frameworks, keep your modules as atomic and separate as possible. Lastly, if you need a working example for the gradle maven plugin, try this, it's old, but works as an example. good luck!

Read More

Saturday, December 16, 2017

Duplicate value fo resource 'attr/tint'

Leave a Comment

I do not know how this error started to happen, I simply closed the android studio yesterday and I turned off the pc, today, I turned on the pc and opened the android studio, then this error appeared soon after opening the android studio.

What have I tried?

invalidate cache

rename and delete files that look like duplicates.

delete .gradle and clear / rebuild project

C:\Users\joaoa.gradle\caches\transforms-1\files-1.1\appcompat-v7-27.0.1.aar\70b6446a0ad42e67664086d0c5dca4d5\res\values\values.xml

C:\Users\joaoa\Desktop\MyPast\myProjects\project001\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml

Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

Error:Execution failed for task ':app:mergeDebugResources'. Error: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

4 Answers

Answers 1

Please open show log in files and delete all the files where you located and please restart your android studio.

if not solved then Again restart with option like InvalidDate Cache and Restart.

Hope this helps you.

Answers 2

check dependencies in gradle file.

2 or more libraries use in project conflict resource file.

example:

in library A,B in variables in arrts.xml or color.xml

Answers 3

I don't think this is a gradle version issue... I am using Android Studio 3.0 with Gradle Plugin Version 3.0.1 (which uses Gradle 4.1) THE LATEST. And I am getting this same issue. Just rename whatever attribute you've named tint to something like libTint or lib_tint or even more obscure ili_lib_tint so the issue can be resolved. I really want to use this lib and not look else where, please.

This is the xml element causing the issue

ImageLetterIcon/imageletter/src/main/res/values/attrs.xml

 <declare-styleable name="TintableImageView"> 

Answers 4

Android studio creates many files that are not part of the normal source code. If you reboot without saving your project things may get whacked out but this could happen for no apparent reason. You have already cleaned your project so it regenerates some of these files. The .metadata file in the root of your workspace can be deleted but you will need to import all projects already in the workspace. I suggest you check the directory structure of your project using something other than android studio and even delete any generated folders as they will rebuild on the next compile. Perhaps even use a new workspace and copy source code over. First thing you should do is backup everything you want to keep as these suggestions could cause disaster if you are not careful. Consider version control, git repositories or github to save your project in the future as you can roll back to a previous state in the future

Read More

Friday, December 15, 2017

Gradle buildSrc and buildscript

Leave a Comment

We have a Gradle build that includes a buildSrc with some custom plugins. Those plugins apply yet other plugins. For example, our plugin applies com.android.tools.build:gradle. For annotation processing that library needs to be on Gradle's classpath during compilation. So, putting this in our main build.gradle works:

buildscript {     repositories {         google()     }     dependencies {        classpath "com.android.tools.build:gradle:$gToolsVersion"     } } 

However, that means that for a user to apply this plugin they must (1) apply our plugin and (2) add that buildscript boilerplate. It seems like that shouldn't be necessary. We can also add a project.buildscript block inside our plugin but that too seems unnecessary and, due to this bug is problematic: https://developer.android.com/studio/build/gradle-plugin-3-0-0.html?utm_source=android-studio#known_issues.

I added the com.android.tools.build:gradle dependency to buildSrc/build.gradle as a runtime dependency. It seems like that should work: I thought that tells Gradle that in order to run my plugin that library (and its dependencies) need to be on the classpath. However, gradle buildEnvironment (and the fact that our build fails) makes it clear that's not the case.

So, questions:

  1. What's the difference between a runtime dependency specified in buildSrc/build.gradle and a classpath dependency specified in a buildscript block in a regular build.gradle?
  2. How can I arrange things so that users can apply the plugin from buildSrc and not have to also add the buildscript block to their build.gradle?

0 Answers

Read More

How to install a compiled by Gradle jar into the local Gradle Repository files-2.1 instead of the Maven repository?

Leave a Comment

In my build.gradle, I added the plugin:

apply plugin: 'maven' 

Then using “gradle install” I can copy the resulted jar into the maven repository : ~/.m2/repository

However, my Gradle repository resides in ~/.gradle/caches/modules-2/files-2.1. How can I install the jar into this repository?

4 Answers

Answers 1

mavenLocal() is resolved like this:

In order to make use of a non-standard local maven repository, you can use the following configuration in your build.gradle:

repositories { maven { url '/Users/manuelj/apache/maven/repository' } }

Answers 2

A build.gradle sample to create a Jar file along with its logback dependencies. using mavenlocale() apply plugin: 'java'

apply plugin: 'eclipse'

version = '1.0'

sourceCompatibility = 1.7

target Compatibility = 1.7

//create a single Jar with all dependencies

task fatJar(type: Jar) {

 manifest {      attributes 'Implementation-Title': 'Gradle Jar File Example',          'Implementation-Version': version,          'Main-Class': 'com.mkyong.DateUtils' } baseName = project.name + '-all'  from { configurations.compile.collect { it.isDirectory() ? it :  

zipTree(it)

}

} with jar }

//Get dependencies from Maven central repository

repositories {

mavenCentral() 

}

//Project dependencies

dependencies {

compile 'ch.qos.logback:logback-classic:1.1.2' 

}

Reference create a Jar file along with its logback dependencies.

Answers 3

If you insist on manipulating the cache, then your best bet is to write a shell script that will manually replace latest JAR in the cache.

The reason is that Gradle does not come with this functionality built-in, as Gradle uses notion of "local cache" in a strict sense, as opposed to "local repository" which is used by Maven.

The difference is that you are never supposed to save files to local cache manually.

To solve your problem the recommended way: Suppose that project A is a dependency of project B. Then you can call publishToMavenLocal command in project A to refresh the depedency. Add mavenLocal() repository in gradle.build of project B, so every time you build project B, Gradle will check the local repository when resolving the dependency A.

Answers 4

What worked for me is gradle install -Dmaven.repo.local=the/path/of/the/folder.

I don't know which IDE you are using but in eclipse you can add a new Run Configuration, in Gradle taks add install and in program arguments -Dmaven.repo.local=the/path/of/the/folder.

Read More

Monday, December 4, 2017

Download and commit gradle dependencies and plugins in Android Studio

Leave a Comment

This is an excerpt from a build.gradle file for one of my modules. I'm using android-studio-1.5.1 and gradle 2.10.

dependencies {     compile fileTree(dir: 'libs', include: ['*.jar'])     testCompile 'junit:junit:4.12'     compile 'com.android.support:appcompat-v7:23.2.1'     compile 'com.android.support:design:23.2.1'     compile 'com.google.android.gms:play-services-gcm:9.0.0'     compile 'com.squareup.picasso:picasso:2.5.2' } 

I also have classpath 'com.google.gms:google-services:3.0.0' in the project level build.gradle file.

I'm trying to gather all the associated jars into a directory which I can commit to my git repo. Something like:

task copyRuntimeLibs(type: Copy) {     into "${projectDir}/libs"     from configurations.compile } 

(This does not work) Also, I'm not trying to download the sources or javadocs.

I need to be able to commit all dependencies so that the project can be shared on an intranet without internet access.

1 Answers

Answers 1

I've written a plugin which will download all jars and poms. See the code here to download all jars and all poms from a Gradle Configuration

Note: There's a failing test here which shows that the parent pom's are not being downloaded. I've raised an issue here on Gradle's github.

I will likely improve the plugin to invoke the Maven Model Builder APIs to get the parent poms.

FYI - I've already integrated the ModelBuilder APIs successfully with Gradle (see here and here) so shouldn't be too difficult.

Read More