How to speed up iOS app builds of Kotlin Multiplatform from Android Studio - android-studio

I am have an KMP project which contains iOS app, Android app and shared KMP module.
When I try to build the iOS app from the Android Studio (in order to be able to debug it) the build succeed. ☺️
The problem is that the build always (when you change a code) take around 12 minutes 😅⏰. Which is way to long when you are debugging and often testing if given code works.
The 90% percent of time spent on build is used to run these tasks:
> Task :kmpcorelib:linkDebugFrameworkIosArm64
> Task :kmpcorelib:linkDebugFrameworkIosX64
> Task :kmpcorelib:linkKMPCoreDebugFrameworkIosArm64
> Task :kmpcorelib:linkKMPCoreDebugFrameworkIosX64
> Task :kmpcorelib:linkKMPCoreReleaseFrameworkIosArm64
> Task :kmpcorelib:linkKMPCoreReleaseFrameworkIosX64
> Task :kmpcorelib:linkReleaseFrameworkIosArm64
> Task :kmpcorelib:linkReleaseFrameworkIosX64
My question is: Is there a way how to run the app on iOS simulator without running all these task?
I dont know why the studio needs to link the RELEASE version of the framework.
Also I dont understand why it has to run the iOSArm64 variants when its running the on the X64 simulator.
Whats the difference between running linkDebugFrameworkIosArm64 and linkKMPCoreDebugFrameworkIosArm64 isnt it duplication?
PS: I run the iOS buld via clicking the default configuration in Android studio, not some custom gradle script.
This is how the KMP build.gradle looks like:
plugins {
id("com.android.library")
kotlin("multiplatform")
kotlin("native.cocoapods")
kotlin("plugin.serialization") version "1.5.0"
id("com.prof18.kmp.fatframework.cocoa") version "0.0.1"
id("io.gitlab.arturbosch.detekt")
id("maven-publish")
}
version = "1.3.11"
group = "com.betsys.kmpcorelib"
val podName = "KMPCore"
detekt {
autoCorrect = true
config = files("$rootDir/config/detekt.yml")
baseline = file("$rootDir/config/baseline.xml")
input = files("src/commonMain/kotlin")
reports {
html.enabled = true
xml.enabled = true
txt.enabled = true
}
}
// If you want to build iOS app from Android Studio - you have to put this config to comment - it somehow breaks the iOS build
fatFrameworkCocoaConfig {
fatFrameworkName = podName
outputPath = "$rootDir/../cocoapods"
versionName = "1.16.1"
}
val ktorVersion = "1.5.4"
val napierVersion = "1.4.1"
val koinVersion = "3.0.1"
val kotlinxVersion = "1.4.1"
val kotlinxDatetime = "0.1.1"
kotlin {
// We cant use simple ios() target now, since it doesnt support Arm32 architecture
// For that reason we have specify each target explicitly
// Same for folders with iOS code. We havet to use duplicit iosX64Main etc. instead of one iosMain folder
ios("ios") {
binaries.framework(podName)
}
android {
publishLibraryVariants("debug")
publishLibraryVariantsGroupedByFlavor = true
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
implementation("io.ktor:ktor-client-mock:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")
implementation("io.ktor:ktor-client-websockets:$ktorVersion")
api("io.insert-koin:koin-core:$koinVersion")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxVersion-native-mt")
api("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDatetime")
api("com.ionspin.kotlin:bignum:0.3.1-SNAPSHOT")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation( "io.mockk:mockk-common:1.11.0")
implementation("com.ionspin.kotlin:bignum:0.3.1-SNAPSHOT")
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("com.google.android.material:material:1.3.0")
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxVersion")
implementation("com.jakewharton.timber:timber:4.7.1")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
implementation("io.mockk:mockk:1.11.0")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktorVersion")
}
}
val iosTest by getting
}
}
android {
compileSdkVersion(30)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(19)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
packagingOptions {
excludes.add("META-INF/*.kotlin_module")
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
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 sdkName: String? = System.getenv("SDK_NAME")
val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
val framework = kotlin.targets
.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>(
if (isiOSDevice) {
"iosArm64"
} else {
"iosX64"
}
)
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
from({ framework.outputDirectory })
into(targetDir)
println("Build Folder => $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.build.dependsOn("packForXCode")

The "default configuration" in Android Studio (e.g. the assemble or build gradle tasks), will build all "build" tasks, which includes the linking of iOS frameworks for both debug, release and for X64 and Arm64 architectures.
Notice that packForXcode task you got there in your build.gradle.kts file? That's what you want to call when you want to build the KMM module for your iOS application (at least locally). Using that task will build only the architecture and configuration you need (e.g. X64 and DEBUG on your simulator), and you'll quickly see that it's quite a lot faster. It's supposed to be called in a Run script phase as part of the Build steps of your Xcode project.
I believe this should have been added to your Xcode project automatically if you're using the Kotlin Multiplatform application template when creating a new project in Android Studio.
You can read more about it here: Understand the KMM project structure | Kotlin Multiplatform Mobile Docs

I use this task to build changes for iOS:
./gradlew :shared:compileKotlinIosSimulatorArm64
works pretty fast

Related

KMM Project: Expected class has no actual declaration in module for JVM

I have a KMM project that is working perfectly except Android Studio gives an error on every expect function/value in my project complaining the actual version of it doesn't exist for JVM.
The A in a yellow diamond to the side of it shows both the iOS and Android actual versions and the project builds/runs just fine.
I've double checked package names and it happens with every expect regardless of the package.
I've looked over my gradle build files and can't find anything weird when comparing them to a new KMM example project.
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("com.rickclephas.kmp.nativecoroutines") version "0.12.2-new-mm"
}
version = "1.0"
kotlin {
android()
iosX64()
iosArm64()
//iosSimulatorArm64() sure all ios dependencies support this target
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
ios.deploymentTarget = "15.0"
podfile = project.file("../iosApp/Podfile")
framework {
baseName = "shared"
}
}
sourceSets {
val ktorVersion = "2.0.2"
val commonMain by getting {
dependencies {
implementation("com.litclimbing:firebase-auth:+")
implementation("com.litclimbing:firebase-firestore:+")
implementation("com.litclimbing:buffer:+")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
implementation("io.ktor:ktor-client-core:$ktorVersion")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1")
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
}
}
val androidTest by getting
val iosX64Main by getting
val iosArm64Main by getting
//val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
//iosSimulatorArm64Main.dependsOn(this)
dependencies {
implementation("io.ktor:ktor-client-darwin:$ktorVersion")
}
}
val iosX64Test by getting
val iosArm64Test by getting
//val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
//iosSimulatorArm64Test.dependsOn(this)
}
}
sourceSets.all {
languageSettings.optIn("kotlin.RequiresOptIn")
languageSettings.optIn("kotlin.ExperimentalUnsignedTypes")
}
}
android {
compileSdk = 32
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 29
targetSdk = 32
}
}
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
classpath("com.android.tools.build:gradle:7.2.1")
classpath("com.google.gms:google-services:4.3.10")
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.0")
}
}
allprojects {
repositories {
google()
mavenLocal()
mavenCentral()
maven {
setUrl("https://jitpack.io")
}
maven {
setUrl("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven")
}
}
}
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
I've even tried copying the gradle files to a new KMM project to see if it would break it and it didn't so I'm at a loss of where to even look.
Not really the solution I was looking for but it seems to be a bug in Android Studio/IntelliJ and not the gradle setup.
To fix it do the following.
Close Android Studio
Open your project folder in the file browser
Rename the .idea folder to .ideaBackup
Reopen the project
Assuming everything is now working, delete .ideaBackup
Enjoy your lack of random errors

How can i downgrade the gradle on project kotlin multiplatform to use a Android Studio Stable version?

Recently i started to work on a kotlin multiplatform project, i did not have any previous experience when i started, and i got the project with its base already created. The developer that create the project had the ideia to use the compose library on android development part.
Then he quit the job, and i started in it.
But i choose to not use compose because of the rush on deliver the application.
So the project gradle version is currently on 6.8 and android plugin on 7.0.0-alpha05
but i want to downgrade to stop to use the Android Studio on Canary version, and use on a stable version. But when i downgrade the gradle i am getting this error:
A problem occurred configuring project ':shared'.
> Failed to notify project evaluation listener.
> /Users/jhonata/Documents/Projetos/Aurea/quicktendr-mgmt/shared/src/main/AndroidManifest.xml (No such file or directory)
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':shared'.
at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:75)
at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:68)
at org.gradle.configuration.project.LifecycleProjectEvaluator.access$400(LifecycleProjectEvaluator.java:51)
at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate.run(LifecycleProjectEvaluator.java:191)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
at ...
gradle properties:
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
shared gradle:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.android.library")
id("kotlin-parcelize")
id("dev.icerock.mobile.multiplatform-resources")
kotlin("plugin.serialization")
}
android {
configurations {
create("androidTestApi")
create("androidTestDebugApi")
create("androidTestReleaseApi")
create("testApi")
create("testDebugApi")
create("testReleaseApi")
}
}
kotlin {
// jvm()
android()
ios {
binaries {
framework {
baseName = "shared"
when (val target = this.compilation.target.name) {
"iosX64" -> {
export(Deps.Decompose.iosX64)
}
"iosArm64" -> {
export(Deps.Decompose.iosArm64)
}
else -> error("Unsupported target: $target")
}
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
api(Deps.Decompose.decompose)
api(Deps.coroutines)
implementation(Deps.ktxSerializationJson)
implementation(Deps.ktorCore)
implementation(Deps.ktorSerialization)
implementation(Deps.kissMeCommon)
implementation("ch.qos.logback:logback-classic:1.2.3")
implementation("dev.icerock.moko:mvvm-core:0.10.1")
implementation("dev.icerock.moko:mvvm-livedata:0.10.1")
api("dev.icerock.moko:resources:0.15.1")
api("dev.icerock.moko:mvvm:0.9.1")
implementation("io.ktor:ktor-client-logging:1.4.2")
implementation("io.ktor:ktor-client-auth:1.4.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
// val mobileMain by creating {
// dependsOn(commonMain)
// dependencies {
//
// }
// }
val androidMain by getting {
dependencies {
implementation(Deps.ktorAndroid)
implementation(Deps.kissMeAndroid)
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13")
}
}
val iosMain by getting {
dependencies {
implementation(Deps.ktorIOS)
implementation(Deps.kissMeIOS)
}
}
val iosTest by getting
// val jvmMain by getting {
// dependencies {
// implementation("io.ktor:ktor-client-okhttp:1.4.2")
// }
// }
named("iosX64Main") {
dependencies {
api(Deps.Decompose.iosX64)
}
}
named("iosArm64Main") {
dependencies {
api(Deps.Decompose.iosArm64)
}
}
}
}
multiplatformResources {
multiplatformResourcesPackage = "com.quicktendr.mgmt" // required
iosBaseLocalizationRegion = "es" // optional, default "en"
}
android {
compileSdkVersion(29)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework =
kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
gradle:
buildscript {
repositories {
gradlePluginPortal()
jcenter()
google()
mavenCentral()
maven("https://kotlin.bintray.com/kotlinx")
maven("https://dl.bintray.com/jetbrains/kotlin-native-dependencies")
maven("https://dl.bintray.com/kotlin/kotlin-dev")
maven("https://dl.bintray.com/icerockdev/plugins")
}
dependencies {
val kotlinVersion = "1.4.31"
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion")
classpath("com.android.tools.build:gradle:4.2.1")
classpath("com.github.jengelman.gradle.plugins:shadow:5.2.0")
classpath("dev.icerock.moko:resources-generator:0.15.1")
classpath("com.google.gms:google-services:4.3.5")
classpath("com.google.firebase:firebase-crashlytics-gradle:2.5.2")
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven("https://dl.bintray.com/arkivanov/maven")
maven("https://dl.bintray.com/icerockdev/moko")
maven("https://dl.bintray.com/netguru/maven/")
maven("https://repo.repsy.io/mvn/chrynan/public")
maven("https://jitpack.io")
}
}
If you just want to downgrade gradle, you can downgrade gradle in the gradle properties file which you posted.
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
You would need to set this to the latest version supported by Android Studio 4.2.1. There are also compatibility considerations with the Android gradle plugin. You can see a compatibility matrix for that here:
https://developer.android.com/studio/releases/gradle-plugin#4-2-0
Please be aware that if your project was using things like compose which relied on particular versions of AGP/Gradle, you might need to rewrite those pieces. It is okay to use the canary versions of android studio or recent versions of intellij - unless you are hitting some issue. You can use compose and old view classes together using AndroidView
https://developer.android.com/jetpack/compose/interop/interop-apis#views-in-compose

Android Studio build works, Gradle command line fails

I have ported an app from Eclipse to Android Studio, implemented my needed flavors and have it allow working in Android Studio. Due to the number of flavors I would prefer to build it using command line Gradle. However when I run the following command to build my release APKs
gradlew.bat assembleRelease
I get the following error:
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\whatever\build.gradle' line: 1
* What went wrong:
A problem occurred evaluating project ':MyCompany'.
> java.lang.UnsupportedClassVersionError: com/android/build/gradle/AppPlugin : Unsupported major.minor version 52.0
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
I have run with --stacktrace and --debug and it really does not offer any other information, other than pointing the error to be with the first line of the build.gradle:
apply plugin: 'com.android.application'
I have attempted the following based on other stackoverflow responses to this error:
Upgraded to JavaVersion.VERSION_1_8
Added Jack the build.gradle (and that slowed everything down, but it was required for 1.8, even though it is deprecated?)
Increased memory for heap (org.gradle.jvmargs=-Xmx4096m) and dex (javaMaxHeapSize "4g").
I am running Android Studio 2.3.3
Here is my build.gradle file. I have left only a couple of the flavors to save space, and renamed some of the stuff to protect the innocent. I have left in the dependencies in case that might be the problem? The only funkiness is that I am renaming the APK and pushing it to a different folder, but that is all working when I run the release build directly out of Android Studio. The build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
repositories {
maven { url 'https://maven.fabric.io/public' }
}
android {
signingConfigs {
config {
keyAlias 'whatever'
keyPassword 'imnotgoingtotellyou'
storeFile file('C:/whereever/mycompany.keystore')
storePassword 'yeps'
}
}
compileSdkVersion 25
buildToolsVersion '25.0.3'
defaultConfig {
jackOptions {
enabled true
additionalParameters('jack.incremental': 'true')
}
applicationId "com.mycompany.default"
minSdkVersion 14
targetSdkVersion 23
versionCode 44
versionName "2.1.44"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 }
signingConfig signingConfigs.config
}
dexOptions {
javaMaxHeapSize "4g"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.config
}
}
productFlavors.whenObjectAdded { flavor ->
flavor.ext.set('directoryPath', '')
flavor.ext.set('apkName', '')
}
productFlavors {
Flavor1 {
signingConfig signingConfigs.config
directoryPath = 'flavor1'
}
Flavor2 {
applicationId 'com.mycompany.flavor2'
signingConfig signingConfigs.config
directoryPath = 'flavor2'
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def path = "C:/AndroidBuilds/MyBuild.Build/" + variant.productFlavors[0].directoryPath + "/"
logger.error("Path = " + path)
def SEP = "-"
def apkName = variant.productFlavors[0].apkName
def flavor = variant.productFlavors[0].name
if (apkName != '')
flavor = apkName;
def version = variant.versionCode
def newApkName = path + version + SEP + flavor
logger.error("newApkName = " + newApkName)
output.outputFile = new File(newApkName + ".apk")
}
}
}
dependencies {
compile project(':androidpdfview100')
compile 'com.android.support:support-v13:25.3.1'
compile 'com.google.code.gson:gson:2.7'
compile 'joda-time:joda-time:2.5'
compile 'com.google.android.gms:play-services-maps:11.0.4'
compile files('libs/httpmime-4.2.5.jar')
compile files('libs/itextg-5.4.4.jar')
compile files('libs/js.jar')
compile files('libs/logentries-android-2.1.1.jar')
compile files('libs/universal-image-loader-1.8.6.jar')
compile files('libs/xmlworker-5.4.4.jar')
compile files('libs/zbar.jar')
compile('com.crashlytics.sdk.android:crashlytics:2.6.8#aar') {
transitive = true;
}
}
UPDATE
The project structure looks like this:
It was generated automatically by Android Studio when I ported the code from Eclipse:
When you drill into the App itself it looks like this:
For anyone facing this issue in the future, for the command line build make sure your JAVA_HOME is set to the same version as Android Studio is using. E.g. JDK v8:
JAVA_HOME=C:\Program Files\Java\jdk1.8.0_112
Or wherever your 1.8 JDK is. It is a beast and sucks up memory, but it was the only way to get around this build error. I would NOT recommend that you build in Android Studio with 1.8 since it seems to require Jack which is just plain slow. And sadly it is deprecated to boot.
I work on macOS with Zsh as my shell and have just downloaded Android Studio 3.6.2.
I added the following to my ~/.zshenv file, and everything worked.
export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"
I believe updating ~/.profile would do it as well, but I haven't tried it.

Import swagger-codegen project into existing Android project

Im trying to integrate a "module"-project generated by swagger-codegen, into my Android project.
Haven't worked that much with gradle before and the swagger-codegen creates a quite messy build.gradle from my point of view.
I have a hard time finding documentation on how to do this. And I feel a bit lost.
I used this method described in the FAQ
mvn clean package
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l java --library=okhttp-gson \
-o /var/tmp/java/okhttp-gson/
So fare I tried to copy the source from the project that was generated by swagger-codegen and merge the two gradle build files. I removed the Junit tests because I couldn't get the Junit dependency working (Implementing Swagger-codegen project - Error:(23, 17) Failed to resolve: junit:junit:4.12). But then I got stuck with some conflict between the plugins?
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Here's the build.gradle:
import static jdk.nashorn.internal.runtime.regexp.joni.ApplyCaseFold.apply
apply plugin: 'idea'
apply plugin: 'eclipse'
group = 'io.swagger'
version = '1.0.0'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
// classpath 'com.android.tools.build:gradle:1.5.+'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
}
}
repositories {
jcenter()
maven { url 'http://repo1.maven.org/maven2' }
}
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 23
buildToolsVersion '23.0.2'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "\u0024{project.name}- \u0024{variant.baseName}-\u0024{version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = 'XxxxXxxx'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
dependencies {
compile 'io.swagger:swagger-annotations:1.5.8'
compile 'com.squareup.okhttp:okhttp:2.7.5'
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'com.google.code.gson:gson:2.6.2'
compile 'joda-time:joda-time:2.9.3'
// testCompile 'junit:junit:4.12'
}
Am I doing something complete wrong here? What is the correct way to implement swagger-codegen code into my project?
The swift way to import it was to compile the swagger generated project then copy the .jar file to my android project and add its as a library.
I have a hard time finding documentation on how to do this. And I feel a bit lost.
You could clone the Android swagger-codegen example.
(which does use Junit, so I'm not sure what error you got)
Unless that's what you mean by
So far I tried to copy the source and merge the two gradle build files
To which, I ask, what two Gradle files? It looks like you merged an Android Gradle file with a Java Gradle file, which seems to causing more issues because you are getting...
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Which seems pretty self explanatory when you have this line
apply plugin: 'java'
It's not too clear what you are trying to do here other than check the build target
if(hasProperty('target') && target == 'android')

Android Studio 2.0 Preview 5, linking ndk app fails to locate module .so and .a

I have an ndk project with two modules:
abwrenderer - native library module
app - native and java hybrid, glues java to the abwrenderer
I just updated to AS 2.0 Preview 5 this morning, and encountered some gradle related issues.
I upgraded to gradle-2.10 and switched to gradle-experimental:0.6.0-alpha5. When attempting to debug, an ndk build is triggered and I run into the following problem:
Error:error: C:\android\projects\foo\abwrenderer\build\intermediates\binaries\debug\obj\armeabi-v7a\libabwrenderer.so: No such file or directory
Now when I was on gradle-2.9 & gradle-experimental:0.6.0-alpha3, the libraries were built in this directory. After this morning's upgrades, the libraries are now located in:
C:\android\projects\foo\abwrenderer\build\libs\abwrenderer\shared\armeabi-v7a\debug
Is there a way to update the search location for project dependencies that build libraries?
For reference, I define the dependency on abwrenderer project as follows (build.gradle (app)):
android.sources {
main {
jni {
source {
srcDirs 'src/main/jni'
}
dependencies {
project ":abwrenderer" buildType "debug" linkage "shared"
}
}
jniLibs {
source {
srcDirs 'src/main/libs'
}
}
}
}
And build.gradle for abwrenderer project is as follows:
apply plugin: "com.android.model.native"
model {
android {
compileSdkVersion = 23
}
android.ndk {
moduleName = "abwrenderer"
cppFlags.addAll(["--std=c++11",
"-fexceptions",
"-frtti"])
ldLibs.addAll(["android", "EGL", "GLESv3", "log", "dl"])
stl = "c++_static"
debuggable = true
}
android.sources {
main {
jni {
exportedHeaders {
srcDir "src/main/jni"
}
}
}
}
}
I have invalidated caches and restarted, done a clean build, etc. Any help would be greatly appreciated!
Your defaultConfig and ndk blocks were missing some info. They should look similar to this:
defaultConfig {
applicationId = 'com.myapp.abwrenderer'
minSdkVersion.apiLevel = 13
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = '1.0'
}
ndk {
platformVersion = 21
moduleName = 'abwrenderer'
toolchain = 'clang'
stl = 'gnustl_static'
cppFlags.addAll(['-std=c++11'])
ldLibs.addAll(['android', 'EGL', 'GLESv3', 'log', 'dl'])
}
You should take a look at the following NDK sample from Google to see how they did it: hello-libs

Resources