Android Samsung Lollipop 设备上的应用程序崩溃 NoClassDefFoundError
Android app crash NoClassDefFoundError on Samsung Lollipop devices
我们最近将应用程序的 minSdkVersion 从 16 (Jellybean) 提高到了 21 (Lollipop)。尽管我们主要使用调试版本对我们的应用程序进行了广泛的测试,但我们现在在应用程序启动时面临大量的生产崩溃,主要是在旧的三星设备上——(Note3 和 S4 是最崩溃的)并且总是在 Lollipop 上。
错误是
Fatal Exception: java.lang.NoClassDefFoundError: com.retailconvergence.ruelala.delegate.GoogleLoginDelegate
at com.retailconvergence.ruelala.delegate.LifecycleDelegateManager.addDelegateOfType(LifecycleDelegateManager.java:48)
at com.retailconvergence.ruelala.extensions.activity.LifecycleDelegateActivity.addDelegateOfType(LifecycleDelegateActivity.java:55)
at com.retailconvergence.ruelala.activity.SplashActivity.setupDelegates(SplashActivity.java:198)
at com.retailconvergence.ruelala.activity.SplashActivity.onCreate(SplashActivity.java:60)
at android.app.Activity.performCreate(Activity.java:6288)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
at android.app.ActivityThread.access0(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
SplashActivity 是应用程序的初始启动 activity。 class not found 是一个历史悠久的 class 不是新引入的东西。作为旁注,作为这个最新版本的一部分,我们升级到 Android Studio 3 并引入了 Kotlin 代码,但我认为这些与问题无关。我们没有在构建中使用混淆器。
我知道当 minSdkVersion 为 21 及以上时,构建会发生重大变化,这与使用 ART 而不是 Dalvik 有关,所以我想知道 Samsung Lollipop 设备是否仍然存在缺陷现在在主 dex 文件中寻找 class?
模块级build.gradle:
import java.text.SimpleDateFormat
import java.util.concurrent.TimeUnit
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'
apply plugin: 'spoon'
// Manifest version information
def versionMajor = 4
def versionMinor = 2
def versionPatch = 0
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
ext.versionReleaseDate="OCT-13-2017" // UPDATE THIS WHEN YOU BUMP THE VERSIONS ABOVE FOR A NEW RELEASE MMM-dd-yyy
repositories {
mavenCentral()
maven { url 'https://maven.fabric.io/public' }
maven { url 'http://salesforce-marketingcloud.github.io/JB4A-SDK-Android/repository' }
maven { url "https://maven.google.com" }
maven { url "http://maven.tealiumiq.com/android/releases/" }
}
def getCountOfHoursSinceVersionUpdate() {
def currentDate = new Date()
def format = new SimpleDateFormat("MMM-dd-yyyy")
def buildDate = (Date)format.parse(versionReleaseDate)
return (Integer)((currentDate.getTime() - buildDate.getTime()) / TimeUnit.HOURS.toMillis(1))
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.1'
defaultConfig {
targetSdkVersion 25
/**
* Increment versionCode by commit count
*/
versionCode versionMajor * 100000 + versionMinor * 10000 + versionPatch * 1000 + versionBuild + getCountOfHoursSinceVersionUpdate()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// Enabling multidex support. :(
multiDexEnabled true
def manifestPath = project(':').file('app/src/androidTest/AndroidManifest.xml')
buildConfigField "String", "MANIFEST_PATH", "\"" + manifestPath + "\""
def resPath = project(':').file('app/src/main/res/')
buildConfigField "String", "RES_PATH", "\"" + resPath + "\""
def assetPath = project(':').file('app/src/prod/assets/')
buildConfigField "String", "ASSET_PATH", "\"" + assetPath + "\""
}
dexOptions {
javaMaxHeapSize "8g"
dexInProcess true // the magic line
}
flavorDimensions "debugDimension"
/**
* productFlavors override defaultConfig properties as well as force gradle to look in the new
* folders that we have created to differentiate the build assets and manifests.
* src/dev, src/prod
*/
productFlavors {
dev {
minSdkVersion 21
applicationId "com.retailconvergence.ruelala.dev"
versionName "${versionMajor}.${versionMinor}.0${versionPatch}"
manifestPlaceholders = [optimizelyId: "optly4740131949"]
dimension "debugDimension"
}
prod {
minSdkVersion 21
applicationId "com.retailconvergence.ruelala"
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
manifestPlaceholders = [optimizelyId: "optly4752051515"]
dimension "debugDimension"
}
}
signingConfigs {
prod {
//the key is up a level, don't include in the modules
storeFile file("../RueLaLaKeystore")
storePassword "Boutiques"
keyAlias "rue la la"
keyPassword "Boutiques"
}
}
buildTypes {
release {
signingConfig signingConfigs.prod
ext.betaDistributionReleaseNotesFilePath = 'release_notes.txt'
ext.betaDistributionGroupAliases = 'AndroidTesters'
ext.betaDistributionNotifications = true
}
debug {
versionNameSuffix '-dev'
signingConfig signingConfigs.prod
// to get coverage report, set testCoverageEnabled to true and run gradle task called createDevelopmentDebugAndroidTestCoverageReport
// Note that test coverage doesn't seem to work on Samsung devices, other brand or emulator should work though
testCoverageEnabled = false
ext.betaDistributionReleaseNotesFilePath = 'release_notes.txt'
ext.betaDistributionGroupAliases = 'AndroidTesters'
ext.betaDistributionNotifications = true
}
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
exclude 'LICENSE.txt'
exclude 'LICENSE'
exclude 'READ.ME'
exclude 'README'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
configurations {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//include our modules
compile project(':core')
compile project(':data')
//android
final APP_COMPAT_VERSION = '26.1.0'
compile "com.android.support:appcompat-v7:$APP_COMPAT_VERSION"
compile "com.android.support:recyclerview-v7:$APP_COMPAT_VERSION"
compile "com.android.support:design:$APP_COMPAT_VERSION"
compile "com.android.support:multidex:1.0.0"
compile "com.android.support:cardview-v7:$APP_COMPAT_VERSION"
// google
final PLAY_SERVICES_VERSION = '10.2.4'
compile "com.google.android.gms:play-services-wallet:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-location:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-gcm:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-plus:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-identity:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-analytics:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-auth:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-maps:$PLAY_SERVICES_VERSION"
// facebook
compile 'com.facebook.android:facebook-android-sdk:4.8.+'
compile 'com.facebook.stetho:stetho:1.1.0'
//markdown4j
compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0'
//crashlytics
compile('com.crashlytics.sdk.android:crashlytics:2.5.2@aar') {
transitive = true;
}
//image zoom
compile 'com.github.chrisbanes.photoview:library:1.2.3'
//square
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.makeramen:roundedimageview:2.2.1'
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'
compile 'com.jakewharton:butterknife:8.6.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
// optimizely
compile('com.optimizely:optimizely:1.4.2@aar') {
transitive = true
}
//braintree
compile 'com.braintreepayments.api:braintree:2.6.0'
compile 'com.braintreepayments.api:data-collector:2.+'
// guava
compile 'com.google.guava:guava:19.0'
// sticky headers
compile 'com.github.mtotschnig:StickyListHeaders:2.7.1'
// expandable recyclerview
compile 'eu.davidea:flexible-adapter:5.0.0-rc2'
//recyclerview animations
compile 'jp.wasabeef:recyclerview-animators:2.2.3'
// tooltip
compile 'com.github.michaelye.easydialog:easydialog:1.4'
// tealium
compile 'com.tealium:library:5.3.0'
// circle indicator
compile 'me.relex:circleindicator:1.2.2@aar'
//testing
final HAMCREST_VERSION = '1.3'
def jUnit = "junit:junit:4.12"
// ExactTarget SDK
compile ('com.salesforce.marketingcloud:marketingcloudsdk:5.0.5') {
exclude module: 'android-beacon-library' //remove to use Proximity messaging
exclude module: 'play-services-location' //remove to use Geofence or Proximity messaging
}
androidTestCompile jUnit
// Unit tests dependencies
testCompile jUnit
testCompile "org.hamcrest:hamcrest-core:$HAMCREST_VERSION"
testCompile "org.hamcrest:hamcrest-library:$HAMCREST_VERSION"
testCompile "org.hamcrest:hamcrest-integration:$HAMCREST_VERSION"
testCompile 'org.robolectric:robolectric:3.1'
testCompile 'org.mockito:mockito-core:1.+'
testCompile 'com.google.guava:guava:19.0'
testCompile("com.android.support:support-v4:$APP_COMPAT_VERSION") {
exclude module: 'support-annotations'
}
testCompile('org.powermock:powermock-api-mockito:1.6.4') {
exclude module: 'objenesis'
}
testCompile('org.powermock:powermock-module-junit4:1.6.4') {
exclude module: 'objenesis'
}
testCompile 'io.reactivex:rxandroid:1.0.1'
testCompile 'io.reactivex:rxjava:1.1.0'
// Espresso
androidTestCompile('com.android.support.test:runner:0.5') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test:rules:0.5') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-web:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.2') {
exclude module: 'support-annotations'
exclude module: 'recyclerview-v7'
exclude module: 'appcompat-v7'
exclude module: 'design'
exclude module: 'support-v4'
}
// allows java 8 compile
compile 'com.annimon:stream:1.1.2'
// For taking screenshots
androidTestCompile 'com.squareup.spoon:spoon-client:1.7.0'
testCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
apply plugin: 'com.google.gms.google-services'
spoon {
noAnimations = true
grantAllPermissions = true
}
apply plugin: 'devicefarm'
devicefarm {
projectName "Rue Mobile"
devicePool "Smoke Test Pool"
useUnmeteredDevices()
authentication {
accessKey System.getenv("AWS_DEVICE_FARM_ACCESS_KEY")
secretKey System.getenv("AWS_DEVICE_FARM_SECRET_KEY")
}
}
解决此问题的方法是禁用预索引:
dexOptions {
preDexLibraries false
}
在应用中 build.gradle。灵感来自这个 link 关于 Lollipop 上的 Picasso class not found 错误:see here
我不完全清楚为什么禁用 pre-dexing 可以解决问题,但我只能推断构建过程正在进行一些优化,影响 classes 在中的排序方式apk 的 dex 文件,然后影响这些三星棒棒糖设备上的应用程序安装。理论上 ART 应该处理所有这些,但显然 pre-dex 优化和一些 Lollipop 设备之间存在依赖关系。
我们最近将应用程序的 minSdkVersion 从 16 (Jellybean) 提高到了 21 (Lollipop)。尽管我们主要使用调试版本对我们的应用程序进行了广泛的测试,但我们现在在应用程序启动时面临大量的生产崩溃,主要是在旧的三星设备上——(Note3 和 S4 是最崩溃的)并且总是在 Lollipop 上。
错误是
Fatal Exception: java.lang.NoClassDefFoundError: com.retailconvergence.ruelala.delegate.GoogleLoginDelegate
at com.retailconvergence.ruelala.delegate.LifecycleDelegateManager.addDelegateOfType(LifecycleDelegateManager.java:48)
at com.retailconvergence.ruelala.extensions.activity.LifecycleDelegateActivity.addDelegateOfType(LifecycleDelegateActivity.java:55)
at com.retailconvergence.ruelala.activity.SplashActivity.setupDelegates(SplashActivity.java:198)
at com.retailconvergence.ruelala.activity.SplashActivity.onCreate(SplashActivity.java:60)
at android.app.Activity.performCreate(Activity.java:6288)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
at android.app.ActivityThread.access0(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
SplashActivity 是应用程序的初始启动 activity。 class not found 是一个历史悠久的 class 不是新引入的东西。作为旁注,作为这个最新版本的一部分,我们升级到 Android Studio 3 并引入了 Kotlin 代码,但我认为这些与问题无关。我们没有在构建中使用混淆器。
我知道当 minSdkVersion 为 21 及以上时,构建会发生重大变化,这与使用 ART 而不是 Dalvik 有关,所以我想知道 Samsung Lollipop 设备是否仍然存在缺陷现在在主 dex 文件中寻找 class?
模块级build.gradle:
import java.text.SimpleDateFormat
import java.util.concurrent.TimeUnit
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'
apply plugin: 'spoon'
// Manifest version information
def versionMajor = 4
def versionMinor = 2
def versionPatch = 0
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
ext.versionReleaseDate="OCT-13-2017" // UPDATE THIS WHEN YOU BUMP THE VERSIONS ABOVE FOR A NEW RELEASE MMM-dd-yyy
repositories {
mavenCentral()
maven { url 'https://maven.fabric.io/public' }
maven { url 'http://salesforce-marketingcloud.github.io/JB4A-SDK-Android/repository' }
maven { url "https://maven.google.com" }
maven { url "http://maven.tealiumiq.com/android/releases/" }
}
def getCountOfHoursSinceVersionUpdate() {
def currentDate = new Date()
def format = new SimpleDateFormat("MMM-dd-yyyy")
def buildDate = (Date)format.parse(versionReleaseDate)
return (Integer)((currentDate.getTime() - buildDate.getTime()) / TimeUnit.HOURS.toMillis(1))
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.1'
defaultConfig {
targetSdkVersion 25
/**
* Increment versionCode by commit count
*/
versionCode versionMajor * 100000 + versionMinor * 10000 + versionPatch * 1000 + versionBuild + getCountOfHoursSinceVersionUpdate()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// Enabling multidex support. :(
multiDexEnabled true
def manifestPath = project(':').file('app/src/androidTest/AndroidManifest.xml')
buildConfigField "String", "MANIFEST_PATH", "\"" + manifestPath + "\""
def resPath = project(':').file('app/src/main/res/')
buildConfigField "String", "RES_PATH", "\"" + resPath + "\""
def assetPath = project(':').file('app/src/prod/assets/')
buildConfigField "String", "ASSET_PATH", "\"" + assetPath + "\""
}
dexOptions {
javaMaxHeapSize "8g"
dexInProcess true // the magic line
}
flavorDimensions "debugDimension"
/**
* productFlavors override defaultConfig properties as well as force gradle to look in the new
* folders that we have created to differentiate the build assets and manifests.
* src/dev, src/prod
*/
productFlavors {
dev {
minSdkVersion 21
applicationId "com.retailconvergence.ruelala.dev"
versionName "${versionMajor}.${versionMinor}.0${versionPatch}"
manifestPlaceholders = [optimizelyId: "optly4740131949"]
dimension "debugDimension"
}
prod {
minSdkVersion 21
applicationId "com.retailconvergence.ruelala"
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
manifestPlaceholders = [optimizelyId: "optly4752051515"]
dimension "debugDimension"
}
}
signingConfigs {
prod {
//the key is up a level, don't include in the modules
storeFile file("../RueLaLaKeystore")
storePassword "Boutiques"
keyAlias "rue la la"
keyPassword "Boutiques"
}
}
buildTypes {
release {
signingConfig signingConfigs.prod
ext.betaDistributionReleaseNotesFilePath = 'release_notes.txt'
ext.betaDistributionGroupAliases = 'AndroidTesters'
ext.betaDistributionNotifications = true
}
debug {
versionNameSuffix '-dev'
signingConfig signingConfigs.prod
// to get coverage report, set testCoverageEnabled to true and run gradle task called createDevelopmentDebugAndroidTestCoverageReport
// Note that test coverage doesn't seem to work on Samsung devices, other brand or emulator should work though
testCoverageEnabled = false
ext.betaDistributionReleaseNotesFilePath = 'release_notes.txt'
ext.betaDistributionGroupAliases = 'AndroidTesters'
ext.betaDistributionNotifications = true
}
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
exclude 'LICENSE.txt'
exclude 'LICENSE'
exclude 'READ.ME'
exclude 'README'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
configurations {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//include our modules
compile project(':core')
compile project(':data')
//android
final APP_COMPAT_VERSION = '26.1.0'
compile "com.android.support:appcompat-v7:$APP_COMPAT_VERSION"
compile "com.android.support:recyclerview-v7:$APP_COMPAT_VERSION"
compile "com.android.support:design:$APP_COMPAT_VERSION"
compile "com.android.support:multidex:1.0.0"
compile "com.android.support:cardview-v7:$APP_COMPAT_VERSION"
// google
final PLAY_SERVICES_VERSION = '10.2.4'
compile "com.google.android.gms:play-services-wallet:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-location:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-gcm:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-plus:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-identity:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-analytics:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-auth:$PLAY_SERVICES_VERSION"
compile "com.google.android.gms:play-services-maps:$PLAY_SERVICES_VERSION"
// facebook
compile 'com.facebook.android:facebook-android-sdk:4.8.+'
compile 'com.facebook.stetho:stetho:1.1.0'
//markdown4j
compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0'
//crashlytics
compile('com.crashlytics.sdk.android:crashlytics:2.5.2@aar') {
transitive = true;
}
//image zoom
compile 'com.github.chrisbanes.photoview:library:1.2.3'
//square
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.makeramen:roundedimageview:2.2.1'
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'
compile 'com.jakewharton:butterknife:8.6.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
// optimizely
compile('com.optimizely:optimizely:1.4.2@aar') {
transitive = true
}
//braintree
compile 'com.braintreepayments.api:braintree:2.6.0'
compile 'com.braintreepayments.api:data-collector:2.+'
// guava
compile 'com.google.guava:guava:19.0'
// sticky headers
compile 'com.github.mtotschnig:StickyListHeaders:2.7.1'
// expandable recyclerview
compile 'eu.davidea:flexible-adapter:5.0.0-rc2'
//recyclerview animations
compile 'jp.wasabeef:recyclerview-animators:2.2.3'
// tooltip
compile 'com.github.michaelye.easydialog:easydialog:1.4'
// tealium
compile 'com.tealium:library:5.3.0'
// circle indicator
compile 'me.relex:circleindicator:1.2.2@aar'
//testing
final HAMCREST_VERSION = '1.3'
def jUnit = "junit:junit:4.12"
// ExactTarget SDK
compile ('com.salesforce.marketingcloud:marketingcloudsdk:5.0.5') {
exclude module: 'android-beacon-library' //remove to use Proximity messaging
exclude module: 'play-services-location' //remove to use Geofence or Proximity messaging
}
androidTestCompile jUnit
// Unit tests dependencies
testCompile jUnit
testCompile "org.hamcrest:hamcrest-core:$HAMCREST_VERSION"
testCompile "org.hamcrest:hamcrest-library:$HAMCREST_VERSION"
testCompile "org.hamcrest:hamcrest-integration:$HAMCREST_VERSION"
testCompile 'org.robolectric:robolectric:3.1'
testCompile 'org.mockito:mockito-core:1.+'
testCompile 'com.google.guava:guava:19.0'
testCompile("com.android.support:support-v4:$APP_COMPAT_VERSION") {
exclude module: 'support-annotations'
}
testCompile('org.powermock:powermock-api-mockito:1.6.4') {
exclude module: 'objenesis'
}
testCompile('org.powermock:powermock-module-junit4:1.6.4') {
exclude module: 'objenesis'
}
testCompile 'io.reactivex:rxandroid:1.0.1'
testCompile 'io.reactivex:rxjava:1.1.0'
// Espresso
androidTestCompile('com.android.support.test:runner:0.5') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test:rules:0.5') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-web:2.2.2') {
exclude module: 'support-annotations'
}
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.2') {
exclude module: 'support-annotations'
exclude module: 'recyclerview-v7'
exclude module: 'appcompat-v7'
exclude module: 'design'
exclude module: 'support-v4'
}
// allows java 8 compile
compile 'com.annimon:stream:1.1.2'
// For taking screenshots
androidTestCompile 'com.squareup.spoon:spoon-client:1.7.0'
testCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
apply plugin: 'com.google.gms.google-services'
spoon {
noAnimations = true
grantAllPermissions = true
}
apply plugin: 'devicefarm'
devicefarm {
projectName "Rue Mobile"
devicePool "Smoke Test Pool"
useUnmeteredDevices()
authentication {
accessKey System.getenv("AWS_DEVICE_FARM_ACCESS_KEY")
secretKey System.getenv("AWS_DEVICE_FARM_SECRET_KEY")
}
}
解决此问题的方法是禁用预索引:
dexOptions {
preDexLibraries false
}
在应用中 build.gradle。灵感来自这个 link 关于 Lollipop 上的 Picasso class not found 错误:see here
我不完全清楚为什么禁用 pre-dexing 可以解决问题,但我只能推断构建过程正在进行一些优化,影响 classes 在中的排序方式apk 的 dex 文件,然后影响这些三星棒棒糖设备上的应用程序安装。理论上 ART 应该处理所有这些,但显然 pre-dex 优化和一些 Lollipop 设备之间存在依赖关系。