Context and Resource in Android Instrumented Unit Tests - android

I'm designing a system with some not-so-simple classes that require a Context object in order to initialize them. These classes make use of third party classes which also require context initialization. This class also utilizes the context to load a number of string resources necessary to the functionality.
The problem comes with writing Instrumented Unit tests for these classes. When I attempt to get a Context object for the test using InstrumentationRegistry.getContext(), I run into an exception where the context cannot find the string resources associated with the class (android.content.res.Resources$NotFoundException).
My question is this: How can I design these tests so that the context can retrieve the string resources that I need, and also act as suitable context objects for the third party classes? There's only so much mocking I can do as some of these classes handle auth tokens, which would be difficult to mock. I can't be the only person who's run into this issue in the Android domain, so I'm sure there's a common solution for this presumably common problem.
EDIT:
As suggested, I've tried integrating Robolectric (version 3.3.2) in my Project, however when I try and run my unit tests I'm met with the following error:
Error:Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been compiled using Java 8 or above.
If you are using the 'java' gradle plugin in a library submodule add
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
to that submodule's build.gradle file.
I've tried adding the targetCompatibility and sourceCompatibility lines to my gradle files (in several locations) to no avail.
Here's my mobile build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'checkstyle'
apply plugin: 'io.fabric'
project.ext {
supportLibVersion = '25.3.0'
multiDexSupportVersion = '1.0.1'
gsonVersion = '2.8.0'
retrofitVersion = '2.2.0'
daggerVersion = '2.4'
butterKnifeVersion = '8.5.1'
eventBusVersion = '3.0.0'
awsCoreServicesVersion = '2.2.+'
twitterKitVersion = '2.3.2#aar'
facebookVersion = '4.+'
crashlyticsVersion = '2.6.7#aar'
autoValueVersion = '1.2'
autoValueParcelVersion = '0.2.5'
autoValueGsonVersion = '0.4.4'
permissionDispatcher = '2.2.0'
testRunnerVersion = '0.5'
espressoVersion = '2.2.2'
junitVersion = '4.12'
roboelectricVersion = '3.3.2'
}
def gitSha = exec('git rev-parse --short HEAD', "unknown");
def gitCommitCount = 100 + Integer.parseInt(exec('git rev-list --count HEAD', "-1"))
def gitTag = exec('git describe --tags', stringify(gitCommitCount))
def gitTimestamp = exec('git log -n 1 --format=%at', -1)
def appId = "com.example.myapp"
def isCi = "true".equals(System.getenv("CI"))
// Uncomment if you wish to enable Jack & Java8
// apply from: 'jack.gradle'
// Uncomment if you wish to enable Sonar
//apply from: 'sonar.gradle'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId appId
minSdkVersion 16
targetSdkVersion 25
multiDexEnabled = true
versionCode gitCommitCount
versionName gitTag
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildConfigField 'String', 'GIT_SHA', "\"${gitSha}\""
buildConfigField 'long', 'GIT_TIMESTAMP', "${gitTimestamp}L"
}
buildTypes {
debug {
applicationIdSuffix '.debug'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
qa.initWith(buildTypes.release)
qa {
applicationIdSuffix '.qa'
debuggable true
}
}
lintOptions {
abortOnError false
}
applicationVariants.all { variant ->
def strictMode = !variant.name.equals("release")
buildConfigField 'boolean', 'STRICT_MODE_ENABLED', "${strictMode}"
}
}
configurations.all {
resolutionStrategy {
force "com.android.support:support-annotations:$supportLibVersion"
force "com.squareup.okhttp3:okhttp:3.4.1"
force "com.squareup:okio:1.9.0"
force "com.google.guava:guava:19.0"
}
}
dependencies {
compile "com.android.support:appcompat-v7:$supportLibVersion"
compile "com.android.support:design:$supportLibVersion"
compile "com.android.support:recyclerview-v7:$supportLibVersion"
compile "com.android.support:cardview-v7:$supportLibVersion"
compile "com.android.support:multidex:$multiDexSupportVersion"
compile "com.squareup.retrofit2:retrofit:$retrofitVersion"
compile "com.squareup.retrofit2:converter-gson:$retrofitVersion"
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
provided 'javax.annotation:jsr250-api:1.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.jakewharton.timber:timber:4.3.1'
compile "com.jakewharton:butterknife:$butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
compile "org.greenrobot:eventbus:$eventBusVersion"
annotationProcessor "org.greenrobot:eventbus:$eventBusVersion"
compile 'io.reactivex.rxjava2:rxandroid:2.0.0'
debugCompile 'com.squareup.okhttp3:logging-interceptor:3.4.2'
compile "com.google.auto.value:auto-value:$autoValueVersion"
annotationProcessor "com.google.auto.value:auto-value:$autoValueVersion"
compile "com.ryanharter.auto.value:auto-value-parcel-adapter:$autoValueParcelVersion"
annotationProcessor "com.ryanharter.auto.value:auto-value-parcel:$autoValueParcelVersion"
compile "com.github.hotchemi:permissionsdispatcher:$permissionDispatcher"
annotationProcessor "com.github.hotchemi:permissionsdispatcher-processor:$permissionDispatcher"
compile("com.crashlytics.sdk.android:crashlytics:$crashlyticsVersion") {
transitive = true;
}
compile("com.twitter.sdk.android:twitter:$twitterKitVersion") {
transitive = true
}
compile "com.facebook.android:facebook-android-sdk:$facebookVersion"
compile "com.amazonaws:aws-android-sdk-core:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-core:$awsCoreServicesVersion"
compile "com.amazonaws:aws-android-sdk-apigateway-core:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-apigateway-core:$awsCoreServicesVersion"
compile "com.amazonaws:aws-android-sdk-cognito:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-cognito:$awsCoreServicesVersion"
compile "com.amazonaws:aws-android-sdk-cognitoidentityprovider:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-cognitoidentityprovider:$awsCoreServicesVersion"
compile "com.amazonaws:aws-android-sdk-lambda:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-lambda:$awsCoreServicesVersion"
compile "com.amazonaws:aws-android-sdk-sns:$awsCoreServicesVersion"
annotationProcessor "com.amazonaws:aws-android-sdk-sns:$awsCoreServicesVersion"
androidTestCompile "junit:junit:$junitVersion"
androidTestCompile "com.android.support.test:runner:$testRunnerVersion"
androidTestCompile "com.android.support.test:rules:$testRunnerVersion"
androidTestCompile "com.android.support.test.espresso:espresso-intents:$espressoVersion"
androidTestCompile "com.android.support.test.espresso:espresso-core:$espressoVersion"
androidTestCompile "com.squareup.retrofit2:retrofit-mock:$retrofitVersion"
androidTestCompile "org.robolectric:robolectric:$roboelectricVersion"
testCompile "junit:junit:$junitVersion"
testCompile 'com.google.truth:truth:0.30'
testCompile 'org.hamcrest:hamcrest-all:1.3'
testCompile "org.robolectric:robolectric:$roboelectricVersion"
}
task checkCodingStyle(type: Checkstyle) {
description 'Runs Checkstyle inspection against Android sourcesets.'
group = 'Code Quality'
ignoreFailures = false
showViolations = false
source 'src'
include '**/*.java'
exclude '**/gen/**'
exclude '**/R.java'
exclude '**/BuildConfig.java'
reports {
xml.destination "$project.buildDir/reports/checkstyle/report.xml"
}
classpath = files()
configFile = file("${rootProject.rootDir}/config/checkstyle/checkstyle.xml")
}
def stringify(int versionCode) {
def builder = new StringBuilder();
def dot = ""
String.format("%03d", versionCode).toCharArray().each {
builder.append(dot)
builder.append(it)
dot = "."
}
return builder.toString()
}
def exec(String command, Object fallback = null) {
def cmd = command.execute([], project.rootDir)
cmd.waitFor()
if (cmd.exitValue() != 0) {
if (fallback == null) {
throw new RuntimeException("'$command' failed: $cmd.errorStream.text")
} else {
return fallback
}
}
return cmd.text.trim()
}
if (isCi) {
build.finalizedBy(checkCodingStyle)
}

The accepted answer is not the actual solution. There are many cases when you want to test your interaction with a real Android framework. Robolectric, as any other stub, may hide some actual issues.
Your problem is that you use InstrumentationRegistry.getContext() that is not the same that your app uses. According to docs:
Return the Context of this instrumentation's package.
And you should have used InstrumentationRegistry.getTargetContext() instead:
Return a Context for the target application being instrumented.
Because it, in the contrary to the first, will have access to your resourses.

Related

Program type already present: android.support.compat.R$attr

My project has two modules i.e. app and moduleX.
app project is mostly built on Java and moduleX is completly in Kotlin.
While creating "debug" build, it's running fine but when I try to create release build i.e. devRelease, it give following error-
* What went wrong:
Execution failed for task ':app:transformDexArchiveWithDexMergerForDevRelease'.
> com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
Program type already present: android.support.compat.R$attr
Here is the app level build.gradle-
apply plugin: 'com.android.application'
apply plugin: 'com.facebook.testing.screenshot'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "com.appname"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner rootProject.ext.testInstrumentationRunner
}
flavorDimensions "environment"
productFlavors {
dev {
dimension "environment"
versionNameSuffix "-dev"
applicationIdSuffix ".dev"
}
qa {
dimension "environment"
versionNameSuffix "-test"
applicationIdSuffix ".test"
}
staging {
dimension "environment"
versionNameSuffix "-staging"
applicationIdSuffix ".staging"
}
prod {
dimension "environment"
}
}
signingConfigs {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
release {
storeFile file("keystore/appname_keystore.jks")
storePassword properties.getProperty('storePassword')
keyAlias properties.getProperty('keyAlias')
keyPassword properties.getProperty('keyPassword')
}
}
buildTypes {
debug {
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
bundle {
language {
enableSplit = false
}
}
configurations.all {
resolutionStrategy {
// force certain versions of dependencies (including transitive)
force 'com.squareup.okhttp3:okhttp:' + okHttpLibVersion
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//Unit testing
testImplementation rootProject.ext.junit
androidTestImplementation rootProject.ext.androidTestRunner
androidTestImplementation rootProject.ext.espresso
testImplementation rootProject.ext.mockito
testImplementation rootProject.ext.facebookScreenshotTestCommon
implementation rootProject.ext.facebookScreenshotTestLitho
androidTestImplementation rootProject.ext.supportTestRules
//Support Library & UI
implementation rootProject.ext.constraintLayout
implementation rootProject.ext.supportCompatV7
implementation rootProject.ext.supportDesign
implementation rootProject.ext.supportCardView
implementation rootProject.ext.supportCustomTabs
implementation rootProject.ext.glide
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
// Dagger dependency for DI
implementation 'com.google.dagger:dagger:2.16'
annotationProcessor "com.google.dagger:dagger-compiler:2.16"
compileOnly 'javax.annotation:jsr250-api:1.0'
implementation 'javax.inject:javax.inject:1'
// RxJava lib
implementation rootProject.ext.rxAndroid
implementation rootProject.ext.rxJava
implementation rootProject.ext.rxJavaRetrofitAdapter
//Retrofit
implementation(rootProject.ext.retrofit) {
exclude module: 'okhttp'
}
implementation rootProject.ext.okHttp
implementation rootProject.ext.okHttpLoggingInterceptor
implementation rootProject.ext.retrofitGsonConverter
implementation rootProject.ext.retrofitScalarsConverter
//Memory leaks
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
//Others
implementation rootProject.ext.parceler
annotationProcessor rootProject.ext.parcelerAnnotationProcessor
implementation rootProject.ext.lombok
annotationProcessor rootProject.ext.lombokAnnotationProcessor
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
// Fingerprint Auth
implementation 'com.multidots:fingerprint-auth:1.0.1'
//Module Projects
api project(':energyswitchcui')
}
screenshots {
multipleDevices true
}
and here is the build.gradle file of moduleX-
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
// need separate runner for facebook screenshot test in module
testInstrumentationRunner 'com.appname.SnapshotTestRunner'
}
flavorDimensions "environment"
productFlavors {
dev {
dimension "environment"
}
qa {
dimension "environment"
}
staging {
dimension "environment"
}
prod {
dimension "environment"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
test.java.srcDirs += 'src/test/kotlin'
androidTest.java.srcDirs += 'src/androidTest/kotlin'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//Unit testing
testImplementation rootProject.ext.junit
androidTestImplementation rootProject.ext.androidTestRunner
androidTestImplementation rootProject.ext.espresso
testImplementation rootProject.ext.mockito
testImplementation rootProject.ext.facebookScreenshotTestCommon
implementation rootProject.ext.facebookScreenshotTestLitho
androidTestImplementation rootProject.ext.supportTestRules
//Support Library & UI
implementation rootProject.ext.constraintLayout
implementation rootProject.ext.supportCompatV7
implementation rootProject.ext.supportDesign
implementation rootProject.ext.supportCardView
implementation rootProject.ext.supportCustomTabs
implementation rootProject.ext.glide
implementation 'com.intuit.sdp:sdp-android:1.0.6'
// RxJava lib
implementation rootProject.ext.rxAndroid
implementation rootProject.ext.rxJava
implementation rootProject.ext.rxJavaRetrofitAdapter
//Retrofit
implementation(rootProject.ext.retrofit) {
exclude module: 'okhttp'
}
implementation rootProject.ext.okHttp
implementation rootProject.ext.okHttpLoggingInterceptor
implementation rootProject.ext.retrofitGsonConverter
implementation rootProject.ext.retrofitScalarsConverter
//Others
implementation rootProject.ext.parceler
kapt rootProject.ext.parcelerAnnotationProcessor
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
}
repositories {
mavenCentral()
}
// need for facebook screenshot test in module
apply plugin: 'com.facebook.testing.screenshot'
screenshots {
multipleDevices true
}
This is the project level build.gradle file-
apply from: 'dependencies.gradle'
buildscript {
ext.kotlinVersion = '1.3.30'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.facebook.testing.screenshot:plugin:0.8.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
This is dependencies.gradle-
ext {
//Android
minSdkVersion = 24
targetSdkVersion = 28
compileSdkVersion = targetSdkVersion
testInstrumentationRunner = "com.appname.runner.SnapshotTestRunner"
androidSupportLibVersion = "28.0.0"
okHttpLibVersion = "3.14.0"
//Unit testing
junit = "junit:junit:4.12"
androidTestRunner = "com.android.support.test:runner:1.0.2"
espresso = "com.android.support.test.espresso:espresso-core:3.0.2"
mockito = "org.mockito:mockito-all:1.10.19"
facebookScreenshotTestCommon = "com.facebook.testing.screenshot:layout-hierarchy-common:0.8.0"
facebookScreenshotTestLitho = "com.facebook.testing.screenshot:layout-hierarchy-litho:0.8.0"
supportTestRules = "com.android.support.test:rules:1.0.2"
//Support Library & UI
constraintLayout = "com.android.support.constraint:constraint-layout:1.1.3"
supportCompatV7 = "com.android.support:appcompat-v7:$androidSupportLibVersion"
supportDesign = "com.android.support:design:$androidSupportLibVersion"
supportCardView = "com.android.support:cardview-v7:$androidSupportLibVersion"
supportCustomTabs = "com.android.support:customtabs:$androidSupportLibVersion"
glide = "com.github.bumptech.glide:glide:3.7.0"
// RxJava lib
rxAndroid = "io.reactivex.rxjava2:rxandroid:2.0.1"
rxJava = "io.reactivex.rxjava2:rxjava:2.1.8"
rxJavaRetrofitAdapter = "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0"
//Retrofit
retrofit = "com.squareup.retrofit2:retrofit:2.4.0"
okHttp = "com.squareup.okhttp3:okhttp:$okHttpLibVersion"
okHttpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:$okHttpLibVersion"
retrofitGsonConverter = "com.squareup.retrofit2:converter-gson:2.3.0"
retrofitScalarsConverter = "com.squareup.retrofit2:converter-scalars:2.3.0"
//Others
parceler = "org.parceler:parceler-api:1.1.6"
parcelerAnnotationProcessor = "org.parceler:parceler:1.1.6"
lombok = "org.projectlombok:lombok:1.16.16"
lombokAnnotationProcessor = "org.projectlombok:lombok:1.16.16"
}
I have already tried many answers i.e.
Error : Program type already present: android.support.design.widget.CoordinatorLayout$Behavior
but nothing is working here.
Hi i have come up with the solution and run successful below gradles with just little version changes:
Main Project Level Gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.30'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.facebook.testing.screenshot:plugin:0.8.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
//Android
minSdkVersion = 24
targetSdkVersion = 28
compileSdkVersion = targetSdkVersion
testInstrumentationRunner = "com.appname.runner.SnapshotTestRunner"
androidSupportLibVersion = "28.0.0"
androidCompatVersion = "1.0.0-beta01"
androidCardViewVersion = "1.0.0"
constraintlayoutVersion = "1.1.3"
okHttpLibVersion = "3.14.0"
//Unit testing
junit = "junit:junit:4.12"
androidTestRunner = "androidx.test:runner:1.1.0-alpha4"
espresso = "androidx.test.espresso:espresso-core:3.1.0-alpha4"
supportTestRules = "com.android.support.test:rules:1.0.2"
//Support Library & UI
constraintLayout = "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion"
supportCompatV7 = "androidx.appcompat:appcompat:$androidCompatVersion"
supportDesign = "com.android.support:design:$androidSupportLibVersion"
supportCardView = "androidx.cardview:cardview:$androidCardViewVersion"
supportCustomTabs = "com.android.support:customtabs:$androidSupportLibVersion"
glide = "com.github.bumptech.glide:glide:3.7.0"
mockito = "org.mockito:mockito-all:1.10.19"
facebookScreenshotTestCommon = "com.facebook.testing.screenshot:layout-hierarchy-common:0.8.0"
facebookScreenshotTestLitho = "com.facebook.testing.screenshot:layout-hierarchy-litho:0.8.0"
// RxJava lib
rxAndroid = "io.reactivex.rxjava2:rxandroid:2.0.1"
rxJava = "io.reactivex.rxjava2:rxjava:2.1.8"
rxJavaRetrofitAdapter = "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0"
//Retrofit
retrofit = "com.squareup.retrofit2:retrofit:2.4.0"
okHttp = "com.squareup.okhttp3:okhttp:$okHttpLibVersion"
okHttpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:$okHttpLibVersion"
retrofitGsonConverter = "com.squareup.retrofit2:converter-gson:2.3.0"
retrofitScalarsConverter = "com.squareup.retrofit2:converter-scalars:2.3.0"
//Others
parceler = "org.parceler:parceler-api:1.1.9"
parcelerAnnotationProcessor = "org.parceler:parceler:1.1.9"
lombok = "org.projectlombok:lombok:1.16.16"
lombokAnnotationProcessor = "org.projectlombok:lombok:1.16.16"
}
App Level gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.example.gradletest"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testImplementation rootProject.ext.junit
androidTestImplementation rootProject.ext.androidTestRunner
androidTestImplementation rootProject.ext.espresso
androidTestImplementation rootProject.ext.supportTestRules
testImplementation rootProject.ext.mockito
testImplementation rootProject.ext.facebookScreenshotTestCommon
implementation rootProject.ext.facebookScreenshotTestLitho
implementation rootProject.ext.constraintLayout
implementation rootProject.ext.supportCompatV7
implementation rootProject.ext.supportDesign
implementation rootProject.ext.supportCardView
implementation rootProject.ext.supportCustomTabs
implementation rootProject.ext.glide
// RxJava lib
implementation rootProject.ext.rxAndroid
implementation rootProject.ext.rxJava
implementation rootProject.ext.rxJavaRetrofitAdapter
//Retrofit
implementation(rootProject.ext.retrofit) {
exclude module: 'okhttp'
}
implementation rootProject.ext.okHttp
implementation rootProject.ext.okHttpLoggingInterceptor
implementation rootProject.ext.retrofitGsonConverter
implementation rootProject.ext.retrofitScalarsConverter
implementation rootProject.ext.parceler
// annotationProcessor rootProject.ext.parcelerAnnotationProcessor
implementation rootProject.ext.lombok
annotationProcessor rootProject.ext.lombokAnnotationProcessor
//Memory leaks
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.multidots:fingerprint-auth:1.0.1'
implementation project(':energyswitchcui')
}
Module("energyswitchcui") gradle:
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//Unit testing
testImplementation rootProject.ext.junit
androidTestImplementation rootProject.ext.androidTestRunner
androidTestImplementation rootProject.ext.espresso
testImplementation rootProject.ext.mockito
testImplementation rootProject.ext.facebookScreenshotTestCommon
implementation rootProject.ext.facebookScreenshotTestLitho
androidTestImplementation rootProject.ext.supportTestRules
//Support Library & UI
implementation rootProject.ext.constraintLayout
implementation rootProject.ext.supportCompatV7
implementation rootProject.ext.supportDesign
implementation rootProject.ext.supportCardView
implementation rootProject.ext.supportCustomTabs
implementation rootProject.ext.glide
implementation 'com.intuit.sdp:sdp-android:1.0.6'
// RxJava lib
implementation rootProject.ext.rxAndroid
implementation rootProject.ext.rxJava
implementation rootProject.ext.rxJavaRetrofitAdapter
//Retrofit
implementation(rootProject.ext.retrofit) {
exclude module: 'okhttp'
}
implementation rootProject.ext.okHttp
implementation rootProject.ext.okHttpLoggingInterceptor
implementation rootProject.ext.retrofitGsonConverter
implementation rootProject.ext.retrofitScalarsConverter
//Others
implementation rootProject.ext.parceler
// kapt rootProject.ext.parcelerAnnotationProcessor
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
repositories {
mavenCentral()
}
// need for facebook screenshot test in module
apply plugin: 'com.facebook.testing.screenshot'
screenshots {
multipleDevices true
}
Below are the errors that were encountered during gradle and what i have done to solve it:
1) Error: Invoke-customs are only supported starting with Android O (--min-api 26)
Solution: put below lines under android section of app level gradle
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
2) Error: The given artifact contains a string literal with a package reference 'android.support.v4.widget' that cannot be safely rewritten. Libraries using reflection such as annotation processors need to be updated manually to add support for androidx.
Solution: Removed "annotationProcessor rootProject.ext.parcelerAnnotationProcessor" from app level gradle and updated this library in main level gradle under "ext" section from 1.1.6 to 1.1.9 'parcelerAnnotationProcessor = "org.parceler:parceler:1.1.9"'
but it does not worked
So i removed that library and successfully build gradle and also can run the project. Here is the dropbox link you can find project on :https://www.dropbox.com/s/ki8gpfdaxh0dzo3/GradleTest.zip?dl=0
3) Above solution will work only in debug mode but in release build we have to also remove this two libraries to build successfully in release build:
facebookScreenshotTestCommon = "com.facebook.testing.screenshot:layout-hierarchy-common:0.9.0"
facebookScreenshotTestLitho = "com.facebook.testing.screenshot:layout-hierarchy-litho:0.9.0"

Multidex app still over 64K method limit

I'm facing a weird issue with multidex. I've had my app multidexed for a long time, but lately I can't build it anymore. It started after configuring Kotlin in the project.
The 'run' option in Android Studio works: the app runs successfully in my device. However, if I try the "Build APK" option or run gradlew assembleDebug, the build fails with the usual exception:
Error:The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
Error:com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
However, multidex worked correctly before adding Kotlin. I can checkout the commit just before adding Kotlin, build the apk and check there's 3 .dex files, with a method count over 100k total.
Some key details:
Gradle 4.1, with Gradle plugin 3.0.1
Build-tools version 26.0.2
Kotlin version 1.2.0
After proguarding, the app does not need multidex, but I don't really want to proguard for debug compilation, and besides, this should be working.
Here's the complete build.gradle script:
buildscript {
repositories {
mavenCentral()
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'idea'
repositories {
mavenCentral()
jcenter()
maven { url "https://maven.google.com" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url 'https://jitpack.io' }
}
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}
// read keystore for app signing
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = null
if (keystorePropertiesFile.exists()) {
keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
def getDate() {
def date = new Date()
def formattedDate = date.format('yyyy.MM.dd')
return formattedDate
}
def getCustomProguardFiles() {
return fileTree(dir: "proguard", include: ["*.pro"]).asList().toArray()
}
android {
compileSdkVersion 25
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
applicationId "my.app.id"
multiDexEnabled true
manifestPlaceholders = [
'appAuthRedirectScheme': 'my.app.id'
]
//TODO do not put this into release
resValue "string", "google_client_id", google_appId + ".apps.googleusercontent.com"
resValue "string", "google_auth_redirect_uri", "com.googleusercontent.apps." + google_appId + ":/oauth2redirect"
}
dexOptions {
}
dexOptions {
javaMaxHeapSize "2g"
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
signingConfigs {
release {
keyAlias keystoreProperties != null ? keystoreProperties['keyAlias'] : null
keyPassword keystoreProperties != null ? keystoreProperties['keyPassword'] : null
storeFile keystoreProperties != null ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties != null ? keystoreProperties['storePassword'] : null
}
}
lintOptions {
abortOnError false
checkReleaseBuilds false
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt')
proguardFiles getCustomProguardFiles()
testProguardFiles getDefaultProguardFile('proguard-android.txt')
testProguardFiles getCustomProguardFiles()
signingConfig signingConfigs.release
}
debug {
debuggable true
minifyEnabled false
}
}
flavorDimensions "buildType"
productFlavors {
develop {
applicationIdSuffix ""
dimension "buildType"
}
product {
dimension "buildType"
}
ci {
dimension "buildType"
}
}
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
compileOptions.incremental = false
}
dependencies {
/********** DEBUGGING **********/
// Chrome debug bridge
compile 'com.facebook.stetho:stetho:1.5.0'
compile 'com.facebook.stetho:stetho-okhttp3:1.5.0'
// Memory leak debugging
// 1.5.2 held back because of a bug with gradle 3.0
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
androidTestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
/********** SUPPORT **********/
// Multidex support
compile 'com.android.support:multidex:1.0.2'
// Support libs
compile "com.android.support:appcompat-v7:$libVersions.android.support"
compile "com.android.support:cardview-v7:$libVersions.android.support"
compile "com.android.support:customtabs:$libVersions.android.support"
compile "com.android.support:design:$libVersions.android.support"
compile "com.android.support:gridlayout-v7:$libVersions.android.support"
compile "com.android.support:palette-v7:$libVersions.android.support"
compile "com.android.support:preference-v7:$libVersions.android.support"
compile "com.android.support:recyclerview-v7:$libVersions.android.support"
compile "com.android.support:support-annotations:$libVersions.android.support"
compile "com.android.support:support-v4:$libVersions.android.support"
compile "com.android.support:support-v13:$libVersions.android.support"
// Testing dependencies
// Made explicit to avoid conflicts with other testing libs
androidTestCompile "com.android.support:appcompat-v7:$libVersions.android.support"
androidTestCompile "com.android.support:design:$libVersions.android.support"
androidTestCompile "com.android.support:recyclerview-v7:$libVersions.android.support"
androidTestCompile "com.android.support:support-annotations:$libVersions.android.support"
androidTestCompile "com.android.support:support-v4:$libVersions.android.support"
/********** TESTING **********/
// JUnit
testCompile 'junit:junit:4.12'
// Mockito
testCompile "org.mockito:mockito-core:2.8.47"
// Support testing
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.0'
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.0'
androidTestCompile 'com.android.support.test:rules:1.0.0'
androidTestCompile 'com.android.support.test:runner:1.0.0'
/********** UTILITIES **********/
// HTML parsing
compile 'org.jsoup:jsoup:1.10.2'
// Event bus
compile 'org.greenrobot:eventbus:3.0.0'
// FHIR
compile 'ca.uhn.hapi.fhir:hapi-fhir-android:3.1.0'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0'
// Jobs
compile 'com.evernote:android-job:1.1.11'
// JSON serializing-deserializing
compile 'com.google.code.gson:gson:2.8.1'
// JWT validation
compile 'com.nimbusds:nimbus-jose-jwt:4.41.1'
// Lang utilities
// Used for Levenshtein distance, etc
compile 'org.apache.commons:commons-lang3:3.6'
compile 'org.apache.commons:commons-text:1.1'
// OpenID authentication
compile 'net.openid:appauth:0.7.0'
// QR code scanning
compile 'com.google.zxing:core:3.3.0'
compile 'com.journeyapps:zxing-android-embedded:3.5.0#aar'
// Play Services (for Firebase InstanceID)
compile 'com.google.android.gms:play-services-auth:11.6.0'
// Recurrence processing
compile 'org.dmfs:lib-recur:0.10'
// REST services
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
// SQLite ORM
compile 'com.j256.ormlite:ormlite-android:5.0'
// Time and date handling
compile 'com.fatboyindustrial.gson-jodatime-serialisers:gson-jodatime-serialisers:1.6.0'
compile 'joda-time:joda-time:2.9.7'
// View/resource binding
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'com.jakewharton:butterknife:8.8.1'
/********** VIEWS AND VIEW UTILITIES **********/
// About page with libraries
compile('com.mikepenz:aboutlibraries:5.2.5#aar') {
transitive = true
}
// Calendar views
compile 'com.roomorama:caldroid:3.0.1'
compile 'com.squareup:android-times-square:1.6.4#aar'
// Circular progress "pie" view
// Used for pill picker
compile 'com.github.filippudak.progresspieview:library:1.0.4'
// Dialogs with material style
compile 'com.github.javiersantos:MaterialStyledDialogs:2.0'
// Floating Action Button
compile 'com.getbase:floatingactionbutton:1.9.0'
// GIF ImageView
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'
// Icons
compile 'com.mikepenz:community-material-typeface:1.9.32.2#aar'
compile 'com.mikepenz:google-material-typeface:2.1.2.1#aar'
compile 'com.mikepenz:iconics-core:2.7.1#aar'
// Image loading
compile 'com.squareup.picasso:picasso:2.5.2'
// Intro slides
compile 'com.heinrichreimersoftware:material-intro:1.5.8'
// Material style utilities
compile('com.mikepenz:materialize:0.2.7#aar') {
transitive = true
}
// Picker DialogFragments
compile 'com.code-troopers.betterpickers:library:3.1.0'
// Round image view
compile 'com.makeramen:roundedimageview:1.5.0'
// Tab strip
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
// Sliding left drawer
compile('com.mikepenz:materialdrawer:4.4.1#aar') {
transitive = true
}
// Recyclerview adapters
compile('com.mikepenz:fastadapter:2.1.5#aar') {
transitive = true
}
compile 'com.mikepenz:fastadapter-commons:2.1.0#aar'
compile 'com.mikepenz:fastadapter-extensions:2.1.0#aar'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Schedule step-by-step building
compile 'com.stepstone.stepper:material-stepper:3.3.0'
compile 'com.wdullaer:materialdatetimepicker:3.2.2'
compile 'com.shawnlin:number-picker:2.4.4'
}
apply plugin: 'com.google.gms.google-services'
And the build.gradle of the project:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.2.0'
repositories {
jcenter()
maven { url "https://maven.google.com" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:3.0.0'
}
ext {
libVersions = [
android: [
support: '25.4.0'
]
]
}
}
It turned out to be a problem with the way I was including HAPI-FHIR. It's a really big library with tons of dependencies, and it probably was collapsing the main dexfile.
In the end, I solved it by replacing:
// FHIR
compile 'ca.uhn.hapi.fhir:hapi-fhir-android:3.1.0'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0'
with:
// FHIR
compile 'ca.uhn.hapi.fhir:hapi-fhir-base:3.1.0#jar'
compile 'ca.uhn.hapi.fhir:hapi-fhir-utilities:3.1.0#jar'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0#jar'
compile 'commons-io:commons-io:2.5'
compile 'org.slf4j:slf4j-api:1.7.25#jar'
commons-io and slf4j are runtime dependencies of HAPI, and when using #jar those dependencies aren't downloaded, so they need to be explicitly declared.
Note: this particular configuration is only valid for my use case, as HAPI has more runtime dependencies, which would need to be added manually as well in case they're needed.

Android Studio Gradle not using transitive dependencies

Having experienced this problem in a separate project, I made a test project to verify the issue.
Opening Android Studio 3.0, I created a new basic project. Its main module was called app.
I added a library module, called libraryone.
In libraryone, I added a dependency to Gson, and added a single class with a single static method using Gson.
In app, I added a dependency to libraryone. I tested it plain, as well as with transitive = true, as the internet seemed to vaguely concur that doing so might help. (It did not.)
In app, in MainActivity, I used the class from libraryone. This worked (as long as I didn't have transitive = false set, instead).
However, I cannot reference Gson from MainActivity itself. It gives a "Cannot resolve symbol 'Gson'" error, both from Android Studio, as well as from the command line Gradle. This is...unusual and aggravating, as it means you have to repeat common dependencies all throughout a group of projects, and the classes are included in the output anyway. Surely either I'm doing something wrong, or this is a bug?
My code is as follows:
MainActivity.java (in app)
package com.erhannis.test.dependencytest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.erhannis.test.libraryone.LibClass;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String s = LibClass.convert(new Object());
System.out.println("out: " + s);
new com.google.gson.Gson(); // This line gives a compile-time error: "Cannot resolve symbol 'Gson'"
}
}
LibClass.java (in libraryone)
package com.erhannis.test.libraryone;
import com.google.gson.Gson;
public class LibClass {
public static String convert(Object o) {
Gson gson = new Gson();
return gson.toJson(o);
}
}
build.gradle (app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.erhannis.test.dependencytest"
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation (project(path: ':libraryone'))
}
build.gradle (libraryone)
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.google.code.gson:gson:2.8.2'
}
It is because you declared the transitive dependency as implementation. Use api instead of implementation change:
implementation 'com.google.code.gson:gson:2.8.2'
to:
api 'com.google.code.gson:gson:2.8.2'
The reason why you should declare the transitive dependency in your library can be found here
You are using:
implementation (project(path: ':libraryone'))
implementation 'com.google.code.gson:gson:2.8.2'
Check the official doc:
When your module configures an implementation dependency, it's letting Gradle know that the module does not want to leak the dependency to other modules at compile time. That is, the dependency is available to other modules only at runtime.
Here you can find a very good blog about it.
The best solution for this is to create a private Github/Gitlab repository for the aar dependency. You can also make it public if you want. The aar file does not contain transitive dependencies when used locally. We need to publish it somewhere with the .pom file. Here's how to do it,
create a personal access token in Github
Github -> Settings -> Developer Settings -> Personal Access token - with write:packages / read:packages access level
(create two tokens if you need to distribute privately
Add id 'maven-publish' to plugins in module level gradle
Add the below code to module level gradle
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
archiveClassifier.set("sources")
}
publishing {
publications {
bar(MavenPublication) {
groupId 'com.your'
artifactId 'artifact'
version '1.0'
artifact sourceJar
artifact("$buildDir/outputs/aar/YourLibraryName-release.aar")
pom.withXml {
final dependenciesNode = asNode().appendNode('dependencies')
ext.addDependency = { Dependency dep, String scope ->
if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
return
final dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
dependencyNode.appendNode('version', dep.version)
dependencyNode.appendNode('scope', scope)
if (!dep.transitive) {
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode('groupId', rule.group ?: '*')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
}
}
}
configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.api.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") }
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY")
credentials {
username = "GITHUB_USERID" // Better if you use env variable
password = "WRITE_ACCESS_TOKEN"
}
}
}
}
In the Gradle toolbar you can find publish under the publishing subdirectory in your library module directory. ( Make sure to build the aar from build->build in module directory before publish)
To use it in your project, add following to your app level gradle file inside android{ }tag
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY")
credentials {
username = "GITHUB_USERID" // Better if you use env variable
password = "READ_ACCESS_TOKEN"
}
}
}
Finally in dependencies
implementation 'com.your:artifact:1.0'
*Gitlab is also pretty similar to this

App with dependency to Google Play Services 11.0.0 not running on Android Studio emulators

I am using play services on Android to request periodic user locations. For that purpose, I added the following dependency on my app/build.gradle
compile "com.google.android.gms:play-services-location:11.0.0"
In physical devices it works pretty well. However, on emulators it does not work and it prompts to update play services.
I have tried different solutions according to following questions
How to update Google Play Services for Android Studio 2.2 emulators?
How to update Google Play Services on the emulator in Android Studio
https://android.stackexchange.com/questions/176578/how-to-use-google-maps-android-api-by-google-play-services-11-on-an-emulator-wit (it was marked as off-the-topic, but here the same problem is described)
I tried creating a new emulator with an x86_64 image with Google APIs, but that does not solve the problem.
I have also checked for updates on Android Studio (I have version 2.3.3) but it says the IDE is up to date.
How can I run Google Play Services V11.0.0 and above on emulators? Any help with this issue will be appreciated
EDIT:
Here is my app/build.gradle file
buildscript {
repositories {
jcenter()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
// These docs use an open ended version so that our plugin
// can be updated quickly in response to Android tooling updates
// We recommend changing it to the latest version from our changelog:
// https://docs.fabric.io/android/changelog.html#fabric-gradle-plugin
classpath 'io.fabric.tools:gradle:1.22.0'
classpath 'me.tatarka:gradle-retrolambda:3.6.1'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'me.tatarka.retrolambda'
repositories {
mavenCentral()
maven { url 'https://maven.fabric.io/public' }
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "xxxxxxxxxxxxxxxx"
minSdkVersion 19
targetSdkVersion 25
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
manifestPlaceholders = [fabric_io_id: "$System.env.FABRIC_KEY"]
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled = true
}
signingConfigs {
release {
try {
storeFile new File(STORE_FILE)
storePassword STORE_PASSWORD
keyAlias KEY_ALIAS
keyPassword KEY_PASSWORD
} catch (ex) {
throw new InvalidUserDataException("Signing configuration not found")
}
}
}
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
productFlavors {
development {
versionNameSuffix "-dev"
manifestPlaceholders = [
appName: "xxxx"
]
}
production {
manifestPlaceholders = [
appName: "xxxxxxxxxxxxx"
]
}
}
variantFilter { variant ->
def names = variant.flavors*.name
if ((names.contains("alpha") || names.contains("qatesting") || names.contains("sandbox") || names.contains("production"))
&& variant.buildType.name == "debug") {
variant.ignore = true
}
if (names.contains("development") && variant.buildType.name == "release") {
variant.ignore = true
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE-FIREBASE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/rxjava.properties'
}
}
ext {
supportLibraryVersion = '25.3.1'
butterKnifeVersion = '8.5.1'
leakCanaryVersion = '1.5.1'
daggerVersion = '2.10'
rxAndroidVersion = '2.0.1'
rxJavaVersion = '2.1.0'
timberVersion = '4.5.1'
jUnitVersion = '4.12'
mockitoVersion = '1.10.19'
testRunnerVersion = '0.5'
powerMockVersion = '1.6.2'
crashlyticsVersion = '2.6.8'
guavaVersion = '19.0'
googlePlayServicesVersion = '11.0.1'
contraintLayoutVersion = '1.0.2'
awsCognitoVersion = '2.4.3'
espressoVersion = '2.2.2'
retrofitVersion = '2.3.0'
jacksonConverterVersion = '2.1.0'
okHttpLoggingInterceptorVersion = '3.2.0'
firebaseJobDispatcherVersion = '0.6.0'
apacheCommonsVersion = '3.6'
multiDexVersion = '1.0.1'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.support:appcompat-v7:$supportLibraryVersion"
compile "com.android.support:design:$supportLibraryVersion"
compile "com.android.support:support-v4:$supportLibraryVersion"
/* Multidex */
compile "com.android.support:multidex:$multiDexVersion"
/* Views injection - Butterknife */
compile "com.jakewharton:butterknife:$butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
/* Memory leaks detection - LeakCanary */
debugCompile "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
testCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
/* Dependency Injection - Dagger*/
compile "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
/* Rx Android - Rx Java */
compile "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
compile "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
/* Application Logger - Timber*/
compile "com.jakewharton.timber:timber:$timberVersion"
/* Crashlytics - crash reporting */
compile("com.crashlytics.sdk.android:crashlytics:$crashlyticsVersion#aar") {
transitive = true;
}
/* Google analytics */
compile "com.android.support.constraint:constraint-layout:$contraintLayoutVersion"
compile "com.google.android.gms:play-services-analytics:$googlePlayServicesVersion"
compile "com.google.guava:guava:$guavaVersion"
compile "com.android.support:support-v4:$supportLibraryVersion"
/* Google play location services */
compile "com.google.android.gms:play-services-location:$googlePlayServicesVersion"
/* Amazon cognito */
compile "com.amazonaws:aws-android-sdk-cognitoidentityprovider:$awsCognitoVersion"
/* Retrofit - API rest access*/
compile "com.squareup.retrofit2:retrofit:$retrofitVersion"
/* Retrofit JSON converter with Jackson */
compile "com.squareup.retrofit2:converter-jackson:$jacksonConverterVersion"
/* Firebase job dispatcher */
compile "com.firebase:firebase-jobdispatcher:$firebaseJobDispatcherVersion"
/* Mapbox */
compile('com.mapbox.mapboxsdk:mapbox-android-sdk:5.0.2#aar') {
transitive = true
}
compile "com.google.android.gms:play-services-places:$googlePlayServicesVersion"
/* Apache commons */
compile "org.apache.commons:commons-lang3:$apacheCommonsVersion"
/* Android testing */
testCompile "junit:junit:$jUnitVersion"
testCompile "org.mockito:mockito-core:$mockitoVersion"
androidTestCompile("com.android.support.test.espresso:espresso-core:$espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile "com.android.support.test:runner:$testRunnerVersion"
androidTestCompile "com.android.support:support-annotations:$supportLibraryVersion"
testCompile "org.powermock:powermock-api-mockito:$powerMockVersion"
testCompile "org.powermock:powermock-module-junit4-rule-agent:$powerMockVersion"
testCompile "org.powermock:powermock-module-junit4-rule:$powerMockVersion"
testCompile "org.powermock:powermock-module-junit4:$powerMockVersion"
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.8.8'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.8'
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.8'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.android.support:support-v4:25.3.1'
}
Google released emulator images featuring the whole Google Play Store. Those should be able to get the most recent version of the PlayServices via the Play Store.
EDIT: Virtual Device Manager - Screenshot

Databinding fails with NoSuchMethodError

After updating to gradle 2.10 every time when I try to assemble debug build of the app I get the NoSuchMethodError exception. Here is the relevant part of the build log:
java.lang.RuntimeException: failure, see logs for details.
cannot generate view binders java.lang.NoSuchMethodError: com.google.common.base.Strings.isNullOrEmpty(Ljava/lang/String;)Z
at android.databinding.tool.util.StringUtils.capitalize(StringUtils.java:57)
at android.databinding.tool.util.ParserHelper.toClassName(ParserHelper.java:23)
at android.databinding.tool.store.ResourceBundle$LayoutFileBundle.getFullBindingClass(ResourceBundle.java:551)
at android.databinding.tool.store.ResourceBundle$LayoutFileBundle.getBindingClassPackage(ResourceBundle.java:541)
at android.databinding.tool.CompilerChef.pushClassesToAnalyzer(CompilerChef.java:124)
at android.databinding.tool.CompilerChef.createChef(CompilerChef.java:73)
at android.databinding.annotationprocessor.ProcessExpressions.writeResourceBundle(ProcessExpressions.java:148)
at android.databinding.annotationprocessor.ProcessExpressions.onHandleStep(ProcessExpressions.java:82)
at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.runStep(ProcessDataBinding.java:154)
at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.access$000(ProcessDataBinding.java:139)
at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:66)
As you can see Method com.google.common.base.Strings.isNullOrEmpty can't be found.
Some specifics
I use Retrolambda 3.2.5 and Java 8. There are no other extra plugins.
Build plugin version: com.android.tools.build:gradle:2.0.0
Build tools version: 23.0.3
OS: OS X
build.gradle looks like this. I altered it slightly to not expose some private stuff, but problem is still there.
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'me.tatarka:gradle-retrolambda:3.2.3'
}
}
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
project.version = '1.0.0'
afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = []
}
dx.additionalParameters += "--set-max-idx-number=50000" // default 60000
}
}
def googleApiKey = "key goes here"
def appVersionCode = 1
def appVersionName = project.version + "." + appVersionCode
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 15
targetSdkVersion 23
manifestPlaceholders = [googleApiKey : googleApiKey,
appVersionCode: appVersionCode,
appVersionName: appVersionName]
multiDexEnabled true
ndk {
abiFilters "armeabi", "armeabi-v7a"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
"App-${project.version}-${appVersionCode}.apk"
)
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
flavorDimensions "multidex", "leakcanary"
productFlavors {
withLeakCanary {
dimension "leakcanary"
}
withoutLeakCanary {
dimension "leakcanary"
}
develDex {
dimension "multidex"
minSdkVersion 21
targetSdkVersion 23
}
prodDex {
dimension "multidex"
minSdkVersion 15
targetSdkVersion 23
}
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/DEPENDENCIES'
}
lintOptions {
abortOnError false
}
sourceSets {
main {
jniLibs.srcDir 'build/jniLibs'
}
}
dexOptions {
javaMaxHeapSize "4g"
}
dataBinding {
enabled = true
}
}
task copyNativeLibs(type: Copy) {
from(new File(buildDir, 'intermediates/exploded-aar/')) {
include '**/*.so'
exclude '**/lib-detector.so'
}
into new File(buildDir, 'jniLibs')
eachFile { details ->
def pathSplit = details.path.split('/')
details.path = pathSplit[pathSplit.length - 2] + '/' + pathSplit[pathSplit.length - 1]
}
includeEmptyDirs = false
}
tasks.withType(JavaCompile) { javaCompileTask -> javaCompileTask.dependsOn copyNativeLibs }
clean.dependsOn 'cleanCopyNativeLibs'
dependencies {
testCompile 'junit:junit:4.11'
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.robolectric:shadows-multidex:3.0'
testCompile('org.robolectric:shadows-httpclient:3.0') {
exclude module: 'httpcore'
exclude module: 'commons-codec'
}
testCompile 'org.powermock:powermock-module-junit4:1.5.2'
testCompile 'org.powermock:powermock-api-mockito:1.5.2'
testCompile 'org.roboguice:roboguice:3.0.1'
compile 'com.parse.bolts:bolts-android:1.2.1'
compile fileTree(dir: 'libs', include: 'Parse-*.jar')
compile 'com.google.android.gms:play-services-drive:7.8.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:support-annotations:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.android.support:design:23.0.1'
compile 'org.roboguice:roboguice:3.0.1'
provided 'org.roboguice:roboblender:3.0.1'
compile('com.google.inject.extensions:guice-assistedinject:3.0') {
exclude group: 'com.google.inject', module: 'guice'
}
compile 'commons-io:commons-io:2.4'
compile 'commons-lang:commons-lang:2.6'
compile 'com.intellij:annotations:12.0'
compile 'com.google.zxing:core:3.2.1'
compile 'com.google.zxing:android-core:3.2.1'
compile 'com.google.android.gms:play-services-base:7.8.0'
compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-maps:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
compile 'com.amazon:in-app-purchasing:2.0.1'
compile 'com.googlecode.libphonenumber:libphonenumber:7.0.7'
withLeakCanaryCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
compile 'com.google.android.gms:play-services-ads:7.8.0'
compile 'io.reactivex:rxandroid:1.0.1'
compile 'io.reactivex:rxjava:1.0.14'
}
Question
Did anyone else had the same problem? How to fix it? If you need some extra information, please let me know in comments.
Have you tried the new patch on jitpack of simular issue #134 clean-build, there seemed to be something wrong with gradle import ordering you can try it with :
repositories {
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.github.denis-itskovich:gradle-retrolambda:3.2.3-fix-134'
}
It looks like there is an error with a plugin after upgrading the Android Studio.
If you go in : <Android Studio Dir>/plugins/android/lib/builder-model-x.x.x.jar you may find 2 .jars. Try to delete the old version .jar and keep the new one and also clean and rebuild the project.
if the above does not work try this:
Change the version of Objectify library in the build.gradle file of your backend to 4.0b to 5.0.3 or higher if it exists.
This is may sound irrelevant but objectify 4.0b library has same classes with same package name which are present in appengine sdk like com.google.common.base.Strings.isNullOrEmpty.
when you deploy the app backend the appengine classes are overridden by objectify classes and hence when you try to call some method it is throwing error.
This is solved in objectify 5.0.+
Hope it helps as it helped me solving this issue.

Categories

Resources