insert plugin into Android gradle build using init.gradle - android

F-Droid is a free software app store for Android. We enforce that apps are 100% free software, so its something like Debian for Android. Since most Android apps use gradle, it makes sense to use gradle tricks to automate our enforcement. The 'com.jaredsburrows.license' plugin is one kind of thing we'd like to automatically inject into every build. init.gradle should be able to do this, but I can't quite figure out how to insert the plugin into the Android plugin. Here's where I got:
apply plugin: FDroidLicenseCheck
class FDroidLicenseCheck implements Plugin<Gradle> {
def supportedPlugins = [
'org.gradle.api.plugins.JavaPlugin',
'com.android.build.gradle.AppPlugin'
]
void apply(Gradle gradle) {
println('applying license check')
def added = false
gradle.allprojects { project ->
project.with {
if (parent == null) {
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.jaredsburrows:gradle-license-plugin:0.5.0"
}
}
}
plugins.whenPluginAdded { plugin ->
println('Checking ' + plugin.class.name)
if (!added && supportedPlugins.contains(plugin.class.name)) {
println('Adding to ' + plugin.class.name)
rootProject.apply plugin: 'com.jaredsburrows.license'
added = true
}
}
}
}
}
}

Related

Setting up Protobuf + Kotlin in Android Studio 2023

I spend hours on just setting up Protobuf with Kotlin in Android Studio. The endgoal is just that my proto files are compiled in Kotlin and that I can use them in my project.
I have an example project here: https://github.com/Jasperav/ProtobufAndroid. It mimics my setup in the real application: an external dir containing the proto files and the android project. It contains all the code mentioned below. This is a combined effort of tutorials I found on the internet. It is probably terrible wrong. I tried https://github.com/google/protobuf-gradle-plugin, but it just looks so complicated for something simple I am doing:
Have a dir with protofiles somewhere on your filesystem
Create a new Android project on Kotlin
In the Project build.gradle, add id 'com.google.protobuf' version '0.9.2' apply false as plugin
In the Module build.gradle, add ->
This to the dependencies: implementation 'com.google.protobuf:protobuf-lite:3.21.12'
The sourceSets at the bottom inside the android bracket
The protobuf section at the bottom between the dependencies and android section.
sourceSets:
sourceSets {
main {
kotlin {
srcDirs += 'build/generated/source/proto/main/kotlin'
}
proto {
srcDir '/Users/me/androidkotlin/proto'
}
}
}
protobuf:
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.21.12'
}
plugins {
kotlinlite {
artifact = 'com.google.protobuf:protoc-gen-kotlin:3.21.12'
}
}
generateProtoTasks {
ofSourceSet("main").forEach { task ->
task.builtins {
getByName("kotlin") {
option("lite")
}
}
}
}
}
I get this error:
A problem occurred evaluating project ':app'.
> Could not find method proto() for arguments [build_cxwfo79b6zcc266x9rsqzou9f$_run_closure1$_closure8$_closure10$_closure12#203aac02] on source set main of type com.android.build.gradle.internal.api.DefaultAndroidSourceSet.
You are in a good way, but, there is some stuff missing:
The gradle code I'll share is written in Kotlin, just in case. If you can convert your grade files to Kotlin, nice, if not you have to convert them to groovy.
The first thing to check is if you have the proto folder in the right path, it should be in
root->app->src->main->proto
In the project gradle make sure to have the plugin applied
id("com.google.protobuf") version "0.8.15" apply false
In the app gradle, make sure to have the following.
import com.google.protobuf.gradle.*
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.protobuf")
}
The dependencies:
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
implementation("com.google.protobuf:protobuf-kotlin:3.21.2")
implementation("io.grpc:grpc-stub:1.52.0")
implementation("io.grpc:grpc-protobuf:1.52.0")
implementation("io.grpc:grpc-okhttp:1.52.0")
implementation("com.google.protobuf:protobuf-java-util:3.21.7")
implementation("com.google.protobuf:protobuf-kotlin:3.21.2")
implementation("io.grpc:grpc-kotlin-stub:1.3.0")
And the protobuf task:
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}"
}
plugins {
id("java") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:${rootProject.ext["grpcKotlinVersion"]}:jdk8#jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
id("java") {
option("lite")
}
id("grpc") {
option("lite")
}
id("grpckt") {
option("lite")
}
}
it.builtins {
id("kotlin") {
option("lite")
}
}
}
}
}
These are the versions I'm using:
ext["grpcVersion"] = "1.47.0"
ext["grpcKotlinVersion"] = "1.3.0" // CURRENT_GRPC_KOTLIN_VERSION
ext["protobufVersion"] = "3.21.2"
ext["coroutinesVersion"] = "1.6.2"
Having that your project should generate the code based on your proto files.
For further reference, I recently build this Android App based on Kotlin + gRPC: https://github.com/wilsoncastiblanco/notes-grpc

Could not resolve git repository as dependency in android gradle

I am trying to add a git repository (https://github.com/FHNW-IP5-IP6/ComposeForms) as a dependency into my project with Gradle and tried the below-listed variants (1.-3.) from Is it possible to declare git repository as dependency in android gradle? but every time when I sync the project I get an Error saying: "Could not resolve com.github.FHNW-IP5-IP6:ComposeForms:master-SNAPSHOT".
I tried the following:
Jitpack (https://jitpack.io/#FHNW-IP5-IP6/ComposeForms/master-SNAPSHOT)
allprojects {
repositories {
...
maven("https://jitpack.io") // also tried uri https://www.jitpack.io
}
}
and in app build.gradle
kotlin {
sourceSets {
named("main") {
dependencies {
...
implementation("com.github.FHNW-IP5-IP6:ComposeForms:master-SNAPSHOT")
}
}
}
}
Git Submodule (named as compose-forms)
include(":compose-forms") inside settings.gradle
kotlin {
sourceSets {
named("main") {
dependencies {
...
implementation(project(":compose-forms"))
}
}
}
}
New feature in gradle
Inside settings.gradle
sourceControl {
gitRepository(uri("https://github.com/FHNW-IP5-IP6/ComposeForms.git")) {
producesModule("compose-forms")
}
}
and in app build.gradle
kotlin {
sourceSets {
named("main") {
dependencies {
...
implementation("compose-forms") {
version {
branch = "master"
}
}
}
}
}
}
I'm running out of options and really need the git repository as a dependency. I would prefer not to have any git submodules inside my project so I prefer numbers 1 and 3 to work. Thanks in Advance for any hint :)
Open Android Studio as Administrator then add maven { url 'https://jitpack.io' } to both, build.gradle(project) and settings.gradle(project) and the respective implementation [...] to build.gradle(:app). This worked for me as every other solution proposed failed.

How to filter submodules in gradle to apply appropriate plugin?

I have a multi-module project of which some are Java libraries and others Android libraries. I wanted to apply custom plugins for my sub projects (modules) depending on the project type, so I have done something like this (see below code snippet) in my project root's build.gradle file. This setup is working but I'm wondering if there is any other way of doing it. Gradle suggests Filtering by properties but I get the error Cannot add task 'integTest' as a task with that name already exists if I try that. The integTest is a task I created in customJavaBuild.gradle and customAndroidBuild.gradle files. Any help is appreciated. Thanks!
def javaLibraries = ["projA", "projB"]
def androidLibraries = ["projC"]
subprojects {
if (javaLibraries.contains(it.name)) {
apply from: '$rootDir/gradle/customJavaBuild.gradle'
} else if (androidLibraries.contains(it.name)) {
apply from: '$rootDir/gradle/customAndroidBuild.gradle'
} else {
//Apply custom plugin for some other project type.
}
}
Filtering by properties
subprojects {
project.ext {
projectType = null
}
project.afterEvaluate {
if (project.ext.projectType == 'jar') {
apply from: '$rootDir/gradle/customJavaBuild.gradle'
} else if (project.ext.projectType == 'aar') {
apply from: '$rootDir/gradle/customAndroidBuild.gradle'
} else {
//Apply custom plugin for some other project type.
}
}
}
And I have this extra property ext.projectType = 'jar' in my sub-modules' (projA, projB, projC) build.gradle files.
The problem is that in your project.afterEvaluate block you are applying your custom gradle script to the root project and not to the evaluated sub project, which causes the error with integTesttask already defined.
You should rewrite your project.afterEvaluate block with something similar to the following:
subprojects {
project.ext {
projectType = null
}
project.afterEvaluate {
if (project.ext.projectType == 'jar') {
// WARNING : use "project.apply ..." instead of "apply ..." here
project.apply from : "$rootDir/gradle/customJavaBuild.gradle"
} else if (project.ext.projectType == 'aar') {
project.apply from : "$rootDir/gradle/customAndroidBuild.gradle"
} else {
// nothing
}
}
}

Gradle use different tasks / arguments for each build type

I'm in the early stages of migrating an android project to gradle, using the experimental plugin 0.4.0
As part of the build process I have a number of scripts that should run prior to compiling my code / building the apk. The arguments or tasks themselves will be different for a debug or release build.
I'm struggling to find a straight forward way to achieve this.
I've stripped everything back to a simple hello world project while I figure this out.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.4.0'
}
}
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
}
android.buildTypes {
debug {
//
}
release {
//runProguard, sign etc.
}
}
android.productFlavors {
create("free")
{
applicationId = "com.example.app.free"
versionName = "1.0-free"
}
create("full")
{
applicationId = "com.example.app.full"
versionName = "1.0-full"
}
}
}
repositories {
jcenter()
}
dependencies {
compile 'joda-time:joda-time:2.7'
}
task runScript(type: Exec) {
executable "sh"
args "-c", "echo SomeScriptHere"
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn runScript
}
task wrapper(type: Wrapper) {
gradleVersion = '2.5'
}
Ideally I want to differentiate by buildType ( not productFlavor ) as the tasks required as based on the type of build not the variety of app produced.
Is it possible to specify that a task should only run on a release or debug build?
Alternatively is it possible to define different arguments to be used for my runScript task based on being a release or debug build?
Apologies if I'm missing something obvious, I'm pretty new to using gradle.
using onlyIf() would be one option gradle docs here but having to define properties seemed awkward especially as a project gets larger and more complicated.
ZXStudio has a good blog post / example here where instead of using properties or rules will iterate over the existing tasks and create a new task based on the buildType / flavor.
So for my original question the answer mean removing the runScript task above and replacing tasks.withType(JavaCompile) as follows;
Could also be extended to match build flavors and create tasks appropriately.
tasks.withType(JavaCompile) {
def newTaskName = "runScript_" + name;
def isDebug = false;
if( name.contains("Debug") )
{
isDebug = true;
}
//Create a new task
tasks.create( newTaskName, Exec ) {
if( isDebug )
{
executable "sh"
args "-c", "echo this is a DEBUG task"
}
else
{
executable "sh"
args "-c", "echo this is a RELEASE task"
}
}
dependsOn newTaskName
}

Google Apps Engine Backend - Javax.persistence missing - Android Studio

I'm trying to migrate to Android studio and my app engine code uses the Entity framework listed below
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class AppVersion {
#Id
private String applicationName;
private int minVersionRequired;
public String getApplicationName() {
return applicationName;
}
public int getMinVersionRequired() {
return minVersionRequired;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public void setminVersionRequired(int minVersionRequired) {
this.minVersionRequired = minVersionRequired;
}
}
Just creating a backend in Android Studio (0.5.6) doesn't work, I can't import javax.persistence.*
From this link I discovered that I needed to create a persistence.xml file (this was automatically created in Eclipse). I just can't figure out where in the file structure it is supposed to go. I understand it needs to be in the META-INF folder but I don't know where that corresponds for gradle (or if it has to be created in the gradle build file).
Current file structure:
-src
-main
-java
-com.package.test
class files
-webapp
-css
-js
-WEB-INF
Gradle build file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.1'
}
}
repositories {
mavenCentral();
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'
sourceCompatibility = 1.7
targetCompatibility = 1.7
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.1'
compile 'com.google.appengine:appengine-endpoints:1.9.1'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.1'
compile 'javax.servlet:servlet-api:2.5'
}
appengine {
downloadSdk = true
appcfg {
oauth2 = true
}
endpoints {
getClientLibsOnBuild = true
getDiscoveryDocsOnBuild = true
}
}
Android Studio's App Engine samples don't use JPA.
However if you want to use JPA, you need to add the JPA dependencies, this describes where you might find out what those are https://developers.google.com/appengine/docs/java/datastore/jpa/overview-dn2
So these (or some subset of these)
asm-4.0.jar
datanucleus-api-jpa-3.1.3.jar
datanucleus-core-3.1.3.jar
jdo-api-3.0.1.jar
datanucleus-api-jdo-3.1.3.jar
datanucleus-appengine-2.1.2.jar
geronimo-jpa_2.0_spec-1.0.jar
jta-1.1.jar
Look on maven.org for those dependencies will reveal how to include them in build.gradle files as compile dependencies:
asm-4.0 :
compile 'org.ow2.asm:asm:4.0'
datanucleus-api-jpa-3.1.3 :
compile 'org.datanucleus:datanucleus-api-jpa:3.1.3'
and so on.
You want the versions to be exactly as they are in the appengine sdk to ensure compatibility. Also make sure you run the enhance task on your project.
Try adding following to the build.gradle
compile group: 'javax.persistence', name: 'persistence-api', version: '1.0'

Categories

Resources