Я написал библиотеку, в которой есть реализация общих предпочтений, в которой она уменьшает количество сообщений об ошибках ANR, которые работали до сегодняшнего дня, одно приложение начало выдавать NoClassDefFoundError
. Этого не происходит ни в каких других приложениях, в которых есть библиотека, и это происходит только при сборке debug , этого не происходит при сборке выпуска. Но это по-прежнему важно, потому что это означает, что я в конечном итоге столкнусь с этой проблемой в будущем.
Обратите внимание, что приложение использовало multidex в течение года при правильной реализации, что означает, что attachBaseContext
переопределено, multiDexEnabled
уже верно et c ...
Следует также упомянуть, что метод getSharedPreferences
переопределен в классе приложения.
public class AppClass extends MultiDexApplication
{
// onCreate and rest of the code
// Return a special SharedPreferences instance
// to apply changes properly.
@Override
public SharedPreferences getSharedPreferences(String name, int mode)
{
return SharedPreferencesWrapper.getInstance(name, super.getSharedPreferences(name, mode));
}
}
APK большой, в нем 4 classes.dex
файлов, и я заметил, что класс SharedPreferences
, который пытается загрузить экземпляр SharedPreferences.Editor
, находится в classes.dex
, тогда как класс, реализующий редактор, находится в classes2.dex
. Я считаю, что это причина того, что программа не работает с таким исключением:
E/AndroidRuntime: FATAL EXCEPTION: firebase-iid-executor
Process: com.test.app, PID: 4226
java.lang.NoClassDefFoundError: com.mylibrary.SharedPreferencesWrapper$SharedPreferencesEditor
at com.mylibrary.SharedPreferencesWrapper.edit(SharedPreferencesWrapper.java:311)
at com.google.firebase.iid.zzaz.zzb(com.google.firebase:firebase-iid@@20.2.1:53)
at com.google.firebase.iid.FirebaseInstanceId.zzl(com.google.firebase:firebase-iid@@20.2.1:70)
at com.google.firebase.iid.FirebaseInstanceId.zza(com.google.firebase:firebase-iid@@20.2.1:159)
at com.google.firebase.iid.zzk.then(com.google.firebase:firebase-iid@@20.2.1)
at com.google.android.gms.tasks.zzg.run(com.google.android.gms:play-services-tasks@@17.0.2:2)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@17.2.1:6)
at java.lang.Thread.run(Thread.java:841)
Я также вижу, что dalvik тоже жалуется на то, что не нашел класс:
E / dalvikvm: не удалось найти класс com.mylibrary.SharedPreferencesWrapper $ SharedPreferencesEditor, на который ссылается метод com.mylibrary.SharedPreferencesWrapper.edit
Здесь он не работает:
public class SharedPreferencesWrapper implements SharedPreferences
{
// rest of the methods
@Override
public Editor edit()
{
// This is where it fails
return new SharedPreferencesEditor();
}
// The wrapper editor class that performs modifying the map
// and writes to files etc...
// This class is not in the same .dex file as the parent class.
// Notice that the class isn't "static", but making it static
// and passing a reference doesn't help either.
public class SharedPreferencesEditor implements SharedPreferences.Editor
{
// some class variables, no static block defined,
// no exceptions are thrown in the constructor.
// It doesn't even reach the constructor.
}
}
В этом блоке кода после создания файла APK я вижу, что SharedPreferencesWrapper
находится в classes.dex
, а SharedPreferencesWrapper$SharedPreferencesEditor
находится в classes2.dex
. Я предполагаю, что он не может найти класс, потому что он находится в другом файле .dex, но я не знаю, как я могу поместить его в тот же файл dex.
Я также заметил, что <clinit>
существует для SharedPreferencesWrapper
в анализаторе APK, но не SharedPreferencesWrapper$SharedPreferencesEditor
. Это кажется мне важным , но я не уверен, как его решить.
Изменить : <clinit>
начал появляться после добавления stati c переменная в класс. По-видимому, это связано с тем, что есть несколько классов, которые не имеют определения <clinit>
, но все равно отлично работают. Однако исключение все еще сохраняется.
То, что я пробовал до сих пор:
- Перемещение класса редактора в его собственный файл и передача самого экземпляра оболочки общих настроек (потому что он необходимо),
- Создание класса редактора c и передача ссылки на объект,
- Использование старой версии gradle и старой версии multi-dex (в настоящее время я использую 2.0. 1),
- Очистка проекта, повторная сборка проекта, удаление папок сборки, удаление кешей, аннулирование кеша и параметр перезапуска, повторный импорт проекта из git et c ... всего этого.
Есть решение? Я понятия не имею, что делать. Любая помощь приветствуется, большое спасибо.