TL;DR
Any chance to compile Google Analytics inside library module without any help from application module?
I'm struggling for more than a week on how to compile an use GoogleAnalytics in my library.
The goals are:
1. Compile and run GoogleAnalytics in android library
2. Maintain an application context (Singletone? )
Here is how i'm trying to compile GoogleAnalytics in my library build.gradle file
buildscript {
ext {
support = '27.0.2' // https://developer.android.com/topic/libraries/support-library/revisions.html
kotlin = '1.2.20' // https://kotlinlang.org/docs/reference/using-gradle.html
playServices = '11.8.0'
}
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
classpath 'com.google.gms:google-services:3.1.0'
}
}
And the code that handles all analytics:
class GenericSettingsAnalytics private constructor(context : Context) {
private val tracker = GoogleAnalytics.getInstance(context).newTracker(R.xml.global_tracker)
companion object {
private var instance : GenericSettingsAnalytics? = null
fun getInstance(context: Context) : GenericSettingsAnalytics {
if (instance == null) {
instance = GenericSettingsAnalytics(context)
instance!!.sendInitAnalytics(context)
}
return instance!!
}
}
fun sendEvent(category: String, action: String) {
tracker.send(HitBuilders.EventBuilder().setCategory(category).setAction(action).build())
}
fun sendInitAnalytics(context: Context) {
tracker.send(HitBuilders.EventBuilder()
.setCategory(ANALYTICS_CATEGORIES.CATEGORY_APP_INFO.categoryName)
.setAction(ANALYTICS_ACTIONS.ACTION_APP_INIT.actionName)
.setLabel(context.packageName)
.build())
}
}
Very simple one.
Everything works great in debug, but when uploading library to bintray (To use it's official compile) i'm getting the following exception:
FATAL EXCEPTION: main
Process: com.udioshi85.genericsettings, PID: 12398
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/analytics/GoogleAnalytics;
at com.oshi.libgenericsettings.GenericSettingsAnalytics.<init>(GenericSettingsAnalytics.kt:14)
at com.oshi.libgenericsettings.GenericSettingsAnalytics.<init>(GenericSettingsAnalytics.kt:12)
at com.oshi.libgenericsettings.GenericSettingsAnalytics$Companion.getInstance(GenericSettingsAnalytics.kt:22)
at com.oshi.libgenericsettings.GenericSettingsLib$Companion.initAnalytics(GenericSettingsLib.kt:20)
at com.oshi.libgenericsettings.GenericSettingsLib$Companion.init(GenericSettingsLib.kt:16)
at com.oshi.genericsettings.GenericSettingsApp.onCreate(GenericSettingsApp.kt:10)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5827)
at android.app.ActivityThread.-wrap1(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1673)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:172)
at android.app.ActivityThread.main(ActivityThread.java:6637)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.analytics.GoogleAnalytics"
Some thougts:
In my library build.gradle i'm adding the following classpath:
buildscript {
....
dependencies {
classpath 'com.google.gms:google-services:3.1.0'
}
}
Is it correct?
Most common libraries counts on their users to init the library from an application class. Something like
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
MyLibrary.init(this)
}
}
I've tried it already. but still getting the same exception. Maybe i'm doing something wrong?
Last thing, I've seen & read lots of examples on how to integrate GoogleAnalytics. The important thing is that my users should not add anything in their build.gradle except my compile/implementation library.
Would appreciate if someone can help me with that.
Thanks very much!
buildscript dependencies are the dependencies of your build script itself, not dependencies of your library. That is why it is not being included into your final build.
You can solve this issue by adding your classpath dependency to the application as well.
buildscript {
dependencies {
classpath 'com.google.gms:google-services:3.1.0'
}
}
Related
I get this build error:
Cannot process test roots and app roots in the same compilation unit:
When I am trying to write the instrumented test like this:
#HiltAndroidTest
class DataRecognitionRepositoryImplTest {
#get:Rule
var hiltRule = HiltAndroidRule(this)
#Test
fun first() {
}
}
I have also created my own runner like this:
class HiltTestRunner: AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
And set it like:
testInstrumentationRunner "com.mayurg.helpers.HiltTestRunner"
My root build file:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
classpath "com.google.dagger:hilt-android-gradle-plugin:2.40.5"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I have tried searching a lot but did not find anything useful apart from this: https://dagger.dev/hilt/flags
But I am not sure how/where to use these. Any help is appreciated.
To fix this you need to add this to your build.gradle file:
android {
defaultConfig {
javaCompileOptions.annotationProcessorOptions.arguments['dagger.hilt.disableCrossCompilationRootValidation'] = 'true'
}
}
I'm experimenting with Kotlin DSL but I can't get it to recognize objects I defined in buildSrc. They get resolved by the IDE but when I compile the code it doesn't work.
This is the my project structure:
build.gradle.kts
settings.gradle.kts
+buildSrc
build.gradle.kts
+src
+main
+java
Dependencies.kt
Versions.kt
+module1
build.gradle.kts
+module2
build.gradle.kts
Content of Dependencies.kt:
/**
* To define plugins
*/
object BuildPlugins {
val gradle by lazy { "com.android.tools.build:gradle:${Versions.gradlePlugin}" }
val kotlinGradle by lazy { "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" }
val safeArgs by lazy { "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.safeArgs}" }
}
/**
* To define dependencies
*/
object Deps {
val appCompat by lazy { "androidx.appcompat:appcompat:${Versions.appCompat}" }
val core by lazy { "androidx.core:core-ktx:${Versions.core}" }
val timber by lazy { "com.jakewharton.timber:timber:${Versions.timber}" }
val kotlin by lazy { "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}" }
val material by lazy { "com.google.android.material:material:${Versions.material}" }
val constraintLayout by lazy { "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}" }
}
Project wide build.gradle.kts (the one which fails first):
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
BuildPlugins.gradle
BuildPlugins.kotlinGradle
BuildPlugins.safeArgs
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
...
I also want to point out that the android { ... } block is not recognized in the modules gradle files but I think that may be because of the failed compilation.
You have Kotlin files under src/main/java. They should be in src/main/kotlin and you will need to include Kotlin build support in the buildSrc Gradle file (maybe you have this, you didn't show what's in buildSrc/build.gradle.kts)
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
I am trying to run the Signal app from Android studio, but I have the following error :
A problem occurred evaluating root project 'Signal'.
> Could not find method content() for arguments [build_ln9dya767x5ojwb6lu9wg470$_run_closure1$_closure2$_closure4$_closure5#1a6eaf53] on object of type org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository.
The concerned line is content and is found in the build.gradle file :
buildscript {
repositories {
google()
mavenCentral()
jcenter {
content {
includeVersion 'org.jetbrains.trove4j', 'trove4j', '20160824'
includeGroupByRegex "com\\.archinamon.*"
}
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
I am facing this issue when using coroutine with retrofit, can you please let me know why i am getting this error
java.lang.ClassNotFoundException: Didn't find class "kotlinx.coroutines.experimental.Deferred" on path: DexPathList[[zip file "/data/app/com.coroutines.retrofit.kotlin-1/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
while i am using the below dependencies,
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
and the kotlin version is :
ext.kotlin_version = '1.3.10'
Add this dependency in your build.gradle : (remove experimental dependency for coroutine)
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
}
And add CoroutineCallAdapterFactory() for retrofit
addCallAdapterFactory(CoroutineCallAdapterFactory())
I am facing the same problem, it is the Jake Warton's library problem. It is using experimental references internally.
Using implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0'
java.lang.NoClassDefFoundError: Failed resolution of: Lkotlinx/coroutines/experimental/Deferred;
at com.jakewharton.retrofit2.adapter.kotlin.coroutines.experimental.CoroutineCallAdapterFactory.get
This library is deprecated . Here is the solution from the library's page on git
This library is deprecated. Please migrate to Retrofit 2.6.0 or newer and its built-in suspend support
it works: (pay attention to jar task)
plugins {
application
kotlin("jvm") version "1.6.10"
}
group = "org.example"
version = "1.0-SNAPSHOT"
application {
mainClass.set("org.example.MainKt")
}
repositories {
mavenCentral()
}
dependencies {
implementation("io.ktor:ktor-client-core-jvm:1.6.7")
implementation("io.ktor:ktor-client-cio-jvm:1.6.7")
}
tasks {
jar {
manifest {
attributes["Main-Class"] = application.mainClass
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
configurations.compileClasspath.get().forEach {
from(if (it.isDirectory) it else zipTree(it))
}
}
compileKotlin {
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.ExperimentalStdlibApi"
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
I'm trying to add new TweetComposer to my project at module "app":
dependencies {
compile('com.twitter.sdk.android:tweet-composer:1.0.5#aar') {
transitive = true;
}
}
And I always got error like this:
Error:Could not find com.twitter.sdk.android:tweet-composer:1.0.5.
Required by:
reader-android:app:unspecified
Search in build.gradle files
I found the issue:
add at project level the following code
repositories {
jcenter()
maven { url 'https://maven.fabric.io/public' }
}
And at application level
dependencies {
compile('com.twitter.sdk.android:tweet-composer:1.0.5#aar') {
transitive = true;
}
}
You should then be able to sync Gradle correctly, let me know if that works for you!
Reference here