Reputation: 15
I'm discovering a problem with an Android application.
My problem is that when I open the application it crashes giving NoClassDefFoundError. This is the stack trace:
09-24 19:37:14.542 32545-32545/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: it.bcv.invadelite, PID: 32545
java.lang.NoClassDefFoundError: com.electronwill.nightconfig.core.file.FormatDetector$$Lambda$0
at com.electronwill.nightconfig.core.file.FormatDetector.registerExtension(FormatDetector.java:27)
at com.electronwill.nightconfig.json.JsonFormat.<clinit>(JsonFormat.java:66)
at it.bcv.invade.appdb.ConfigAdapter.<init>(ConfigAdapter.java:39)
at it.bcv.invade.appdb.Db.<init>(Db.java:51)
at it.bcv.invade.appdb.Db.init(Db.java:75)
at it.bcv.invadelite.activities.StartActivity.initDatabase(StartActivity.java:165)
at it.bcv.invadelite.activities.StartActivity.onCreate(StartActivity.java:125)
[...]
and build.gradle
file has following lines:
// https://github.com/TheElectronWill/Night-Config
implementation 'com.github.TheElectronWill.Night-Config:core:3.1.0'
implementation 'com.github.TheElectronWill.Night-Config:json:3.1.0'
The FormatDetector
class is like this
private static final Map<String, Supplier<ConfigFormat<?>>> registry = new ConcurrentHashMap<>();
/**
* Registers a ConfigFormat for a specific fileExtension.
*
* @param fileExtension the file extension
* @param format the config format
*/
public static void registerExtension(String fileExtension, ConfigFormat<?> format) {
registry.put(fileExtension, () -> format);
}
while the JsonFormat
class has this declaration
private static final JsonFormat<FancyJsonWriter> FANCY = new JsonFormat<FancyJsonWriter>() {
@Override
public FancyJsonWriter createWriter() {
return new FancyJsonWriter();
}
@Override
public ConfigParser<Config> createParser() {
return new JsonParser(this);
}
};
static {
FormatDetector.registerExtension("json", FANCY);
}
I've googled about this error and I found that could be due to the missing of some classes in the classpath.
For this reason I've analyzed the apk with Android Studio analyzer and i found that in classes.dex
there are both packages com.electronwill.nightconfig.core
and com.electronwill.nightconfig.json
that are the only two package that I'm using.
I've debugged the application on many phones, and the only that is causing problems has Android 5.1.1. I don't know if other versions of Android can cause problems but I think that the Android version is not the core problem.
Anyone can help me to solve this please? Anyone knows why I'm getting this error even with gradle and only in one phone?
Upvotes: 1
Views: 708
Reputation: 823
NightConfig author here.
Android studio tools do work with lambdas, but older versions of Android don't have the Supplier
class, which is used by my FormatDetector. This is probably what causes the error.
You should use the new NightConfig *_android
modules, which are adapted for older Android APIs.
Upvotes: 1
Reputation: 15
I've solved the issue with a different approach to the problem.
In the db lib I had a ConfigAdapter
class used to wrap some functionalities from Night-Config lib.
I've transformed this class into an interface like this:
/**
* Find and return value at searched key, or default.
*
* @param k The key to search
* @param def The default value if object not found
* @param <T> The value's type
* @return The value at {@code k} or {@code def}
*/
<T> T get(String k, T def);
/**
* Replaces old value with new one, return old.
*
* @param k The value's key
* @param v The value to set
* @param <T> The type of old value
* @return The old value if any, or null
*/
<T> T put(String k, T v);
/**
* Closes the config resource.
*/
void close();
than I on my application I've created the ConfigAdapterImpl
class like this
public class ConfigAdapterImpl implements ConfigAdapter {
private SharedPreferences preferences;
public ConfigAdapterImpl(SharedPreferences _preferences) {
preferences = _preferences;
}
@Override
public <T> T get(String s, T t) {
Map<String, ?> all = preferences.getAll();
// Watch out unchecked cast!
if (all.get(s) != null)
return (T) all.get(s);
else return t;
}
@Override
public <T> T put(String s, T t) {
SharedPreferences.Editor editor = preferences.edit();
T oldVal = get(s, null);
if (t instanceof String)
editor.putString(s, (String) t);
else if (t instanceof Integer)
editor.putInt(s, (Integer) t);
else if (t instanceof Boolean)
editor.putBoolean(s, (Boolean) t);
editor.apply();
return oldVal;
}
@Override
public void close() {
}
}
With this implementation the configurations are handled by the Android preferences manager, and my lib uses them like the Night-Config object.
Upvotes: 0
Reputation: 1661
The library you are using uses a Java 8 feature (lambda) that is not supported by your current setup. The problem is in this line:
registry.put(fileExtension, () -> format);
You will find step-by-step information on how to use Java 8 features in Android in the official docs. This will usually mean upgrading the Android plugin to 3.0.0
or higher and changing the source and target compatibility in your build.gradle
:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Android does not support all Java 8 features; also some features are not available below API 24 (Android 7).
Upvotes: 2
Reputation: 5168
I don't really know graddle, but if I check the maven repository, maybe the depency should be noted as:
compile group: 'com.electronwill.night-config', name: 'core', version: '3.3.1'
see:
https://mvnrepository.com/artifact/com.electronwill.night-config/core/3.3.1
Upvotes: 1