Is there any way to integrate ads such as Google's Admob library into gluon mobile on either android or iOS or hopefully both?
This is the gradle file, I have downloaded the Google Play Services library and the google Repository :
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.2.0'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'graphing.calculator.Calculator'
dependencies {
compile 'com.gluonhq:charm:4.3.0'
androidCompile 'com.google.android.gms:play-services-ads:9.4.0'
}
jfxmobile {
downConfig {
version = '3.2.0'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
manifest = 'src/android/AndroidManifest.xml'
androidSdk = '/Users/aniket/Library/Android/sdk'
}
ios {
arch = "arm64"
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
project.afterEvaluate {
explodeAarDependencies(project.configurations.androidCompile)
}
Yes, there is a way, for both Android and iOS.
This answer already contains a snippet of how it could be done on Android. But I'll update it here using and extending the Charm Down library. I won't include the iOS solution, though, as it requires modifications in the jfxmobile plugin, as I'll explain later.
Create a new project with the Gluon plugin, and modify the following. You'll have to keep the package names I mention, but you can name your project (and package) as you want.
build.gradle script
You need to include the Google Play Services library:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.4'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.gluonhq.adview.GluonAdView' // this can be changed
dependencies {
compile 'com.gluonhq:charm:4.3.2'
androidCompile 'com.google.android.gms:play-services-ads:9.4.0'
}
jfxmobile {
downConfig {
version '3.2.4'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
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.**.*'
]
}
}
project.afterEvaluate {
explodeAarDependencies(project.configurations.androidCompile)
}
Note the last task: it explodes the aar files on the android/google local repositories, to extract the jars (in this case the Google Play Services jar and all its dependencies).
Note also that after modifying the build file, you need to reload the project (to sync the project and manage the new dependencies).
Source Packages/Java
Besides the project files, you need to add this package: com.gluonhq.charm.down.plugins, and these classes:
AdViewService interface
public interface AdViewService {
void setAdUnit(String unitId, String testDeviceId, boolean test);
}
AdViewServiceFactory class
public class AdViewServiceFactory extends DefaultServiceFactory<AdViewService> {
public AdViewServiceFactory() {
super(AdViewService.class);
}
}
Android/Java Packages
In the Android/Java package, add this package: com.gluonhq.charm.down.plugins.android, and this class:
AndroidAdViewService class
import android.view.Gravity;
import android.widget.LinearLayout;
import com.gluonhq.charm.down.Services;
import com.gluonhq.charm.down.plugins.LifecycleEvent;
import com.gluonhq.charm.down.plugins.LifecycleService;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import javafxports.android.FXActivity;
import com.gluonhq.charm.down.plugins.AdViewService;
public class AndroidAdViewService implements AdViewService {
private AdView adView;
#Override
public void setAdUnit(String unitId, String testDeviceId, boolean test) {
FXActivity.getInstance().runOnUiThread(() -> {
LinearLayout layout = new LinearLayout(FXActivity.getInstance());
layout.setVerticalGravity(Gravity.BOTTOM);
layout.setOrientation(LinearLayout.VERTICAL);
adView = new AdView(FXActivity.getInstance());
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId(unitId);
AdRequest adRequest;
if (test) {
adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR) // All emulators
.addTestDevice(testDeviceId) // from logcat!
.build();
} else {
adRequest = new AdRequest.Builder().build();
}
adView.loadAd(adRequest);
adView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
}
});
layout.addView(adView);
FXActivity.getViewGroup().addView(layout);
});
Services.get(LifecycleService.class).ifPresent(service -> {
service.addListener(LifecycleEvent.RESUME, () -> FXActivity.getInstance().runOnUiThread(() -> adView.resume()));
service.addListener(LifecycleEvent.PAUSE, () -> FXActivity.getInstance().runOnUiThread(() -> adView.pause()));
});
}
}
It makes use of com.google.android.gms.ads.AdView. If your Android dependencies already include Google Play Services, you won't have any problem with the imports. Otherwise, go back to step 1.
Note that I'm setting a layout where the banner will go to the bottom of the screen. Change this at your convenience.
AndroidManifest.xml
You need to add this to the manifest:
<?xml version="1.0" encoding="UTF-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application ...>
<activity .../>
<meta-data android:name="com.google.android.gms.version" android:value="9452000" />
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent"/>
</application>
</manifest>
Note the Google Play Services value corresponds with the 9.4.0 version.
Sample
Now you can add the service to your project. For that you'll need an Ad unit Id. You can create an account on Google AdMob to add your app, and get the App ID for the banner unit.
To get the test device id, you'll have to run the app first, and find in the console the id with adb logcat.
public BasicView(String name) {
super(name);
Services.get(AdViewService.class).ifPresent(ads -> {
ads.setAdUnit("ca-app-pub-17652XXXXXXXXXX/83XXXXXXXX", "0283A9A0758XXXXXXXXXXXXXXXX", true);
});
Label label = new Label("Hello JavaFX World!");
...
}
Run the sample on your Android device
You should see the ads at the bottom, and some logs at the console as well.
04-02 12:42:45.352 25520 25520 I Ads : Starting ad request.
04-02 12:42:47.844 25520 25520 I Ads : Scheduling ad refresh 60000 milliseconds from now.
04-02 12:42:47.889 25520 25520 I Ads : Ad finished loading.
iOS
For iOS it is possible as well. The problem is that it requires downloading the Google Mobile Ads SDK, and adding the GoogleMobileAds.framework to the list of frameworks, so when compiling the native code it finds it.
This should be done in the jfxmobile-plugin, so it is out of scope in this question for now.
Related
I have published maven bom and imported it in top level build.gradle.kts as:
allProjects {
dependencies {
implementation(platform("com.example:some-dependencies:1.2.3"))
}
}
And then in libs.versions.toml:
[libraries]
some-bom = { group = "com.example", name="some-dependencies", version="1.2.3" }
When I change first code sample to:
allProjects {
dependencies {
implementation(platform(libs.some.bom))
}
}
I get:
Could not resolve: javax.xml.bind:jaxb-api
Could not resolve: org.springframework.boot:spring-boot-starter-test
...
Is there any way to use Gradle 7 version catalogs with boms?
In my case, it just worked. I'm working on Android project and my script is just like below:
//libs.versions.toml
[libraries]
deps_okhttp_bom = "com.squareup.okhttp3:okhttp-bom:4.9.1"
deps_okhttp_lib = { module ="com.squareup.okhttp3:okhttp" }
deps_okhttp_logging_interceptor = { module= "com.squareup.okhttp3:logging-interceptor"}
//build.xml
dependencies {
implementation platform(libs.deps.okhttp.bom)
implementation libs.deps.okhttp.lib
implementation libs.deps.okhttp.logging.interceptor
}
In your example, you just added dependency for BOM. But as BOM is just an spec sheet which describes versions for each libraries, you need to add dependencies for specific libraries.
I was in the middle of coding an app using VS Code and react-native and after trying to install react-native-material-ripple I ran into the following error trying to build my app:
///////////////////////////////////////////////////////////////////////////////////////////////
FAILURE: Build failed with an exception.
Where:
Build file 'C:\Users\D'errah\Documents\Code\React\dowProjectMatcher\node_modules\react-native-reanimated\android\build.gradle' line: 89
What went wrong:
A problem occurred configuring project ':react-native-reanimated'.
java.io.IOException: The filename, directory name, or volume label syntax is incorrect
//////////////////////////////////////////////////////////////////////////////////////////////
The app was working perfectly before then. I went to the file in question and looked at the line the error mentioned:
mentioned line:
classpath += files(android.bootClasspath)
full file:
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
buildscript {
if (project == rootProject) {
// The Android Gradle plugin is only required when opening the android folder stand-alone.
// This avoids unnecessary downloads and potential conflicts when the library is included as a
// module dependency in an application project.
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
}
}
}
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
compileSdkVersion safeExtGet('compileSdkVersion', 28)
buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 16)
targetSdkVersion safeExtGet('targetSdkVersion', 28)
versionCode 1
versionName "1.0"
}
lintOptions {
abortOnError false
}
}
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
maven {
// Android JSC is installed from npm
url "$rootDir/../node_modules/jsc-android/dist"
}
google()
jcenter()
}
dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation "androidx.transition:transition:1.1.0"
}
def configureReactNativePom(def pom) {
def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text)
pom.project {
name packageJson.title
artifactId packageJson.name
version = packageJson.version
group = "com.swmansion.reanimated"
description packageJson.description
url packageJson.repository.baseUrl
licenses {
license {
name packageJson.license
url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename
distribution 'repo'
}
}
developers {
developer {
id packageJson.author.username
name packageJson.author.name
}
}
}
}
afterEvaluate { project ->
task androidJavadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += files(android.bootClasspath)
classpath += files(project.getConfigurations().getByName('compile').asList())
include '**/*.java'
}
task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
classifier = 'javadoc'
from androidJavadoc.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
include '**/*.java'
}
android.libraryVariants.all { variant ->
def compileTask
if (variant.hasProperty('javaCompileProvider')){
compileTask = variant.javaCompileProvider.get()
}else{
compileTask = variant.javaCompile
}
def name = variant.name.capitalize()
task "jar${name}"(type: Jar, dependsOn: compileTask) {
from compileTask.destinationDir
}
}
artifacts {
archives androidSourcesJar
archives androidJavadocJar
}
task installArchives(type: Upload) {
configuration = configurations.archives
repositories.mavenDeployer {
// Deploy to react-native-event-bridge/maven, ready to publish to npm
repository url: "file://${projectDir}/../android/maven"
configureReactNativePom pom
}
}
}
The problem is, I'm pretty sure that how that line was already even while the app was working. So I've spent the last few hours googling and haven't been able to figure out what cause the issue/how to fix it.
Any help would be GREATLY appreciated!
Things to note:
-using VS Code
-Was working before installing react-native-material-ripple (tried uninstalling, test, reinstalling, test)
Same error occurred for me also, please go through this documentation for proper installation setup for react-native-reanimate.
Install latest
yarn add react-native-reanimated#next
or
npm i react-native-reanimated#next
now go to android dir and gradlew clean, for more details go through below link
https://docs.swmansion.com/react-native-reanimated/docs/installation
There are few Kotlin Extensions that come along with org.gradle.kotlin.dsl like
android or publishing etc. Say, for publishing, the extension is defined as below
fun org.gradle.api.Project.`publishing`(configure: org.gradle.api.publish.PublishingExtension.() -> Unit): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("publishing", configure)
That means within mybuild.gradle.kts I can call
publishing {
// blablabla
}
In my case, I have a separate file that handles publishing defined as random.gradle.kts and is located at totally random directory.
Here, I want to access this publishing extension but not able to do it.
Any suggestions are welcomed.
To give another example android is also not accessible.
In my build.gradle.kts I can access android but in my random.gradle.kts I am not able to do it.
android extension is defined as below
val org.gradle.api.Project.`android`: com.android.build.gradle.LibraryExtension get() =
(this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("android") as com.android.build.gradle.LibraryExtension
In fact, LibraryExtension is also not accessible.
So, how to pass or import those extensions to my random.gradle.kts?
//build.gradle.kts tested with gradle 6.7
subprojects {
afterEvaluate {
(extensions.findByType(com.android.build.gradle.LibraryExtension::class)
?: extensions.findByType(com.android.build.gradle.AppExtension::class))?.apply {
println("Found android subproject $name")
lintOptions.isAbortOnError = false
compileSdkVersion(30)
if (this is com.android.build.gradle.AppExtension)
println("$name is an application")
if (this is com.android.build.gradle.LibraryExtension) {
val publishing =
extensions.findByType(PublishingExtension::class.java) ?: return#afterEvaluate
val sourcesJar by tasks.registering(Jar::class) {
archiveClassifier.set("sources")
from(sourceSets.getByName("main").java.srcDirs)
}
afterEvaluate {
publishing.apply {
val projectName = name
publications {
val release by registering(MavenPublication::class) {
components.forEach {
println("Publication component: ${it.name}")
}
from(components["release"])
artifact(sourcesJar.get())
artifactId = projectName
groupId = ProjectVersions.GROUP_ID
version = ProjectVersions.VERSION_NAME
}
}
}
}
}
}
}
}
I started a new project with kotlin-multiplatform to create a library usable on iOS and Android using this tutorial :
https://play.kotlinlang.org/hands-on/Targeting%20iOS%20and%20Android%20with%20Kotlin%20Multiplatform/01_Introduction
It seems to work fine but I wanted to add the Serialization library mentioned at the end of the tutorial (https://github.com/Kotlin/kotlinx.serialization) and I can't make it work.
The setup guide in the library is not in Kotlin DSL so I tried different things to adapt the code but without success. Here is my project gradle :
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
And now my build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework {
baseName = "SharedCode"
}
}
}
jvm("android")
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:0.13.0")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.13.0")
}
sourceSets["iosMain"].dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:0.13.0")
}
}
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
/// generate a helpful ./gradlew wrapper with embedded Java path
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\n"
+ "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
+ "cd '${rootProject.rootDir}'\n"
+ "./gradlew \$#\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
I have no errors but I cannot use the library in my code.
Can someone please explain how to integrate this dependency or any dependency with this setup ? What do I do wrong ?
Note : I'm using Android Studio 3.5.1, Gradle 5.4.1, Kotlin 1.3.50.
Ok, so I found the issue.. just the version of the library.. 0.13.0 not 0.14.0. No error is thrown when you sync a wrong library version. I hope this post helps someone anyway.
I have microservices that will share some of the same configuration between all of them, mainly Jib, publish, and release. Not sure if it's possible to do the same for dependencies but it would be beneficial to include actuator and log4j2 in each. Here is the build.gradle.kts for one of my projects.
import net.researchgate.release.BaseScmAdapter
import net.researchgate.release.GitAdapter
import net.researchgate.release.ReleaseExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("com.gorylenko.gradle-git-properties") version "1.5.1"
id("com.google.cloud.tools.jib") version "1.6.1"
id("io.spring.dependency-management") version "1.0.7.RELEASE"
id("net.researchgate.release") version "2.8.1"
id("org.sonarqube") version "2.7.1"
id("org.springframework.boot") version "2.1.6.RELEASE"
kotlin("jvm") version "1.2.71"
kotlin("plugin.spring") version "1.2.71"
jacoco
`maven-publish`
}
java.sourceCompatibility = JavaVersion.VERSION_1_8
springBoot {
buildInfo {
group = project.properties["group"].toString()
version = project.properties["version"].toString()
description = project.properties["description"].toString()
}
}
repositories {
maven(url = uri(project.properties["nexus.url.gateway"].toString()))
mavenCentral()
}
dependencies {
// Kotlin
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// Spring
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-log4j2")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.cloud:spring-cloud-config-server")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:Greenwich.SR3")
}
}
configurations.all {
exclude(group = "ch.qos.logback", module = "logback-classic")
exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
build { dependsOn(clean) }
afterReleaseBuild { dependsOn(publish) }
publish { dependsOn(build) }
jibDockerBuild { dependsOn(build) }
jacocoTestReport {
reports {
html.isEnabled = false
xml.isEnabled = true
}
}
}
publishing {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
pom {
scm {
connection.set("scm:git:git#github.com:company/${project.name}.git")
developerConnection.set("scm:git:git#github.com:company/${project.name}.git")
url.set("https://github.com/company/${project.name}/")
}
}
versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}
}
}
repositories {
maven {
val releasesRepoUrl = "${project.properties["nexus.url.publish"].toString()}/releases"
val snapshotsRepoUrl = "${project.properties["nexus.url.publish"].toString()}/snapshots"
url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
credentials {
username = project.properties["nexus.user"].toString()
password = project.properties["nexus.password"].toString()
}
}
}
}
fun ReleaseExtension.git(configureFn : GitAdapter.GitConfig.() -> Unit) {
(propertyMissing("git") as GitAdapter.GitConfig).configureFn()
}
release {
scmAdapters = mutableListOf<Class<out BaseScmAdapter>> ( GitAdapter::class.java )
git {
requireBranch = "develop"
pushToRemote = project.properties["release.git.remote"].toString()
pushReleaseVersionBranch = "master"
tagTemplate = "${project.name}.${project.version}"
}
}
jib {
from {
image = "openjdk:8-jdk-alpine"
}
to {
image = "host:port/${project.name}:${project.version}"
auth {
username = project.properties["nexus.user"].toString()
password = project.properties["nexus.password"].toString()
}
}
container {
workingDirectory = "/"
ports = listOf("8080")
environment = mapOf(
"SPRING_OUTPUT_ANSI_ENABLED" to "ALWAYS",
"SPRING_CLOUD_BOOTSTRAP_LOCATION" to "/path/to/bootstrap.yml"
)
useCurrentTimestamp = true
}
setAllowInsecureRegistries(true)
}
I was able to get a custom plugin created and added to this project using git#github.com:klg71/kotlintestplugin.git and git#github.com:klg71/kotlintestpluginproject.git but I have no idea how to implement these existing plugins and their configurations. In the main Plugin class in the apply function I am able to call the project.pluginManager.apply(PublishingPlugin::class.java) which causes the task to show in the project referencing the custom plugin but I can't figure out how to configure it and it does not successfully publish to the nexus server. I can publish the plugin itself to the nexus server and reference it in the microservice but it skips running the task, which I assume is caused by the configuration not being included. Also, when trying to apply/configure the Jib plugin, all of the classes are not visible when attempting to import.
So the above answer isn't super long and to preserve the issues I ran into I am posting a new answer.
PLUGIN
This portion of the answer is going to discuss the actual custom plugin project.
Because the plugins wrapper in the build.gradle.kts is runtime, the CustomPlugin.kt does not have access to it at compile time. My boss who is much smarter than me was kind enough to point this out to me even though he has never worked with gradle. Although I looked pretty dumb in front of him he still got me up and running by basically following the 'legacy' way of applying plugins in gradle.
plugins { // This is a runtime script preventing plugins declared here to be accessible in CustomPlugin.kt but is used to actually publish/release this plugin itself
id("net.researchgate.release") version "2.8.1"
kotlin("jvm") version "1.3.0"
`maven-publish`
}
repositories {
maven { url = uri("https://plugins.gradle.org/m2/") } // This is required to be able to import plugins below in the dependencies
jcenter()
}
dependencies {
compile(kotlin("stdlib"))
compile(kotlin("reflect"))
// These must be declared here (at compile-time) in order to access in CustomPlugin.kt
compile(group = "gradle.plugin.com.gorylenko.gradle-git-properties", name = "gradle-git-properties", version = "2.2.0")
compile(group = "gradle.plugin.com.google.cloud.tools", name = "jib-gradle-plugin", version = "1.7.0")
compile(group = "net.researchgate", name = "gradle-release", version = "2.8.1")
compile(group = "org.asciidoctor", name = "asciidoctor-gradle-plugin", version = "1.5.9.2")
compile(group = "org.jetbrains.dokka", name = "dokka-gradle-plugin", version = "0.9.18")
compile(group = "org.sonarsource.scanner.gradle", name = "sonarqube-gradle-plugin", version = "2.8")
implementation(gradleApi()) // This exposes the gradle API to CustomPlugin.kt
}
This allowed me to have access to jib and everything else in the CustomPlugin.kt.
The plugins jacoco and maven-publish are automatically accessible in the plugin project but still need to be added in the microservice project referencing the plugin. I was unable to find a workaround for this unfortunately.
I included the typical maven-publish plugin in the build.gradle.kts to push to nexus with the publishing task configurations in the build.gradle.kts as well so I could pull this from nexus in the microservice that wanted to use the plugin.
publishing {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
pom {
scm {
connection.set("scm:git:git#github.com:diendanyoi54/${project.name}.git")
developerConnection .set("scm:git:git#github.com:diendanyoi54/${project.name}.git")
url.set("https://github.com/diendanyoi54/${project.name}/")
}
}
}
}
repositories {
maven {
val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
url = uri(if (version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
credentials {
username = project.properties["nexus.user"].toString()
password = project.properties["nexus.password"].toString()
}
}
}
}
Lastly, you want to make sure you include the properties file that will tell the microservices where the plugin class is. In Intellij's IDEA, when typing the path to the implementation-class it auto completed for me.
The name of this file should reflect apply(plugin = "string") in the microservice's build.gradle.kts.
IMPLEMENTATION
This portion of the answer is going to reflect the microservice project that will be referencing the plugin. As stated above, jacoco and maven-publish still need to be added to the plugin block in the build.gradle.kts for some reason (I think because they are official gradle plugins).
To reference the plugin from the nexus server it was published to, the microservice must reference it in the buildscript.
buildscript { // Custom plugin must be accessed by this buildscript
repositories {
maven {
url = uri("https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository/maven-public")
credentials {
username = project.properties["nexus.user"].toString()
password = project.properties["nexus.password"].toString()
}
}
}
dependencies { classpath("com.company:kotlin-consolidated-plugin:1.0.0-SNAPSHOT") }
}
Lastly, the plugin must be applied using the properties file name referenced above.
apply(plugin = "com.company.kotlinconsolidatedplugin") // Custom plugin cannot reside in plugin declaration above
I created sample projects of these and posted them to Github so feel free to clone or take a look:
git#github.com:diendanyoi54/kotlin-consolidated-plugin.git
git#github.com:diendanyoi54/kotlin-consolidated-plugin-implementation.git
I was able to successfully able to use the github repo examples referenced above to accomplish what I needed with the publish task. Here is my custom plugin's build.gradle.kts.
plugins {
id("com.google.cloud.tools.jib") version "1.6.1"
id("org.sonarqube") version "2.7.1"
kotlin("jvm") version "1.3.0"
`maven-publish`
}
dependencies {
compile(kotlin("stdlib"))
compile(kotlin("reflect"))
implementation(gradleApi())
}
repositories {
jcenter()
}
publishing {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
pom {
scm {
connection.set("scm:git:git#github.com:company/${project.name}.git")
developerConnection.set("scm:git:git#github.com:company/${project.name}.git")
url.set("https://github.com/company/${project.name}/")
}
}
}
}
repositories {
maven {
val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
url = uri(if (version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
credentials {
username = project.properties["nexus.user"].toString()
password = project.properties["nexus.password"].toString()
}
}
}
}
Here is the CustomPlugin.kt class.
package com.company.gradlemicroserviceplugin
//import com.google.cloud.tools.jib.gradle.JibExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.plugins.PublishingPlugin
import org.gradle.testing.jacoco.tasks.JacocoReport
import java.net.URI
open class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
// applySonar(project)
applyPublish(project)
// applyJib(project)
}
// private fun applySonar(project: Project) {
// project.pluginManager.apply("sonarqube")
// val task = project.task("jacocoTestReport") as JacocoReport
// task.reports = JacocoReport()
// jacocoTestReport { This was nested in the tasks declaration in build.gradle.kts so the fields below are the fields I'm trying to set in task.reports
// reports {
// html.isEnabled = false
// xml.isEnabled = true
// }
// }
// }
private fun applyPublish(project: Project) {
project.pluginManager.apply(PublishingPlugin::class.java)
val publishingExtension = project.extensions.findByType(PublishingExtension::class.java)
val mavenPublication = publishingExtension?.publications?.create(project.name, MavenPublication::class.java)
publishingExtension?.repositories?.maven {
val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
it.url = URI(if (project.version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
it.credentials { cred ->
cred.username = project.properties["nexus.user"].toString()
cred.password = project.properties["nexus.password"].toString()
}
}
mavenPublication?.from(project.components.findByName("java"))
mavenPublication?.pom?.scm {
it.connection.set("scm:git:git#github.com:company/${project.name}.git")
it.developerConnection.set("scm:git:git#github.com:company/${project.name}.git")
it.url.set("https://github.com/company/${project.name}/")
}
}
// private fun applyJib(project: Project) {
// project.pluginManager.apply(JibPlugin::class.java)
//
// }
}
There are definitely areas of improvement on this but at least I got something working here. There is maven-publish logic in both build.gradle.kts because I push to the custom plugin to nexus and the maven-publish logic is in the CustomPlugin.kt class so the microservice that references this plugin can use it. However, I am unable to successfully setup Jib and Sonar. Jib doesn't give me access to anything in com.google.cloud.tools.jib.gradle preventing me from using the same approach as I used in maven-publish.
For Sonar I think I'm on the right track with retrieving the task by its name but I'm unable to set any fields that belong to task.reports because they are all final and this is necessary for Sonar to properly analyze Kotlin.
Applying built-in plugins
plugins {
java
id("jacoco")
}
You can also use the older apply syntax:
apply(plugin = "checkstyle")
Applying external plugins
plugins {
id("org.springframework.boot") version "2.0.1.RELEASE"
}
i am not good in kotlin but here is link to better understanding missing migration guide to the Gradle Kotlin DSL