Since several weeks I am trying to find out, why does a "LGE Nexus 5 (hammerhead), 2048MB RAM, Android 5.0" device keep reporting crashes with java.lang.NoClassDefFoundError
caused by ClassNotFoundException
in a Google Play beta app.
My problem is to find out, which class is missing -
The function names reported (the SlovaApplication.onCreate()
) do not even have any code (because my app has 2 flavors - one for Google Play with FCM and one for Amazon with ADM).
Below is my app/build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
versionCode 29
applicationId "de.slova"
minSdkVersion 16
targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
debug {
keyAlias 'AndroidDebugKey'
storeFile file('../../../../../.android/debug.keystore')
keyPassword 'android'
storePassword 'android'
}
release {
keyAlias 'AndroidReleaseKey'
storeFile file('../../../conf/release.keystore')
keyPassword System.getenv('PASSPHRASE1')
storePassword System.getenv('PASSPHRASE1')
}
}
flavorDimensions "store"
productFlavors {
google {
dimension "store"
versionName "$defaultConfig.versionCode-google"
resConfigs "ru"
}
amazon {
dimension "store"
versionName "$defaultConfig.versionCode-amazon"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
debuggable false
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
splits {
density {
enable true
reset()
include "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
}
}
}
dependencies {
implementation 'com.android.support:multidex:1.0.3'
implementation "com.android.support:appcompat-v7:$supportVersion"
implementation "com.android.support:cardview-v7:$supportVersion"
implementation "com.android.support:customtabs:$supportVersion"
implementation "com.android.support:design:$supportVersion"
implementation "com.android.support:support-compat:$supportVersion"
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.neovisionaries:nv-websocket-client:2.3'
implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
implementation 'ru.ok:odnoklassniki-android-sdk:2.1.2'
implementation 'com.vk:androidsdk:1.6.9'
implementation 'com.facebook.android:facebook-login:4.28.0'
googleImplementation "com.google.android.gms:play-services-auth:$firebaseVersion"
googleImplementation "com.google.firebase:firebase-messaging:$firebaseVersion"
googleImplementation 'com.android.billingclient:billing:1.0'
amazonCompileOnly files('libs/amazon-device-messaging-1.0.1.jar')
amazonImplementation files('libs/login-with-amazon-sdk.jar')
implementation 'com.mikepenz:crossfader:1.5.2@aar'
implementation('com.mikepenz:materialdrawer:6.0.6@aar') {
transitive = true
}
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testImplementation 'junit:junit:4.12'
}
if (!getGradle().getStartParameter().getTaskRequests().toString().contains("Amazon")) {
apply plugin: 'com.google.gms.google-services'
}
And I have also tried changing from Application
to MultiDexApplication
but that has not helped (below is the google
flavor class whose 2 tasks are: update Play Services if needed and sign-in the Google user):
public class SlovaApplication extends MultiDexApplication implements Flavor, Keys {
private static final int PLAY_SERVICES = 1972; // USED TO UPDATE PLAY SERVICES
private static final int PLAY_LOGIN = 1979; // USED FOR GOOGLE SIGN-IN
@Override
public void onCreate() {
super.onCreate();
MultiDex.install(this); // HAS NOT HELPED WITH CRASHES
FirebaseApp.initializeApp(this);
VKSdk.initialize(this);
Utils.init(this);
}
@Override
public void onCreate(Activity activity) {
// DO NOTHING IN google FLAVOR
}
@Override
public void onResume() {
// DO NOTHING IN google FLAVOR
}
@Override
public boolean onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PLAY_SERVICES: {
if (resultCode != Activity.RESULT_OK) {
Toast.makeText(activity, getString(R.string.error_play_services), Toast.LENGTH_LONG).show();
activity.finish();
}
return true;
}
case PLAY_LOGIN: {
User user = null;
if (resultCode == Activity.RESULT_OK) {
try {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
if (task.isSuccessful()) {
GoogleSignInAccount account = task.getResult();
String photoUrl = (account.getPhotoUrl() != null ? account.getPhotoUrl().toString() : null);
user = new User(
account.getId(),
User.GOOGLE,
account.getGivenName(),
account.getFamilyName(),
(URLUtil.isNetworkUrl(photoUrl) ? photoUrl : null)
);
DatabaseService.updateUser(activity, user);
}
} catch (Exception ex) {
Log.w(TAG, "Adding Google user failed", ex);
}
}
if (user == null) {
Toast.makeText(activity, getString(R.string.error_play_login), Toast.LENGTH_LONG).show();
activity.finish();
}
return true;
}
default: return false;
}
}
@Override
public boolean doesExist() {
return Users.getInstance().doesUserExist(GOOGLE);
}
@Override
public void signin(final Activity activity) {
GoogleApiAvailability api = GoogleApiAvailability.getInstance();
int code = api.isGooglePlayServicesAvailable(activity);
if (code == ConnectionResult.SUCCESS) {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build();
GoogleSignInClient client = GoogleSignIn.getClient(activity, gso);
Intent i = client.getSignInIntent();
activity.startActivityForResult(i, PLAY_LOGIN);
} else if (api.isUserResolvableError(code)) {
api.showErrorDialogFragment(activity, code, PLAY_SERVICES, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
Toast.makeText(activity, getString(R.string.error_play_services), Toast.LENGTH_LONG).show();
activity.finish();
}
});
} else {
Toast.makeText(activity, getString(R.string.error_play_services) + " " + api.getErrorString(code), Toast.LENGTH_LONG).show();
activity.finish();
}
}
@Override
public void putToken(JSONObject obj, String ignore) throws JSONException {
String token = FirebaseInstanceId.getInstance().getToken();
obj.put(KEY_FCM, token);
}
}
I am lost at how to fix these crashes and how to identify the supposedly missing class...
The other devices in my beta program do not crash:
UPDATE: Adding multiDexEnabled true
has unfortunately not helped and here is my proguard-rules.pro:
-libraryjars libs
-dontwarn com.squareup.okhttp.**
-dontwarn com.amazon.device.messaging.**
-keep class com.amazon.device.messaging.** {*;}
-keep public class * extends com.amazon.device.messaging.ADMMessageReceiver
-keep public class * extends com.amazon.device.messaging.ADMMessageHandlerBase
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
Per the documentation, you are missing one line in app/build.gradle:
defaultConfig {
...
multiDexEnabled true
...
}
you are missing the line
multiDexEnabled true in App gradle file
defaultConfig{
...
multiDexEnabled true
}
Follow this link from android Docs to enable multidex in your application
https://developer.android.com/studio/build/multidex.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With