GRPC in Kotlin Multiplatform (Android, Desktop) - android

I am creating a Jetbrains Compose Multiplatform project. But I will only need Desktop (JVM) and Android, so two JVM targets. I want to factor out the logic which needs grpc, so both Android and Desktop can use it without me having to program it twice.
I can't seem to figure out a way of binding in my grpc/proto into the project, so that I can write the logic once and share it between android and desktop.
This is what my build.gradle.kts of the common project looks like:
plugins {
id("com.android.library")
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
android()
jvm("desktop")
sourceSets {
named("commonMain") {
dependencies {
api(compose.runtime)
api(compose.foundation)
api(compose.material)
api(compose.ui)
implementation(compose.preview)
implementation(compose.uiTooling)
}
}
}
}
android {
compileSdk = 31
defaultConfig {
minSdk = 21
targetSdk = 31
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
sourceSets {
named("main") {
manifest.srcFile("src/androidMain/AndroidManifest.xml")
res.srcDirs("src/androidMain/res")
}
}
}
I tried binding my protos into a sourceset but couldn't get it working.
My other approach:
Next I tried creating a second submodule where the protos and the logic would be bound, but I couldn't get that working either:
Here is the build.gradle.kts for shared-logic:
import com.google.protobuf.gradle.*
import org.gradle.kotlin.dsl.proto
plugins {
kotlin("jvm")
idea
id("com.google.protobuf")
}
version = "unspecified"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
api(project(":kotlin-common")) {
exclude(group = "io.grpc", module = "grpc-protobuf")
exclude(group = "io.grpc", module = "grpc-stub")
}
implementation("io.grpc:grpc-okhttp:${Versions.GRPC}")
api("com.google.protobuf:protobuf-java-util:${Versions.PROTOBUF}")
api("io.grpc:grpc-stub:${Versions.GRPC}")
api("io.grpc:grpc-protobuf-lite:${Versions.GRPC}")
api("io.grpc:grpc-kotlin-stub:${Versions.GRPC_KOTLIN}")
api("com.google.protobuf:protobuf-kotlin-lite:${Versions.PROTOBUF}")
api("io.insert-koin:koin-core:${Versions.KOIN}")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.COROUTINES}")
}
sourceSets {
main {
proto {
srcDirs("../protos/src/main")
}
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${Versions.PROTOBUF}"
}
plugins {
id("java") {
artifact = "io.grpc:protoc-gen-grpc-java:${Versions.GRPC}"
}
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${Versions.GRPC}"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:${Versions.GRPC_KOTLIN}:jdk7#jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
id("grpc") {
option("lite")
}
id("grpckt") {
option("lite")
}
}
it.builtins {
id("kotlin") {
option("lite")
}
}
}
}
}
Here is the build.gradle.kts for kotlin-common:
plugins {
kotlin("jvm")
}
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
implementation("io.grpc:grpc-stub:${Versions.GRPC}")
}
Here I get resolution error I tried fixing but couldn't figure out what to exclude:
Duplicate class com.google.protobuf.AbstractMessageLite found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
...

Related

groovy.lang.MissingMethodException: No signature of method: ApplicationVariantData.getName()

This question has been asked a lot of times on SO, but I was not able to find any solution that could work for me.
I am trying to migrate from groovy to kotlin DSL and getting the following error.
All the conversion is done into kotlin DSL, but when I am trying to sync the issue starts to appear. I am using the latest version of android gradle plugin.
A problem occurred configuring project ':app'.
Failed to notify project evaluation listener.
com.android.build.gradle.internal.crash.ExternalApiUsageException: groovy.lang.MissingMethodException: No signature of method: com.android.build.gradle.internal.variant.ApplicationVariantData.getName() is applicable for argument types: () values: []
Possible solutions: getAt(java.lang.String), getClass()
KotlinJvmAndroidCompilation with name 'debug' not found.
Please let me know what can be done in this, Thanks in advance.
plugins {
id("com.android.application")
id("com.google.firebase.crashlytics")
id("io.hansel.preprocessor")
id("com.google.firebase.firebase-perf")
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
id("com.google.gms.google-services")
}
buildscript {
apply("../buildSrc/config.gradle.kts")
}
repositories {
maven { url = uri(Config.Repositories.hansel_io) }
}
allprojects {
repositories {
google()
jcenter()
flatDir {
dirs("libs")
}
}
}
android {
signingConfigs {
....
}
}
defaultConfig {
...
}
buildTypes {
getByName("debug") {
...
}
getByName("release") {
...
}
}
flavorDimensions("version")
productFlavors {
create("development") {
...
}
applicationVariants.all {
val variant = this
variant.outputs
.map { it as BaseVariantOutputImpl }
.forEach { output ->
....
}
}
}
compileOptions {
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
}
buildFeatures {
dataBinding = true
}

Android & GRPC "import io.grpc.examples.helloworld.GreeterGrpc" Error

I am trying to develop GRPC on Android Mobile App. I found HelloWorld sample project from https://github.com/grpc/grpc-java/tree/v1.34.1/examples/android/helloworld
When I build the project, I got the following error:
import io.grpc.examples.helloworld.GreeterGrpc;
^
symbol: class GreeterGrpc
location: package io.grpc.examples.helloworld
I am trying to build the app with that gradle:
apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'
android {
compileSdkVersion 28
defaultConfig {
applicationId "io.grpc.helloworldexample"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
}
buildTypes {
debug { minifyEnabled false }
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
disable 'GoogleAppIndexingWarning', 'HardcodedText', 'InvalidPackage'
textReport true
textOutput "stdout"
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.2.0"
}
plugins {
lite {
artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.plugins {
lite { }
}
}
}
}
dependencies {
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'io.grpc:grpc-okhttp:1.34.1'
implementation 'io.grpc:grpc-protobuf-lite:1.34.1'
implementation 'io.grpc:grpc-stub:1.34.1'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
}
The proto file like that:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Is there any problem in the code or gradle file? Could you help me please? Thanks
The error indicates that you are missing the generated GreeterGrpc service code. You need to feed protoc compiler the gRPC-Java codegen plugin in order to get the generated gRPC code.
protobuf {
protoc { artifact = "com.google.protobuf:protoc:3.12.0" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.34.1" }
}
generateProtoTasks {
all().each { task ->
task.builtins {
java { option 'lite' }
}
task.plugins {
grpc { // Options added to --grpc_out
option 'lite' }
}
}
}
}
Note I've changed to use protoc v3.12.0 in this case. If you are using protoc older than v3.8.0, it would be
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.2.0"
}
plugins {
lite {
artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
}
grpc {
// some old grpc version, newer ones may not work, suggest upgrading
artifact = "io.grpc:protoc-gen-grpc-java:1.22.3"
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.plugins {
lite { }
grpc { // Options added to --grpc_out
option 'lite' }
}
}
}
}

Kotlin Multiplatform build failure due to android target

I am creating a Kotlin Multiplatform library with Android support.
When I try to build with gradle I get an error (./gradlew build --warning-mode all).
Either this:
Could not determine the dependencies of task ':lib:compileDebugAidl'.
> Failed to find target with hash string '29' in: /home/user/Android/Sdk
Or that:
Could not determine the dependencies of task ':lib:verifyReleaseResources'.
> Failed to find target with hash string '29' in: /home/user/Android/Sdk
The first right after indexing and the second when I do ./gradlew clean
However, there is this dependency in any case since I have already created Android apps based on that.
I have also tried Target 28 and an RC version of 30 (since 30 has not yet been officially released, but I have still created apps)
My structure of the gradle files is like this:
root
|-build.gradle.kts
|-settings.gradle.kts
|-gradlew
|-gradlew.bat
|-gradle
|-wrapper
|-gradle-wrapper.jar
|-gradle-wrapper.properties
|-lib
|-build.gradle.kts
settings.gradle.kts:
rootProject.name = "Library"
include(":lib")
root build.gradle.kts:
buildscript {
repositories {
addRepos()
maven(uri("https://dl.bintray.com/kotlin/kotlin-eap")) {
metadataSources {
gradleMetadata()
mavenPom()
}
}
}
dependencies {
classpath("com.android.tools.build:gradle:4.1.0-beta04")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
}
}
allprojects {
repositories {
addRepos()
maven(uri("https://dl.bintray.com/kotlin/kotlin-eap")) {
metadataSources {
gradleMetadata()
mavenPom()
}
}
}
}
lib build.gradle.kts:
plugins {
id("com.android.library")
kotlin("multiplatform")
id("maven-publish")
}
group = "de.datlag"
version = "1.0"
android {
compileSdkVersion = 29.toString()
buildToolsVersion = "29.0.3"
defaultConfig {
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
buildTypes {
val debug by getting {
isMinifyEnabled = false
isDebuggable = true
isShrinkResources = false
}
val release by getting {
isMinifyEnabled = false
isDebuggable = false
isShrinkResources = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
repositories {
addRepos()
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
js {
browser()
nodejs()
}
android {
publishAllLibraryVariants()
}
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val androidMain by getting {
dependsOn(jvmMain)
}
val androidTest by getting {
dependsOn(jvmTest)
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val nativeMain by getting { }
val nativeTest by getting { }
}
}
addRepos method:
fun RepositoryHandler.addRepos() {
mavenLocal {
metadataSources {
gradleMetadata()
mavenPom()
}
}
mavenCentral {
metadataSources {
gradleMetadata()
mavenPom()
}
}
jcenter {
metadataSources {
gradleMetadata()
mavenPom()
}
}
google {
metadataSources {
gradleMetadata()
mavenPom()
}
}
gradlePluginPortal()
}
In lib.build.gradle.kts you should use the compileSdkVersion(29) syntax rather than setting a string. You can see in the source for these extensions that the behavior is different if you call the string version.
/** #see #getCompileSdkVersion() */
public void compileSdkVersion(String version) {
checkWritability();
this.target = version;
}
/** #see #getCompileSdkVersion() */
public void compileSdkVersion(int apiLevel) {
compileSdkVersion("android-" + apiLevel);
}
The when passing an int it will append "android-" for you. So you could do compileSdkVersion = "android-29" if you wanted, but just passing the int is easier

Android Kotlin DSL - Unresolved reference: firebaseAppDistribution

I just migrated my Andoroid project's build system from Groovy to Kotlin DSL. On migrating, I'm unable to solve firebaseAppDistribution { .. } in build.gradle.kts.
The plugin for the FAD has already been apllied and the classpath as well.
plugins {
id("com.android.application")
//id("com.google.firebase.appdistribution") //I've tried it here but "Plugin not found"
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
id("com.google.gms.google-services")
}
apply(plugin = "com.google.firebase.appdistribution")
buildscript {
repositories {
google()
}
dependencies {
classpath("com.google.firebase:firebase-appdistribution-gradle:1.3.1")
}
}
.
.
productFlavors {
create("dev") {
firebaseAppDistribution {
serviceCredentialsFile = "xxx.json"
groups = "xx"
}
}
}
.
.
**Unresolved reference: firebaseAppDistribution**
How do I fix it ?
You could use :
import com.google.firebase.appdistribution.gradle.AppDistributionExtension
productFlavors {
create("dev") {
configure<AppDistributionExtension> {
serviceCredentialsFile = "path/to/serviceAccountKey.json"
releaseNotes="you release note"
...
}
}
}

Unresolved reference on org.gradle.api dependencies after migrating build.gradle file to build.gradle.kts in buildSrc directory

I am trying to migrate my build.gradle file to build.gradle.kts in my buildSrc directory. Note that in my buildSrc I already create a gradle plugin using java-gradle-plugin and using api from org.gradle.api such as Plugin, Project etc. But when I configured the script I got an unresolved reference inside my file whom using org.gradle.api
here is the code for the build.gradle file
plugins {
id 'java'
id 'java-gradle-plugin'
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
}
gradlePlugin {
plugins {
netguard {
id = 'pluginId'
implementationClass = 'myplugin.plugin.awesomeplugin'
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
and this is the migrated build.gradle.kts
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
`kotlin-dsl`
java
`java-gradle-plugin`
id("org.jetbrains.kotlin.jvm") version "1.3.21"
}
gradlePlugin {
plugins {
create("netguard") {
id = "pluginId"
implementationClass = "myplugin.plugin.awesomeplugin"
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = "1.8"
val compileTestKotlin: KotlinCompile by tasks
compileTestKotlin.kotlinOptions.jvmTarget = "1.8"
here some unresolved reference from org.gradle.api
org.gradle.api.Plugin
org.gradle.api.Project
org.gradle.api.file.ConfigurableFileTree
org.gradle.testing.jacoco.plugins.JacocoPluginExtension
org.gradle.testing.jacoco.tasks.JacocoCoverageVerification
org.gradle.testing.jacoco.tasks.JacocoReport
...
any help will be very much appreciated. thank you!

Categories

Resources