How to change the default output folder for generated apk files? - android

When I use the gradle task to create an android .apk file it outputs it the the build\javafxports\android folder of the project (both the regular and unaligned files). I couldn't find a setting to change the output folder.
When I export a jar in eclipse I can specify a destination folder. How can I do that with apk files too?
Here is my build.gradle file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.1.1'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.gluonapplication.GluonApplication'
dependencies {
compile 'com.gluonhq:charm:4.0.1'
}
jfxmobile {
downConfig {
version = '3.0.0'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
compileSdkVersion = 24
manifest = 'src/android/AndroidManifest.xml'
androidSdk = 'C:/Users/Mark/AppData/Local/Android/sdk'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}

The jfxmobile plugin allows changing the path where the apk will be created.
Use installDirectory:
jfxmobile {
downConfig {
version = '3.0.0'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
installDirectory = file('/full/path/of/custom/folder')
manifest = 'src/android/AndroidManifest.xml'
}
}
Be aware that the folder should exist before running android task. Currently the plugin manages that for the default installation folder (removing it, and the apk, if exists and creating it again on every run). So you have to do it yourself, otherwise the task will skip it.
EDIT
The list of global variables that are intended to be modified if necessary are here, but the full list of variables currently included in the plugin can be found in the plugin source code.
Variables like installDirectory are used internally by the plugin and they are initialized with a default value, perform some actions like deleting the previous directory and creating it again (so Gradle performs the task). In case of overriding, these actions won't be executed, so you should take care of that yourself (or create a task for that).

This works for the standard android plugin to change the directory of the generated APKs:
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = file("/some/dir/" + variant.name + "/" + archivesBaseName + ".apk")
}
}
}

Related

Minimal working SpotBugs setup for Android Studio

How do I set up SpotBugs for Android?
I tried following the official documentation and that of the gradle plugin, but the setup for Android is incomplete and confusing, and didn't work.
I tried the following setup.
build.gradle (project):
buildscript {
repositories {
// ...
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
// ...
classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.4"
}
}
build.gradle (app):
//...
apply plugin: "com.github.spotbugs"
android {
// ...
sourceSets {
main {
java.srcDirs = ['src/main/java']
}
}
}
// ...
spotbugs {
toolVersion = "3.1.3"
ignoreFailures = true
reportsDir = file("$project.buildDir/findbugsReports")
effort = "max"
reportLevel = "high"
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
// What do I need to do here?
}
I tried running it with ./gradlew spotbugsMain, but the gradle task is missing.
Am I supposed to add the task manually? How do I do that?
Could you show me an example of a minimal working setup for an Android project?
I made some tests on my side and I manage to make it work like this :
1) Move the sourceSets declaration outside the android block. Leave it empty, it's just for the spotbugsMain task generation, it won't impact the global Android build.
android {
// ...
}
sourceSets {
main {
java.srcDirs = []
}
}
2) Keep your spotbugs block and configure the SpotBugsTask tasks like this :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
It will generate reports in app/build/findbugsReports
Important :
It only works with the ./gradlew build command, ./gradlew spotbugsMain won't work as the project must be built before
You can fix that adding an assemble dependency :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
dependsOn 'assemble'
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
Following on from ToYonos answer (9 October 2018); Use this for Android Studio 3.4 and above:
project/build.gradle
buildscript {
repositories {
google()
jcenter()
maven {
url 'https:// maven url 1'
}
maven {
url "https://plugins.gradle.org/m2/" // Add this, for SpotBugs
}
}
dependencies {
classpath '...'
// If you're using gradle 6.x, add this to use SpotBugs app version 4.0.2
classpath "gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.3.0"
// If you're using gradle 4.x or 5.x, add this to use SpotBugs app version 3.1.2
classpath "com.github.spotbugs:spotbugs-gradle-plugin:2.0.1"
}
}
project/app/build.gradle
apply plugin: 'com.android.application'
apply plugin: '...'
apply plugin: "com.github.spotbugs" // <- Add this
dependencies {
...
}
// This block is only needed for gradle 4/5 only.
// It's for SpotBugs to create a 'spotbugsMain' gradle task.
sourceSets {
main {
java.srcDirs = []
}
}
spotbugs {
ignoreFailures = true
reportsDir = file("$project.buildDir/SpotBugsReports")
effort = "max"
reportLevel = "high"
}
// Note: gradle 4/5 should use "com.github.spotbugs.SpotBugsTask"
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
dependsOn 'assembleDebug'
classes = files("$project.buildDir/intermediates/javac") // Important to use this path
excludeFilter = file("$project/spot-bugs-exclude.xml") // Optional - Explained below
source = fileTree('src/main/java') // Only needed on gradle 4/5
reports {
// Enable HTML report only
html.enabled = true
xml.enabled = false
}
}
You can generate a report for your debug build by running the gradle task:
For gradle 6.x: ./gradlew spotbugsDebug
For gradle 5 or 4: ./gradlew spotbugsMain
It's important to use classes = files("$project.buildDir/intermediates/javac") , otherwise you'll get an error "java.io.IOException: No files to analyze could be opened" -- see Findbugs fails with "java.io.IOException: No files to analyze could be opened"
You'll also need to enable the HTML report and disable XML report, to see a human-readable format.
ignoreFailures = true is optional. When SpotBugs detects a code warning, by default it will end with "BUILD FAILED" + a report file. Setting ignoreFailures = true means the gradle task will end with "BUILD SUCCESSFUL" + a report file.
To exclude some generated classes from the analysis, setup an excludeFilter. For a sample exclude file, check here or here (same as findbugs-exclude.xml)
More information and tutorial here: https://mikedemaso.com/tech/2020-06-10-spotbugs-gradle-plugin-android/

Eclipse: Gluon mobile charm down VideoService - not found

I am following this page to create a test app with video playback.
Eclipse is ready and Gluon is installed.
An SingleView Gluon Project was created.
in the Gluon Mobile Settings i added Video; i checked if 'video' is also added in the build.gradle
so the file looks like:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.11'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.gluonapplication.GluonMultimediaApplication'
dependencies {
compile 'com.gluonhq:charm:5.0.0'
}
jfxmobile {
downConfig {
version = '3.8.0'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'display', 'lifecycle', 'statusbar', 'storage', 'video'
}
android {
manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
i also "copy and pasted" the BasicView from the link above over the default BasicView.
NOTE: i had to change the constructor, as the Viewconstructor does not accept an String...
ALL seems fine, but the VideoService does not get resolved:
NOTE: Project and External Dependencies of Eclipse shows a list of charm-down-plugins but NOT video
NOTE: gradle dependencies shows me the version of video service (3.6.0)
What am i missing?
UPDATE: gradle clean, gradle --refresh-dependencies does not have any affect (which seems crazy as gradle dependencies shows me that VIDEO is a dependency?!
RMB on Project -> Gradle -> Refresh Gradle Project

Generate Protobuf java files with Square's Wire

I'm trying to generate .java files from the .proto files I have stored under my SRC folder in Android studio. I put the below code in my gradle file by it doesn't seem to work
apply plugin: 'com.squareup.wire'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.squareup.wire:wire-maven-plugin:2.1.1'
}
}
There is a gradle plugin for wire here: https://github.com/square/wire-gradle-plugin. However, it seems like it's not quite ready for primetime yet. I had some trouble getting it working.
But, here's a way to do it that automates generation of java code from the *.proto files using the wire compiler directly and a simple gradle task. I've provided a snippet below with the modifications to your build.gradle. Change the protoPath and wireGeneratedPath based on your source layout.
def protoPath = 'src/proto'
def wireGeneratedPath = 'build/generated/source/wire'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.squareup.wire:wire-compiler:2.2.0'
}
}
android {
sourceSets {
main {
java {
include wireGeneratedPath
}
}
}
}
dependencies {
compile 'com.squareup.wire:wire-runtime:2.2.0'
// Leave this out if you're not doing integration testing...
androidTestCompile 'com.squareup.wire:wire-runtime:2.2.0'
}
// This handles the protocol buffer generation with wire
task generateWireClasses {
description = 'Generate Java classes from protocol buffer (.proto) schema files for use with squareup\'s wire library'
delete(wireGeneratedPath)
fileTree(dir: protoPath, include: '**/*.proto').each { File file ->
doLast {
javaexec {
main = 'com.squareup.wire.WireCompiler'
classpath = buildscript.configurations.classpath
args = ["--proto_path=${protoPath}", "--java_out=${wireGeneratedPath}", "${file}"]
}
}
}
}
preBuild.dependsOn generateWireClasses
So instead of using a gradle plugin I just ended up using the square wire compiler jar. Here are the steps.
Download compiler-jar-with-dependencies from http://search.maven.org/#artifactdetails%7Ccom.squareup.wire%7Cwire-compiler%7C2.1.1%7Cjar
Put jar file into root directory of android app
Go to the directory and paste this command
java -jar wire-compiler-2.1.1-jar-with-dependencies.jar --proto_path=directory-of-protofile --java_out=app/src/main/java/ name-of-file.proto
Should work. Make sure to replace the directory-of-protofile and name-of-file with whatever you have.

Gradle Artifactory Plugin - How to publish artifacts from multiple modules in a project?

I have a project which has a SharedCode (Java) module and secondly an Android (Android library) module which depends on the SharedCode module. I want to publish a jar artifact from the SharedCode module and an aar artifact from the Android module. I can't figure out how to compose my build.gradle files so that both modules publish to Artifactory when the artifactoryPublish task is run. At the moment only the SharedCode module publishes its artifact to Artifactory.
My build.gradle files are as below. Note that the maven-publish aspect of my build.gradle files appears to be correct because when I run the publishToMavenLocal task I see the artifacts from both modules in my local Maven folder (i.e. '~/.m2/repository').
Firstly, the build.gradle file in my SharedCode module is as follows:
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
group = "${projectGroupId}"
version = "${projectVersionName}"
dependencies {
compile 'com.google.guava:guava:18.0'
}
publishing {
publications {
SharedCode(MavenPublication) {
groupId "${projectGroupId}"
artifactId 'SharedCode'
version "${projectVersionName}"
from components.java
}
}
}
artifactory {
contextUrl = "${artifactory_url}"
publish {
repository {
repoKey = 'libs-release-local'
username = "${artifactory_username}"
password = "${artifactory_password}"
}
defaults {
publications('SharedCode')
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team': 'core']
publishPom = true
}
}
}
Secondly, the build.gradle file in my Android module is as follows:
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
group = "${projectGroupId}"
version = "${projectVersionName}"
android {
// android stuff here...
}
dependencies {
compile project(':SharedCode')
}
publishing {
publications {
Android(MavenPublication) {
groupId "${projectGroupId}"
artifactId 'Android'
version "${projectVersionName}"
artifact "$buildDir/outputs/aar/Android-release.aar"
}
}
}
artifactory {
contextUrl = "${artifactory_url}"
publish {
repository {
repoKey = 'libs-release-local'
username = "${artifactory_username}"
password = "${artifactory_password}"
}
defaults {
publications('Android')
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team': 'core']
publishPom = true
}
}
}
If I run the artifactoryPublish task at the root, project level or at the SharedCode module level then I see output as follows:
18:23:38: Executing external task 'artifactoryPublish'...
Publication named 'SharedCode' does not exist for project ':Android' in task ':Android:artifactoryPublish'.
:SharedCode:generatePomFileForSharedCodePublication
:SharedCode:artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/libs-release-local/com/mycompany/sdk/SharedCode/0.0.2/SharedCode-0.0.2.jar
Deploying artifact: http://localhost:8081/artifactory/libs-release-local/com/mycompany/sdk/SharedCode/0.0.2/SharedCode-0.0.2.pom
Deploying build descriptor to: http://localhost:8081/artifactory/api/build Build successfully deployed.
Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/client-sdk/1457375019604
BUILD SUCCESSFUL
Note that only the SharedCode artifact is published in this case.
If I run the artifactoryPublish task at the Android module level, then I see output as follows:
18:25:25: Executing external task 'artifactoryPublish'...
Publication named 'SharedCode' does not exist for project ':Android' in task ':Android:artifactoryPublish'.
:Android:artifactoryPublish
Deploying build descriptor to: http://localhost:8081/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/client-sdk/1457375127269
BUILD SUCCESSFUL
Note that no artifacts are published in this case.
Update: As of version 4.6.0 of the com.jfrog.artifactory Gradle plugin, publishing artifacts in a multi-module project just does not work. From personal experience, you're best just abandoning this plugin and using the standard maven-publish plugin for both Java library modules and Android library modules.
--- What follows below is my original answer before I posted the above update ---
So I've finally got this all working! Special thanks to #RaGe for helping me along the way. The key points to note are that the artifactory block needs to be in the project's root-level build.gradle file and not in the build.gradle file of the individual modules. Also, you need to add artifactoryPublish.skip=true to the project's root-level build.gradle file. See this GitHub repo for a full-on yet minimal-as-possible example:
https://github.com/adil-hussain-84/SO-35851251-Multiproject-Artifactory-Publish
In case the link ever stops working I'll paste the contents of the build.gradle files here also. Firstly, the project's root-level build.gradle file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.0.1'
}
}
allprojects {
apply plugin: 'com.jfrog.artifactory'
repositories {
jcenter()
}
group = "${projectGroupName}"
version = "${projectVersionName}"
}
artifactoryPublish.skip=true
artifactory {
contextUrl = "${artifactory_url}"
publish {
repository {
repoKey = 'libs-release-local'
username = "${artifactory_username}"
password = "${artifactory_password}"
}
defaults {
publications('SomePublication')
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team': 'core']
publishPom = true
}
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.8'
}
Secondly, the build.gradle file of the Android module:
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 23
versionCode Integer.parseInt("${projectVersionCode}")
versionName "${projectVersionName}"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile project(':SharedCode')
compile 'com.android.support:appcompat-v7:23.2.1'
testCompile 'junit:junit:4.12'
}
publishing {
publications {
SomePublication(MavenPublication) {
artifact "$buildDir/outputs/aar/Android-release.aar"
//The publication doesn't know about our dependencies, so we have to manually add them to the pom
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
//Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
configurations.compile.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
Thirdly and finally, the build.gradle file of the SharedCode (Java) module:
apply plugin: 'java'
apply plugin: 'maven-publish'
dependencies {
compile 'com.google.guava:guava:18.0'
}
publishing {
publications {
SomePublication(MavenPublication) {
from components.java
}
}
}
That's it!
Going by artifactory multi-project examples on their github repo, it would seem that only the root project needs to have an artifactory{...} configuration section as opposed to in every sub-project as you have done.
Moreover when you declare publications('SharedCode') in the root project, artifactory plugin seems to be looking for a publication called sharedCode in every subproject.
I would try:
Remove the artifactory{...} section from the android build.gradle
Rename the android publication to sharedCode as well (or something more generic in both projects)
Version 4.2.0 of the Gradle Artifactory Plugin was released last week and added multiple Artifactory repositories deployment. Now you can simply define an artifactory closure with a different repository for different modules of the project.

Gradle - build sass per productflavor (multi folder)

We created an Android app with a webview which shows a local website from the assets folder.
The project has different Product Flavors to generate diffent apps with different styles and content but with the same codebas (native Java and HTML / JS).
For each flavor we want to define a diffent sass file with the colors and tweaks for that specific flavour.
I know that I need to create a task in gradle which builds the CSS files but I have no idea where to start:
How do I get the url of the assets folder of a specific flavour?
Can I use a special gradle plugin for building sass or do I have to create a task which executes the "sass" command?
When I use another gradle plugin like compass, how do I configure the right folders for each flavour? The plugin settings are in the top level and not in the Android plugin level.
I finaly have the solution!
Add this to your build.gradle in the main folder (not of your app):
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url 'http://dl.bintray.com/robfletcher/gradle-plugins' }
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.github.robfletcher:compass-gradle-plugin:2.0.6'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
Add this the build.gradle of the app module:
apply plugin: 'com.android.application'
apply plugin: 'com.github.robfletcher.compass'
android {
[..]
android.applicationVariants.all { variant ->
for (output in variant.outputs) {
def assetsDir = output.packageApplication.assets;
tasks["merge${variant.name.capitalize()}Assets"].doLast() {
println "Assets folder: " + assetsDir
def _ccsDir = file("$assetsDir/css")
def _sassDir = file("$assetsDir/sass")
def _imagesDir = file("$assetsDir/images")
def _javascriptsDir = file("$assetsDir/js")
def _fontsDir = file("$assetsDir/fonts")
project.compass {
cssDir = _ccsDir
sassDir = _sassDir
imagesDir = _imagesDir
javascriptsDir = _javascriptsDir
fontsDir = _fontsDir
}
//compileSass
project.compassCompile.execute()
}
}
}
}
I never thought it would work out but it works!

Categories

Resources