I'm trying to add Espresso testing framework to my project. However, I'm stuck with this NoClassDefFoundError for 3 days. After searching over Google I found testing APK is using by default the DEBUG build type. For some reason I need to set Proguard on for debug build type. However, I get the following error when running my test configuration:
06-02 15:27:01.105 19436-19457/com.lingyue.YqgAndroid E/TestLoader: Could not find class: android.support.test.espresso.base.UiControllerModule_ProvideUiControllerFactory
06-02 15:27:01.107 19436-19457/com.lingyue.YqgAndroid I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.test.espresso.core.deps.dagger.internal.Factory>
06-02 15:27:01.107 19436-19457/com.lingyue.YqgAndroid I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.test.espresso.base.ViewFinderImpl_Factory>
06-02 15:27:01.107 19436-19457/com.lingyue.YqgAndroid I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.test.espresso.base.ViewFinderImpl_Factory>
06-02 15:27:01.109 19436-19457/com.lingyue.YqgAndroid E/TestLoader: Could not find class: android.support.test.espresso.base.ViewFinderImpl_Factory
06-02 15:27:01.114 19436-19457/com.lingyue.YqgAndroid I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.test.espresso.core.deps.dagger.internal.Factory>
06-02 15:27:01.115 19436-19457/com.lingyue.YqgAndroid E/AndroidRuntime: FATAL EXCEPTION: Instr: android.support.test.runner.AndroidJUnitRunner
Process: com.lingyue.YqgAndroid, PID: 19436
java.lang.NoClassDefFoundError: android.support.test.espresso.core.deps.dagger.internal.Factory
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:324)
at android.support.test.internal.runner.TestLoader.doLoadClass(TestLoader.java:92)
at android.support.test.internal.runner.TestLoader.loadIfTest(TestLoader.java:113)
at android.support.test.internal.runner.TestRequestBuilder.loadClassesFromClassPath(TestRequestBuilder.java:801)
at android.support.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:747)
at android.support.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:354)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:260)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1879)
My build.gradle looks likes this for dependencies:
dependencies {
compile "com.android.support:cardview-v7:${supportVersion}"
compile "com.android.support:recyclerview-v7:${supportVersion}"
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
compile 'com.loopj.android:android-async-http:1.4.9'
compile 'com.qiniu:qiniu-android-sdk:7.0.9'
compile 'com.mcxiaoke.gradle:packer-helper:1.0.4'
compile 'me.henrytao:smooth-app-bar-layout:23.2.1.1'
compile 'com.alipay.euler:andfix:0.4.0#aar'
compile 'com.umeng.analytics:analytics:6.0.0'
compile fileTree('libs')
compile project(':framework')
compile project(':yqdsdk')
// Only needed at compilation
provided 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'
// For testing
androidTestCompile "com.android.support:support-annotations:${supportVersion}"
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
exclude group: 'javax.inject'
}
}
Build Types look like the following:
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
testProguardFile 'test-proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testProguardFile.pro looks like this:
-dontobfuscate
-dontwarn
What I've done:
If I switch Proguard off for debug build by setting minifyEnabled=false, the test runs successfully. I get the error above otherwise.
I tried to put testProguardFile under "defaultConfig" and "debug", but to no avail both.
I tried to add one more build type "uiTest" with Proguard off, but the test configuration won't work after I set testBuildType to "uiTest". The error is that Android Studio won't recognise the test runner AndroidJUnitRunner.
It seems to me the problem comes with the mix use of proguard and dagger2 but I'm running out of ideas. Please help.
Best wishes
After doing more research, I found a solution for this problem although which is not straight forward:
Add a new build type and sync the build the project, e.g.
uiTest {
minifyEnabled true
}
On the left down side of the Android Studio, click on "Build Variants". For your application module, choose the newly added build variant, e.g. "UiTest".
Run the application.
This is somewhat inconvenient because you need to switch back and forth when you need to test under different build variants. But it gets Expresso running.
I had a similar problem and was able to fix it by adding the following rule to the proguard-rules.pro:
-keep class javax.inject.** { *; }
I'm not entirely sure your issue is the same though.
Also I'm not sure that you need to exclude javax.inject group from espresso-core dependency.
Related
I noticed that this is quite common question around here so I did some research and tried to resolve this on my own, but without any positive results. So if anyone would have any ideas how to solve this problem I would really appreciate it. I have been stuck on this for hours now.
I look up into these threads:
Firebase database dependecny crashes app - there I found out that I should have all my dependency versions same.
Android app crashes - in this thread they suggested that I should use the latest versions depending on google official website.
And also here I found the same suggestions - versions should be the same, clean and rebuild your project etc.
What I understand is the issue:
The dependencies are incompatible.
NOTE: My app worked fine just with the firebase-realtime database. After adding the firebase-auth it crashes instantly (testing on Huawei P9 lite NOT on emulator).
What I have tried:
1) Making all the dependencies the newest versions. It didn’t work – still the app crashes right after start.
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.google.firebase:firebase-database:16.1.0'
implementation 'com.google.firebase:firebase-auth:16.2.0'
2) Downgrading the dependencies to the closest version that they have all in common based on this link (which is 16.0.5).
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-database:16.0.5'
implementation 'com.google.firebase:firebase-auth:16.0.5'
3) When I tried to add the firebase-auth through tools manager it
inserted 'com.google.firebase:firebase-auth:16.0.3' which lead up to this error:
ERROR: In project 'app' a resolved Google Play services library dependency depends on another at an exact version (e.g. "[15.0. 1]", but isn't being resolved to that version. Behavior exhibited by the library will be unknown.
Dependency failing: com.google.android.gms:play-services-flags:15.0.1 -> com.google.android.gms:play-services-basement#[
15.0.1], but play-services-basement version was 16.0.1.
The following dependencies are project dependencies that are direct or have transitive dependencies that lead to the art ifact with the issue.
-- Project 'app' depends onto com.google.firebase:firebase-core#16.0.5
-- Project 'app' depends onto com.google.firebase:firebase-iid#17.0.3
-- Project 'app' depends onto com.google.firebase:firebase-analytics#16.0.5
-- Project 'app' depends onto com.google.firebase:firebase-common#16.0.4
-- Project 'app' depends onto com.google.android.gms:play-services-stats#16.0.1
-- Project 'app' depends onto com.google.android.gms:play-services-basement#16.0.1
-- Project 'app' depends onto com.google.firebase:firebase-auth-interop#16.0.0
-- Project 'app' depends onto com.google.android.gms:play-services-flags#15.0.1
-- Project 'app' depends onto com.google.android.gms:play-services-tasks#16.0.1
-- Project 'app' depends onto com.google.firebase:firebase-measurement-connector-impl#17.0.3
-- Project 'app' depends onto com.google.android.gms:play-services-base#16.0.1
-- Project 'app' depends onto com.google.firebase:firebase-analytics-impl#16.2.3
-- Project 'app' depends onto com.google.firebase:firebase-database#16.0.5
-- Project 'app' depends onto com.google.firebase:firebase-iid-interop#16.0.1
-- Project 'app' depends onto com.google.android.gms:play-services-measurement-base#16.0.4
-- Project 'app' depends onto com.google.android.gms:play-services-ads-identifier#16.0.0
-- Project 'app' depends onto com.google.firebase:firebase-measurement-connector#17.0.1
-- Project 'app' depends onto com.google.firebase:firebase-auth#16.0.3
-- Project 'app' depends onto com.google.android.gms:play-services-measurement-api#16.0.3
This is how my app level gradle file looks like:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.test123"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
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'
implementation 'com.android.support:animated-vector-drawable:28.0.0'
implementation 'com.android.support:support-media-compat:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-database:16.0.5'
implementation 'com.google.firebase:firebase-auth:16.0.5'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
apply plugin: 'com.google.gms.google-services'
This is my gradle file:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
// Android Gradle Plugin
classpath 'com.android.tools.build:gradle:3.3.2'
// Google Services Plugin
classpath "com.google.gms:google-services:4.2.0"
// 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
}
And finally my logcat:
04-05 14:04:36.000 906-906/? I/art: Late-enabling -Xcheck:jni
04-05 14:04:36.192 906-906/com.example.test123 W/System: ClassLoader referenced unknown path: /data/app/com.example.test123-1/lib/arm64
04-05 14:04:36.439 906-922/com.example.test123 I/art: Background partial concurrent mark sweep GC freed 11193(638KB) AllocSpace objects, 4(80KB) LOS objects, 21% free, 15MB/19MB, paused 343us total 105.488ms at HeapTaskDaemon thread CareAboutPauseTimes 1
04-05 14:04:36.658 906-957/com.example.test123 W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
04-05 14:04:36.686 906-956/com.example.test123 I/FA: App measurement is starting up, version: 14700
04-05 14:04:36.686 906-956/com.example.test123 I/FA: To enable debug logging run: adb shell setprop log.tag.FA VERBOSE
04-05 14:04:36.686 906-956/com.example.test123 I/FA: To enable faster debug mode event logging run:
adb shell setprop debug.firebase.analytics.app com.example.test123
04-05 14:04:36.717 906-906/com.example.test123 I/FirebaseInitProvider: FirebaseApp initialization successful
04-05 14:04:36.723 906-961/com.example.test123 W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
04-05 14:04:36.733 906-961/com.example.test123 I/FirebaseAuth: [FirebaseAuth:] Loading module via FirebaseOptions.
04-05 14:04:36.733 906-961/com.example.test123 I/FirebaseAuth: [FirebaseAuth:] Preparing to create service connection to gms implementation
04-05 14:04:37.017 906-976/com.example.test123 I/System: core_booster, getBoosterConfig = false
04-05 14:04:37.048 906-906/com.example.test123 I/HwCust: Constructor found for class android.app.HwCustHwWallpaperManagerImpl
04-05 14:04:37.254 906-906/com.example.test123 W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
04-05 14:04:37.673 906-906/com.example.test123 I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>
04-05 14:04:37.674 906-906/com.example.test123 I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>
04-05 14:04:38.485 906-906/com.example.test123 I/Process: Sending signal. PID: 906 SIG: 9
The problem may be at your device, it might not have the google play services up to date to support the version that your app is requesting.
Try updating your google play services in your device or change to another device and test it there.
Try this,it might work.
implementation 'com.google.firebase:firebase-core:16.0.1'
implementation 'com.google.firebase:firebase-database:16.0.1'
implementation 'com.google.firebase:firebase-auth:16.0.1'
When we use multiple libraries in which some of the libraries are already included by some of the libraries but with the different version no, we come across these kinds of problems. For this, you can force your gradle to use a single version of the library everywhere
configurations.all {
resolutionStrategy {
force "com.google.firebase:firebase-core:${VERSION_XYZ}”
force "com.google.firebase:firebase-database:${VERSION_ABC}”
}}
dependencies {
// ... all dependencies here...
}
Like this, do it for every library and define it in your gradle file, It might help you.
Try this,it will work to you. Happy coding :)
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.google.firebase:firebase-database:16.1.0'
implementation 'com.google.firebase:firebase-auth:16.2.0'
Instrumented tests do pass on local emulators and physical devices but fail on Firebase Test Lab, when the following conditions are met:
ProGuard is enabled for the debug builds;
There are both Dagger and Espresso dependencies.
FTL shows different test issues:
1) In case with APIs 26-28 it shows either Instrumentation run failed due to 'java.lang.NoClassDefFoundError' or Instrumentation run failed due to 'Process crashed.'
Exception stacktrace looks like this, it's not always shown in Firebase but is always present in logcat:
Rejecting re-init on previously-failed class java.lang.Class<androidx.test.espresso.core.internal.deps.dagger.internal.Factory>:
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/inject/Provider;
FATAL EXCEPTION: Instr: androidx.test.runner.AndroidJUnitRunner
Process: com.example.debug, PID: 11425
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/inject/Provider;
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at androidx.test.internal.runner.TestLoader.doCreateRunner(TestLoader.java:72)
at androidx.test.internal.runner.TestLoader.getRunnersFor(TestLoader.java:104)
at androidx.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:789)
at androidx.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:544)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:387)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Caused by: java.lang.ClassNotFoundException: Didn't find class "javax.inject.Provider" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/system/framework/android.test.mock.jar", zip file "/data/app/com.example.debug.test-9kvw--JgNKzmuQurRdDbCQ==/base.apk", zip file "/data/app/com.example.debug-sz-oCUGs05zlEadCzyqsDA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.debug.test-9kvw--JgNKzmuQurRdDbCQ==/lib/arm64, /data/app/com.example.debug-sz-oCUGs05zlEadCzyqsDA==/lib/arm64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 8 more
2) I also ran one test on API 21 which only had one NoClassDefFoundError in the logs. However, this exception is also present on APIs 26-28, but is a part of the exception shown above. Maybe there's just some difference between how it's logged on different API levels.
java.lang.NoClassDefFoundError: androidx.test.espresso.core.internal.deps.dagger.internal.Factory
FATAL EXCEPTION: Instr: androidx.test.runner.AndroidJUnitRunner
Process: com.example.debug, PID: 5691
java.lang.NoClassDefFoundError: androidx.test.espresso.core.internal.deps.dagger.internal.Factory
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:308)
at androidx.test.internal.runner.TestLoader.doCreateRunner(Unknown Source)
at androidx.test.internal.runner.TestLoader.getRunnersFor(Unknown Source)
at androidx.test.internal.runner.TestRequestBuilder.build(Unknown Source)
at androidx.test.runner.AndroidJUnitRunner.buildRequest(Unknown Source)
at androidx.test.runner.AndroidJUnitRunner.onStart(Unknown Source)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
Some relevant lines from build.gradle configuration:
android {
defaultConfig {
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
debug {
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-debug.pro'
testProguardFile 'proguard-rules-test.pro'
}
}
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:core:1.0.0-beta01'
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-beta01') {
// exclude module: 'javax.inject' - Exclusion doesn't help
}
// androidTestImplementation 'javax.inject:javax.inject:1' - Inclusion doesn't help either
androidTestImplementation('androidx.test.ext:junit:1.0.0-beta01') {
exclude group: "org.junit"
}
androidTestImplementation 'androidx.test:runner:1.1.0-beta01'
androidTestImplementation 'androidx.test:rules:1.1.0-beta01'
androidTestImplementation 'org.mockito:mockito-android:2.22.0'
implementation 'com.google.dagger:dagger:2.16'
kapt 'com.google.dagger:dagger-compiler:2.16'
}
proguard-rules-test.pro:
-ignorewarnings
-dontshrink
-dontoptimize
-dontobfuscate
Upon disabling ProGuard or removing Dagger dependency, tests start to pass on FTL.
So I contacted Firebase support and got an embarrassingly simple solution.
Add the following rule to the proguard-rules-debug.pro
-keep class javax.inject.** { *; }
It's still not clear why this problem doesn't occur while testing locally.
But at least this solution works.
I am failing to create a release build. Suddenly Android Studio started throwing below error.
Unexpected error while performing partial evaluation:
Class = [com/google/android/gms/d/lc]
Method = [a(Lcom/google/android/gms/d/kk;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/google/android/gms/d/lh;Lcom/google/android/gms/d/en;Lcom/google/android/gms/d/lb;)Lcom/google/android/gms/d/kn;]
Exception = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/android/gms/d/kn] (with 1 known super classes) and [java/lang/String] (with 2 known super classes))
Unexpected error while preverifying:
Class = [com/google/android/gms/d/lc]
Method = [a(Lcom/google/android/gms/d/kk;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/google/android/gms/d/lh;Lcom/google/android/gms/d/en;Lcom/google/android/gms/d/lb;)Lcom/google/android/gms/d/kn;]
Exception = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/android/gms/d/kn] (with 1 known super classes) and [java/lang/String] (with 2 known super classes))
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Can't find common super class of [com/google/android/gms/d/kn] (with 1 known super classes) and [java/lang/String] (with 2 known super classes)
Here is my Proguard Configurations
-keep public class com.google.android.gms.* { public *; }
-dontwarn com.google.android.gms.**
-keep class com.facebook.ads.** { *; }
Here is the list of gradle dependencies of my project
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.google.firebase:firebase-perf:16.0.0'
implementation 'com.google.firebase:firebase-config:16.0.0'
implementation 'com.google.firebase:firebase-core:16.0.0'
implementation 'com.google.firebase:firebase-messaging:17.0.0'
implementation 'com.google.android.gms:play-services-analytics:16.0.0'
implementation 'com.google.android.gms:play-services-drive:15.0.1'
implementation 'com.google.android.gms:play-services-auth:15.0.1'
implementation 'com.startapp:inapp-sdk:3.8.4'
implementation 'com.facebook.android:audience-network-sdk:4.28.2'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.7.1'
testImplementation 'org.powermock:powermock-mockito-release-full:1.4.9'
implementation('com.crashlytics.sdk.android:crashlytics:2.9.1#aar') {
transitive = true
}
}
Note Commenting the Facebook audience network dependency fixes the error. Unfortunately I cannot do it permanently from the project.
Please help me identifying the cause of an issue. Thanks in advance.
Finally I managed to fix the error. As I am not Proguard expert, I may be wrong but this is the workaround I see at the moment.
As I have mentioned in the question, Facebook Audience Network causes the problem with the release build and errors are associated with the GMS Play Service library. According to comment posted by #pedrofsn, Facebook Audience Network uses the Google Play Service Ads library.
I started looking into documentation for the error Can't find common super class of. It says that
A class in one of your program jars or library jars is referring to a
class or interface that is missing from the input. The warning lists
both the referencing class(es) and the missing referenced class(es).
There can be a few reasons, with their own solutions:
As it says the warning lists both the referencing class(es) and the missing referenced class(es), I decided to remove dontwarn just to see the warnings by the Proguard & updated my Proguard Configuration as below
-keep public class com.google.android.gms.* { public *; }
-keep class com.facebook.ads.** { *; }
I managed to see all the warnings by Proguard as the screenshot below.
As we can see from the screenshot, google ads library classes cannot find their referenced class com.google.android.gms.common.internal.zzac. My guess is that this class com.google.android.gms.common.internal.zzac should belong to the internal jar of the google ads dependency & that internal jar is probably missing.
So I have manually added the google ads dependency to my app level build.gradle as below
implementation 'com.google.android.gms:play-services-ads:15.0.1'
And I see I can compile the release build successfully.
I fixed downgrading 'com.google.firebase:firebase-messaging:17.0.0' to 'com.google.firebase:firebase-messaging:15.0.2'
For this to work, I had to uncomment:
buildTypes {
release {
//minifyEnabled true
//shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
and add the below to your proguard-rules.pro file:
-keep class com.google.android.gms.internal.** { *; }
-keep public class com.google.android.gms.* { public *; }
-dontwarn com.google.android.gms.**
although uncommenting minifyEnabled is not recommended since it removes dead/unused code
App crashes when i apply crashlytics on it
FATAL EXCEPTION: main
Process: com.ehs.pk, PID: 20963
java.lang.RuntimeException: Unable to get provider com.crashlytics.android.CrashlyticsInitProvider: java.lang.ClassNotFoundException: Didn't find class "com.crashlytics.android.CrashlyticsInitProvider" on path: DexPathList[[zip file "/data/app/com.ehs.pk-8.apk"],nativeLibraryDirectories=[/data/app-lib/com.ehs.pk-8, /vendor/lib, /system/lib]]
at android.app.ActivityThread.installProvider(ActivityThread.java:4993)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4585)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4499)
at android.app.ActivityThread.access$1500(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.crashlytics.android.CrashlyticsInitProvider" on path: DexPathList[[zip file "/data/app/com.ehs.pk-8.apk"],nativeLibraryDirectories=[/data/app-lib/com.ehs.pk-8, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67)
at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
at android.app.ActivityThread.installProvider(ActivityThread.java:4978)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4585)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4499)
at android.app.ActivityThread.access$1500(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
I was facing the same issue, is related to the 64k limit "multidex".
I was using multiDexEnabled true property in build.gradle in defaultConfig block, under android one.
As stated in Google documentation
for devices with Android API prior to 21, we need to include the multidex library (implementation 'com.android.support:multidex:1.0.2')
and extend MultiDexApplication in our Application class
I have solved this problem by doing the following:
In the Application class:
#Override
public void attachBaseContext(Context base) {
super.attachBaseContext(base);
try {
MultiDex.install(this);
} catch (RuntimeException multiDexException) {
multiDexException.printStackTrace();
}
}
We were having the same issue, and disabling instant run in Android Studio seemed to get it working.
On mac
Android Studio Settings or Preferences -> Build,Execution,Deployment -> Instant Run.
By looking at this part...
Didn't find class ... on path: DexPathList ... dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67)
of the stack trace you can figure out that your test device is probably pre-Lollipop (Android 5.0) and that you just hit the 64k limit. You can fix it as described here.
This could be an issue with Instant Run. Turn off the Instant Run and run the build again. I faced the same issue and it resolved it.
When minifyEnabled is true while using firebase or crashlytics this problem may happens. Enabling minifyEnabled shrinks methods and classes names to lowest possible characters (changing names and that raises ClassNotFoundException). Unfortunately, firebase and crashlytics versions had many problem with that. To solve it just tell proguard to not shrink those classes by writing the next lines in proguard file "proguard-rules.pro" as:
-keep class com.crashlytics.** { *; }
-keep class com.google.firebase.*.* { *; }
Now if the problem not go away or it didn't find other classes like yours, then check your base project build.gradle dependencies version of gradle and others. I found these version is free of that error:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:3.2.0'
classpath 'io.fabric.tools:gradle:1.25.1'
}
Remeber you can put any classes path into that proguard file so it did not change its name or methods when minify is enabled, and that will help you with other classes "ClassNotFoundException" as well.
Also to test this in debugging, you can adjust debug setting in build.gradle as:
buildTypes {
release {
debuggable false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Just one more case:
In my case, I disabled instant run, added multiDexEnabled true in my gradle, and added the 'com.android.support:multidex:1.0.3' to my dependencies, called the MultiDex.install(this); directly in my custom application, but I still got the same error. The error only occurs in the system Android 4.4. Everything works well on Android 7.0 and 9.0.
Finally, moving the MultiDex.install(this); from the onCreate(Context) method to the attachBaseContext(Context) solved my problem.
So, you should call MultiDex.install(this); in attachBaseContext(Context) instead of onCreate(Context) when you don't plan to extend the MultiDexApplication directly.
If this happens when you run with minifyEnabled true, add this rule in your proguard-rules.pro file:
-keep public class com.crashlytics.android.CrashlyticsInitProvider
When I run the following code:
public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
....
public void testCanCreateMockito() {
List mockedList = Mockito.mock(List.class);
}
}
I get the following exceptions:
java.lang.ExceptionInInitializerError
at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
at com.acesounderglass.hungertracker.ActivityTest.testCanCreateMockito(ActivityTest.java:60)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238)
at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
... 23 more
Caused by: java.lang.reflect.InvocationTargetException
at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385)
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220)
... 28 more
Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
at java.lang.ClassLoader.defineClass(ClassLoader.java:300)
... 32 more
This occurs with any class, List was just an easy example. My gradle dependencies are:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.0'
androidTestCompile "org.mockito:mockito-core:1.+"
androidTestCompile files('libs/dexmaker-mockito-1.0.jar')
androidTestCompile files('libs/dexmaker-1.0.jar')
}
I've upgraded gradle to 1.1, tried using the experimental unit test feature and not, nothing seems to make a difference. What's going on?
I received this error when I was missing the two dexmaker dependencies.
Adding these lines to the app/gradle.build file is working for me.
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
I am also using Android Studio and have found it to be a good idea to restart AS after altering the dependencies.
For me this eventually worked:
androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"
I was getting this because I was using proguard for my debug builds because of the 65K method limit (Yes, I need to cut down on the number of dependencies), and that was causing this error for me.
I added this in my (debug) proguard config to solve it:
### Keep Mockito
-keep class org.mockito.** { *; }
-keep interface org.mockito.** { *; }
-keep class com.google.dexmaker.** { *; }
-keep interface com.google.dexmaker.** { *; }
Not sure If I really need all four of those lines, but this did the trick.
LOOK HERE IF YOU DON'T BUILD YOUR APKS USING GRADLE!!!!
If you don't build your app using gradle (which, unfortunately, my team doesn't) then the above solutions may not work for you. Let me explain a little bit more about how dexmaker-mockito works before giving the solution to the issue.
Motivation
Mockito is a mocking framework for Java and comes packaged with cglib which creates Bytecode mocks, this is how Mockito/Junit outside of Instrumentation tests works. But if you're trying to run Mockito in Android instrumentation tests then Bytecode mocks are not sufficient and you need mocks that Mockito can load into the Dex classloader that ART/Dalvik can understand and that's where Dexmaker comes in. Dexmaker has a Mockito "plugin" that allows Mockito to dynamically switch to using it to create Dex mocks.
How does it know to switch?
The dexmaker-mockito jar has a top level folder named mockito-extensions/org.mockito.plugins.MockMaker containing a fully qualified name com.google.dexmaker.mockito.DexmakerMockMaker. When this jar is packaged with an APK, this top level folder can be included as a "class loader resource".
The class that Mockito uses to abstract the Mocking layer is called MockUtil and, statically, it determines which MockMaker subclass it should use by checking for these resources in the classloader that it is launched from via its PluginLoader. If the resource from dexmaker-mockito can be found, then com.google.dexmaker.mockito.DexmakerMockMaker is instantiated and used as the MockMaker but, if it's not, Mockito defaults to using CGLib which is incompatible within Android's DVM.
Problem
Depending on how you build your APK, you can potentially strip that class loader resource and cause Mockito to not dynamically switch to using Dexmaker.
Fix
First, include the jars that dexmaker requires: mockito 1.9.5+, junit, dexmaker-mockito 1.0+ and dexmaker 1.0+ and then simply reflectively switch which MockMaker Mockito will use manually. This is safe, given the fact that if this is running in the DVM, using the default CGLib MockMaker won't ever work since it produces Bytecode mocks.
static {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
Enumeration<URL> resources = loader.getResources("mockito-extensions/org.mockito.plugins.MockMaker");
if (resources == null || !resources.hasMoreElements()) {
LOGGER.info("Replacing Mockito mockMaker because the classloader resources were not present.");
Field field = MockUtil.class.getDeclaredField("mockMaker");
Class<?> pluginClass = loader.loadClass("com.google.dexmaker.mockito.DexmakerMockMaker");
Object plugin = pluginClass.newInstance();
field.setAccessible(true);
field.set(null, plugin);
} else {
LOGGER.info("Mockito class loader resources present");
}
} catch (Throwable e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker", e);
} else {
e.printStackTrace();
throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker");
}
}
}
and be sure to add this as well because dexmaker will need to know where to output its Dex mocks.
System.setProperty("dexmaker.dexcache", "/sdcard/");
I stumbled upon the same error and could make it work by using
androidTestImplementation 'org.mockito:mockito-android:2.18.3'
in my build.gradle.
I previously made the mistake to only import 'org.mockito:mockito-core:2.18.3'.
I encountered the same error with EasyMock and eventually traced it to an absence of dexmaker. I solved it with the following dependency:
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
That might work for mockito as well
User23's answer is close to the solution that worked for me.
According to the official documentation you have to do the following things to activate Mockito in your Android app:
Download dexmaker-1.4.jar and dexmaker-mockito-1.4.jar and put them into your libs folder.
Add the following dependencies into your build.gradle:
androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-1.4.jar'])
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-mockito-1.4.jar'])