I've started a hello world project in Android Studio.
I've added test-shared as a module because the files in there need to be seen by test and androidTest.
settings.gradle:
include ':app'
include ':test-shared'
rootProject.name = "My Application"
build.gradle (app level):
dependencies {
androidTestImplementation(project(":test-shared"))
testImplementation(project(":test-shared"))
}
build.gradle (test-shared):
plugins {
id 'java-library'
}
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "junit:junit:$junit"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
testImplementation "junit:junit:$junit"
}
And within ExampleInstrumentedTest I try to call a method in MainCoroutineRule:
#RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
#Test
fun useAppContext() {
MainCoroutineRule().doSomething()
}
}
Which gives the error message:
Unresolved reference: test
for the test directory, the same result.
change build.gradle test-shared to:
apply plugin: 'kotlin'
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "junit:junit:$junit"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
}
and add:
packagingOptions {
exclude "META-INF/licenses/**"
exclude "META-INF/AL2.0"
exclude "META-INF/LGPL2.1"
}
to build.gradle App level
An alternative solution will be to use a specific folder inside the app module, for example sharedTest
then in your build.gradle.kts for app you could have something like this
android {
sourceSets {
this.getByName("androidTest") {
resources.srcDirs("src/androidTest/resources", "src/sharedTest/resources")
}
this.getByName("test") {
resources.srcDirs("src/test/resources", "src/sharedTest/resources")
}
}
}
This ensures that test and androidTest will use the resources in testFolder
Resource for how to set up a shared Test folder.
https://www.youtube.com/watch?v=wEmFifgS0PY
In the app gradle add the following code block, which allows the androidTest and test source set to access resources within the package, without this section the java folder will remain grey and can't be properly accessed.
android {
sourceSets {
androidTest.java.srcDirs += "src/test-shared/java"
test.java.srcDirs += "src/test-shared/java"
}
}
add junit dependency to your build.gradle (app level)
dependencies {
...
testImplementation "junit:junit:$junit"
}
Related
The error goes on to say "Please fix your configuration (or suppressKotlinVersionCompatibilityCheck but don't say I didn't warn you!)."
It is not obvious to me how to "fix" the configuration. I added the suggested flag, but it does not resolve and fails on its own.
The IDE is Dolphin Android Studio Dolphin | 2021.3.1
The project sets the Kotlin version:
buildscript {
ext.kotlin_version = '1.6.10'
I previously set the project to use Kotlin 1.7.10 here, but downgraded in the vain hope it would solve the issue, but it does not.
I tried adding an explicit dependency on androidx.compose.compiler:compiler which appears to be silently ignored.
I do not see where Kotlin 1.6.21 and Compose Compiler 1.2.0-alpha05 are being set, as neither is set in the build files.
I'm familiar with Android, but not Compose. I am using the current stable IDE and dependency statements taken directly from the Compose documentation, and yet the project fails to build.
I suspect there is some magic combination of dependency versions needed to use Compose in Dolphin, but I have not been able to find it.
I tried Compose at v1.0 but had to back out again as there were so many issues, and it seems it is still challenging to work with, but perhaps some kind soul will point out my error and then I will happily apologise to our friends at Google. :-)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs'
apply plugin: 'com.google.firebase.crashlytics'
android {
namespace "com.blah"
compileSdk 33
defaultConfig {
applicationId "com.blah"
minSdk 21
targetSdk 33
versionCode 123
versionName "1.2.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
flavorDimensions "environment"
productFlavors {
staging {
dimension "environment"
applicationIdSuffix ".staging"
}
production {
dimension "environment"
}
}
applicationVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "MyApp-${variant.versionName}-${variant.name}.apk"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
buildFeatures {
dataBinding true
compose true
}
lint {
disable 'RtlHardcoded'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2'
// Android X Jetpack
implementation "androidx.appcompat:appcompat:1.5.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
implementation 'androidx.core:core-ktx:1.9.0'
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation "androidx.fragment:fragment-ktx:1.5.2"
implementation "androidx.collection:collection-ktx:1.2.0"
implementation "androidx.window:window:1.0.0"
// Jetpack Compose
implementation("androidx.compose.ui:ui:1.2.1")
implementation("androidx.compose.ui:ui-tooling:1.2.1")
// Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
implementation("androidx.compose.foundation:foundation:1.2.1")
implementation("androidx.compose.material:material:1.2.1")
implementation("androidx.compose.material:material-icons-core:1.2.1")
implementation("androidx.compose.material:material-icons-extended:1.2.1")
// Integration with observables
implementation("androidx.compose.runtime:runtime-livedata:1.2.1")
implementation("androidx.compose.runtime:runtime-rxjava2:1.2.1")
// Google
implementation "com.google.android.material:material:1.6.1"
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
// Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
implementation "androidx.navigation:navigation-ui-ktx:2.5.2"
// Firebase & Crashlytics
implementation "com.google.firebase:firebase-core:21.1.1"
implementation "com.google.firebase:firebase-analytics:21.1.1"
implementation "com.google.firebase:firebase-crashlytics:18.2.13"
implementation "com.google.firebase:firebase-messaging:21.0.1"
// Urban Airship push messaging
implementation "com.urbanairship.android:urbanairship-fcm:13.3.5"
// Twilio (video calling)
implementation "com.twilio:video-android-ktx:7.1.1"
implementation "com.twilio:audioswitch:1.1.4"
// ExoPlayer
implementation "com.google.android.exoplayer:exoplayer-core:2.18.1"
implementation "com.google.android.exoplayer:exoplayer-ui:2.18.1"
// Third-party
implementation "com.jakewharton.timber:timber:5.0.1"
implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.squareup.picasso:picasso:2.71828"
implementation "net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.3.0"
// https://github.com/square/okhttp/blob/master/CHANGELOG.md
implementation "com.squareup.okhttp3:okhttp:4.9.3"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.3"
// Open Source Licence List
implementation "com.github.franmontiel:AttributionPresenter:1.0.1"
// Shake to Send Feedback
implementation "com.linkedin.shaky:shaky:3.0.4"
implementation "com.jraska:falcon:2.2.0"
// Page Indicator View
implementation 'com.github.romandanylyk:PageIndicatorView:v.1.0.3'
// Testing
implementation "androidx.legacy:legacy-support-v4:1.0.0"
testImplementation "junit:junit:4.13.2"
testImplementation "androidx.test:core:1.4.0"
testImplementation "org.mockito:mockito-core:4.6.0"
androidTestImplementation "androidx.test:runner:1.4.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.2.1")
apply plugin: 'com.google.gms.google-services'
}
Module build file:
apply plugin: "com.github.ben-manes.versions"
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.2"
classpath "com.google.firebase:firebase-crashlytics-gradle:2.9.2"
classpath "com.google.gms:google-services:4.3.14"
classpath "com.github.ben-manes:gradle-versions-plugin:0.42.0"
}
}
allprojects {
repositories {
google()
maven { url "https://jitpack.io" }
mavenCentral()
jcenter() {
content {
includeModule("com.google.android", "flexbox")
}
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
In your app/build.gradle file in the android block add:
android {
//..
composeOptions {
kotlinCompilerExtensionVersion "1.3.1"
}
}
According to the compatibility map use kotlin 1.7.10
I have created a Kotlin multiplatform project using Intelli-j IDE (community edition) following a tutorial from this site:
https://medium.com/#cafonsomota/set-up-your-first-kotlin-multiplatform-project-for-android-and-ios-april-2020-258e2b1d9ef4
What I have not followed is the xCode part of the tutorial since, at this point although I want this project to be multiplatform, my primary interest is for Android.
When I am running the common sample tests, I see the error:
e: org.jetbrains.kotlin.konan.MissingXcodeException: An error occurred during an xcrun execution. Make sure that Xcode and its command line tools are properly installed.
I can also see that the for the associated configuration, tasks details the following:
cleanIosTest iosTest
That is why I am receiving the error.
What I can't figure out is how to change Sample Test to not run that configuration. I have tried to remove those tasks, Apply and Save but they keep reappearing when I run them. I can't see anything in the build.gradle files that indicates anything iOS specific for testing.
build.gradle.app
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
google()
jcenter()
mavenCentral()
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
defaultConfig {
applicationId 'org.jetbrains.kotlin.mpp_app_android'
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName '1.0'
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}
buildTypes {
release {
minifyEnabled false
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
}
kotlin {
android("android")
// This is for iPhone emulator
// Switch here to iosArm64 (or iosArm32) to build library for iPhone device
iosX64("ios") {
binaries {
framework()
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
androidMain {
dependencies {
implementation kotlin('stdlib')
}
}
androidTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
iosMain {
}
iosTest {
}
}
}
// This task attaches native framework built from ios module to Xcode project
// (see iosApp directory). Don't run this task directly,
// Xcode runs this task itself during its build process.
// Before opening the project from iosApp directory in Xcode,
// make sure all Gradle infrastructure exists (gradle.wrapper, gradlew).
task copyFramework {
def buildType = project.findProperty('kotlin.build.type') ?: 'DEBUG'
def target = project.findProperty('kotlin.target') ?: 'ios'
dependsOn kotlin.targets."$target".binaries.getFramework(buildType).linkTask
doLast {
def srcFile = kotlin.targets."$target".binaries.getFramework(buildType).outputFile
def targetDir = getProperty('configuration.build.dir')
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
The Sample tests look like this:
package sample
import kotlin.test.Test
import kotlin.test.assertTrue
class SampleTests {
#Test
fun testMe() {
assertTrue(Sample().checkMe() > 0)
}
#Test
fun testProxy() {
assertTrue(Proxy().proxyHello().isNotEmpty())
}
}
The configuration looks like this:
Does anyone know how I can resolve this without needing to download xCode? I am happy to share any other information but am not truthfully sure what I should be sharing for this.
Incidentally, I did create another configuration without that line but, when I press the green PLAY button on the first test, it always defaults to the Sample Test configuration with the iOS tasks in.
This problem is caused by the bug, already described in the Kotlin issue tracker, see here. If you want to run Android-only tests, you should go with Gradle tasks named test<Debug | Release>UnitTest instead of the allTests, which includes the only iOS in your case.
I want to include a module A into Module B.
Module A's build.gradle includes packackingOptions that need to be executed.
These packackingOptions are executed when I build module A. They are not executed when I build module B, which imports module A.
How can I make sure that the packackingOptions from module A's build.gradle are also executed when importing module A into module B?
Module B's build.gradle looks like this:
dependencies {
implementation project(':A')
}
Module A's build.gradle looks like this:
android {
packagingOptions {
pickFirst 'assets/**'
}
}
I set up the project structure as follows:
buildscript-test-app
|
|
buildscript-test-lib
| \------------------------\
| |
buildscript-test-lib-sub-a buildscript-test-lib-sub-b
Both lib-sub-* contain assets/foo.txt with different contents.
build.gradle of buildscript-test-lib:
apply plugin: 'com.android.library'
android {
// omitted default config stuff
packagingOptions {
pickFirst 'assets/**'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':buildscript-test-lib-sub-a')
implementation project(':buildscript-test-lib-sub-b')
}
build.gradle of buildscript-test-app:
apply plugin: 'com.android.application'
android {
// omitted default config stuff
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':buildscript-test-lib')
}
Gradle always picks the file from buildscript-test-lib-sub-a regardless of the order of dependencies (presumably because of alphabetic ordering).
Something else in your buildscript must be wrong if this doesn't work. If it doesn't work, can you provide more details on the build.gradle of your app module and library modules?
Maybe you are overriding pickFirsts in your app. If that's the case, you should instead of pickFirsts = [somevalue] do pickFirst += 'foo' or pickFirst = 'foo'
I have an Android application module (app) and an Android library module (library). Both app and library contain these same dependencies:
dependencies {
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.reactivex:rxjava:1.0.13'
compile 'io.reactivex:rxandroid:0.25.0'
}
However when I try to add that block to the project build.gradle, it complains about not knowing the "compile" DSL.
EDIT: I'm asking about putting this dependencies block in the PROJECT build.gradle, to avoid repeating in each module's build.gradle.
As of Gradle Plugin version 3.0.0 there is a nicer way to do this. We can control whether each dependency is available for only the current module, or for the current module AND any modules which depend on it. This will allow us to easily share dependencies across modules within a project.
Here's how we used to declare dependencies:
compile 'example.dependency:1.0.0'
Here are the new configurations which should replace compile:
implementation 'example.dependency:1.0.0' --> this dependency is only used within this module
api 'example.dependency:1.0.0' --> this dependency will also be available in any builds that depend on this module
Here's how to do that with the architecture you mentioned in the question. Assuming that we have a module named 'library' that is consumed by the 'app' module, we can use the api configuration to declare that the dependency should be shared with any module that depends on it.
library module build.gradle
dependencies {
// dependencies marked 'implementation' will only be available to the current module
implementation 'com.squareup.okhttp:okhttp:2.4.0'
// any dependencies marked 'api' will also be available to app module
api 'com.squareup.retrofit:retrofit:1.9.0'
api 'io.reactivex:rxjava:1.0.13'
api 'io.reactivex:rxandroid:0.25.0'
}
app module build.gradle:
dependencies {
// declare dependency on library module
implementation project(':library')
// only need to declare dependencies unique to app
implementation 'example.dependency:1.0.0'
}
Please see this guide for further information and diagrams.
The dependencies block(closure) needs DependencyHandler as delegate
You need to pass DependencyHandler of each project to shared dependencies in project gradle.build.
project build.gradle
ext.sharedGroup = {dependencyHandler->
delegate = dependencyHandler
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.reactivex:rxjava:1.0.13'
compile 'io.reactivex:rxandroid:0.25.0'
}
app build.gradle
dependencies {
sharedGroup dependencies
}
ref. https://github.com/b1uec0in/DependencyVersionResolver
(see 2. Using default dependency group.
This sample explains many other tips for sharing library version, sdk versions ... for large project that have many modules.)
You can define shared gradle dependencies in the library module, and if the app module has the library as a dependency, you won't need to specify everything twice. Taking this further, you could create a 'common' module that requires the shared gradle dependencies, and have both the app & library module require the common module.
You could do something like this where the project build.gradle will specify the dependencies needed as variable names then in the app build.gradle files you just need to include the variable names. This is very useful when you have many modules and don't want to edit everyone when a version number changes!
project build.gradle
buildscript {
ext {
googlePlayServicesVersion = '7.5.0'
supportLibVersion = '22.2.0'
}
... (the rest of your repositories/dependency info here) ...
}
ext {
minSdkVersion=16
targetSdkVersion=21
buildToolsVersion='22.0.1'
compileSdkVersion=21
//Android Dependencies
supportV4 = 'com.android.support:support-v4:' + supportLibVersion
supportAnnotations = 'com.android.support:support-annotations:' + supportLibVersion
recyclerView = 'com.android.support:recyclerview-v7:' + supportLibVersion
cardView = 'com.android.support:cardview-v7:' + supportLibVersion
palette = 'com.android.support:palette-v7:' + supportLibVersion
appCompat = 'com.android.support:appcompat-v7:' + supportLibVersion
multidex = 'com.android.support:multidex:1.0.1'
appCompat = 'com.android.support:appcompat-v7:' + supportLibVersion
supportDesign = 'com.android.support:design:' + supportLibVersion
playServicesAnalytics = 'com.google.android.gms:play-services-analytics:' + googlePlayServicesVersion
}
app build.gradle file
dependencies {
compile rootProject.ext.supportV4
compile rootProject.ext.appCompat
compile rootProject.ext.supportAnnotations
compile rootProject.ext.recyclerView
compile rootProject.ext.cardView
compile rootProject.ext.palette
compile rootProject.ext.appCompat
compile rootProject.ext.multidex
compile rootProject.ext.supportDesign
compile rootProject.ext.playServicesAnalytics
}
Hope that this helps!
Share libraries using ext block in the root project module
This is an easy way to use the library across all modules in the
android project
Please follow these steps:
Add ext block (it is used to define extra properties for the project) in root project gradle file
Add common libraries in with variable name in ext block
e.g name = [
libraries without implementation keyword
]
Used this ext block in module level using implementation and variable name
e.g implementation variable_name
See below code for complete implementation
build.gradle :project
buildscript {
... (the rest of your repositories here) ...
}
ext { **// ext block start here**
appModuleLibraries = [
commonLibraries,
/*Projects*/
project(':hco-cutout'),
project(':utils')
]
commonLibraries = [
/*Android Libs*/
'androidx.core:core-ktx:1.7.0',
'androidx.appcompat:appcompat:1.4.1',
'com.google.android.material:material:1.5.0',
'androidx.constraintlayout:constraintlayout:2.1.3',
/*Gesture viw for image zooming */
'com.alexvasilkov:gesture-views:2.5.2',
]
cutoutModulleLibraries = [
commonLibraries,
project(':utils'),
// Selfie segmentation
'com.google.mlkit:segmentation-selfie:16.0.0-beta4',
/*checker board drawable*/
'com.github.duanhong169:checkerboarddrawable:1.0.2',
]
} **// ext block end here**
build.gradle :app
dependencies {
/*App Module Libraries in root project gradle*/
implementation appModuleLibraries
}
build.gradle :cutout
dependencies {
/*cutout Module Libraries in root project gradle*/
implementation cutoutModulleLibraries
implementation project(':utils')
}
Hope that this helps!
Based on #SMKS answer, I would prefer this solution for transitive option capability and simplicity
project build.gradle
buildscript {
... (the rest of your repositories/dependency info here) ...
}
ext {
googlePlayServicesVersion = '7.5.0'
supportLibVersion = '22.2.0'
}
app build.gradle file
dependencies {
compile 'com.android.support:support-v4:' + supportLibVersion
compile ' com.android.support:support-annotations:' + supportLibVersion
compile = 'com.android.support:recyclerview-v7:' + supportLibVersion {
transitive = true // do not know if this make sens/interest just for example
}
...
}
I'm new to gradle. Please help me understand how to use the keyword "provided" that is in build.gradle dependencies block.
And what is the difference between this "provided" with "providedCompile" and "providedRuntime"?
build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
def presentationDependencies = rootProject.ext.presentationDependencies
def presentationTestDependencies = rootProject.ext.presentationTestDependencies
compile project(':domain')
compile project(':data')
apt presentationDependencies.daggerCompiler
compile presentationDependencies.dagger
compile presentationDependencies.butterKnife
compile presentationDependencies.recyclerView
compile presentationDependencies.rxJava
compile presentationDependencies.rxAndroid
provided presentationDependencies.javaxAnnotation //what is this???
...
}
EDIT
The project in question has no mention of
configuration {
provided
}
and it still compiles!
The project is Android-cleanArchitecture
TIA
Gradle has no built in support for the provided dependency scope.
However this blog (credit goes to Danny, the blog's writer) describes how it can be emulated.
In short you need to provide a new configuration named "provided":
configurations {
provided
}
Then add this configuration to the relevant source sets configurations:
sourceSets {
main.compileClasspath += configurations.provided
test.compileClasspath += configurations.provided
test.runtimeClasspath += configurations.provided
}
And finally you're good to go:
dependencies {
provided <your dependency>
}
Note that according to the blog post if you're using Eclipse there's a "major flaw" but the post also provides a workaround for that.