迁移到androidx后,我的android应用程序在启动时崩溃并显示以下日志
1579308665.952 E: FATAL EXCEPTION: main
Process: com.lezyne.gpsally, PID: 26998
java.lang.RuntimeException: Unable to instantiate application com.lezyne.gpsally.LezyneLinkApplication: java.lang.ClassNotFoundException: Didn't find class "com.lezyne.gpsally.LezyneLinkApplication" on path: DexPathList[[zip file "/data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk"],nativeLibraryDirectories=[/data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/lib/arm64, /data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]
at android.app.LoadedApk.makeApplication(LoadedApk.java:971)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5796)
at android.app.ActivityThread.-wrap1(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1666)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:251)
at android.app.ActivityThread.main(ActivityThread.java:6572)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.lezyne.gpsally.LezyneLinkApplication" on path: DexPathList[[zip file "/data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk"],nativeLibraryDirectories=[/data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/lib/arm64, /data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.Instrumentation.newApplication(Instrumentation.java:1087)
at android.app.LoadedApk.makeApplication(LoadedApk.java:965)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5796)
at android.app.ActivityThread.-wrap1(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1666)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:251)
at android.app.ActivityThread.main(ActivityThread.java:6572)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Suppressed: java.io.IOException: Failed to open dex files from /data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk because: Failure to verify dex file '/data/app/com.lezyne.gpsally-39sfIUY5mcmCi0Ff5YTHOw==/base.apk': Bad method handle type 7
at dalvik.system.DexFile.openDexFileNative(Native Method)
at dalvik.system.DexFile.openDexFile(DexFile.java:353)
at dalvik.system.DexFile.<init>(DexFile.java:100)
at dalvik.system.DexFile.<init>(DexFile.java:74)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:374)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:337)
at dalvik.system.DexPathList.<init>(DexPathList.java:157)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65)
at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64)
at com.android.internal.os.PathClassLoaderFactory.createClassLoader(PathClassLoaderFactory.java:43)
at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:69)
at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:36)
at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:676)
at android.app.LoadedApk.getClassLoader(LoadedApk.java:709)
at android.app.LoadedApk.getResources(LoadedApk.java:936)
at android.app.ContextImpl.createAppContext(ContextImpl.java:2242)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5703)
... 8 more
我的gradle依赖关系如下:
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(dir: "src/main/jniLibs", include: '*.so')
implementation fileTree(dir: "lib", include: '*.so')
apply plugin: 'findbugs'
implementation project(':android-crop')
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.nispok:snackbar:2.11.+'
implementation 'com.rengwuxian.materialedittext:library:1.8.2'
implementation 'com.github.vajro:MaterialDesignLibrary:1.6'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.mcxiaoke.volley:library-aar:1.0.0'
implementation 'org.apache.commons:commons-lang3:3.3.2'
implementation 'com.androidadvance:topsnackbar:1.1.1'
implementation 'com.googlecode.json-simple:json-simple:1.1'
implementation 'com.jakewharton:disklrucache:2.0.2'
implementation 'de.greenrobot:greendao:1.3.7'
implementation 'net.danlew:android.joda:2.5.1'
implementation 'commons-collections:commons-collections:3.2.1'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.squareup.picasso:picasso:2.5.0'
implementation 'com.facebook.android:facebook-android-sdk:4.24.0'
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-places:17.0.0'
implementation 'com.google.guava:guava:24.1-jre'
implementation 'com.sothree.slidinguppanel:library:3.3.1'
implementation 'com.google.android:flexbox:0.3.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
清单的应用标签看起来像
<application
android:name=".LezyneLinkApplication"
android:icon="@drawable/ic_launcher2"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
问题似乎与该问题有关Application class not found after upgrading to Android X相同,该评论建议干净的构建并使缓存无效,并且此帖子https://stackoverflow.com/a/54024154/1247248指示手动删除构建文件夹。不幸的是,这些都不起作用。
我也找到了这个答案https://stackoverflow.com/a/29210004/1247248,所以我尝试关闭multiDex并将minSdk提高到26。
任何建议将不胜感激。
-----编辑----
1,是的,我确实尝试过使缓存无效并重新启动。
应用程序类定义为
package com.lezyne.gpsally;
import android.app.Application;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.os.Environment;
import android.util.LruCache;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import com.lezyne.gpsally.api.requests.rides.GetRidesListApiRequest;
import com.lezyne.gpsally.tools.RoutingProfile;
import com.lezyne.gpsally.tools.Settings;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import net.danlew.android.joda.JodaTimeAndroid;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import lezyne.com.gpsally.sql.DaoMaster;
import lezyne.com.gpsally.sql.DaoSession;
import lezyne.com.gpsally.sql.PlaceDao;
import lezyne.com.gpsally.sql.PlaceSearchKeyDao;
import lezyne.com.gpsally.sql.SqlRideDao;
import lezyne.com.gpsally.sql.SqlStravaAthleteDao;
import lezyne.com.gpsally.sql.SqlStravaSegmentDao;
public class LezyneLinkApplication extends Application {
private static WeakReference<Context> mContext;
public boolean hasShownFirmwarePopup = false;
public static String resourceString(int id)
{
return mContext.get().getString(id);
}
static public final boolean isMonkeyTestBuild=false;
static public boolean helpScreenShowing=false;
public enum TrackerName {
APP_TRACKER, // Tracker used only in this app.
GLOBAL_TRACKER, // Tracker used by all the apps from a company. eg: roll-up tracking.
ECOMMERCE_TRACKER, // Tracker used by all ecommerce transactions from a company.
}
public static Typeface customFontTypeface;
private DaoSession daoSession;
public RequestQueue requestQue;
public ImageLoader imageLoader;
private Picasso picasso;
private void copyFromAssets(String name)
{
try {
//Also get the font file
File file = new File(getFilesDir(),name);
if (file.exists()) file.delete();
InputStream inputStream = getAssets().open(name);
FileOutputStream fileOutput = new FileOutputStream(file);
int bufferLength = 0;
byte[] buffer = new byte[1024];
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
private void copyFromAssets(String name, String dir)
{
try {
//Also get the font file
File dirFile = new File(getFilesDir(),dir);
dirFile.mkdir();
File file = new File(dirFile,name);
if (file.exists()) file.delete();
InputStream inputStream = getAssets().open(dir+"/"+name);
FileOutputStream fileOutput = new FileOutputStream(file);
int bufferLength = 0;
byte[] buffer = new byte[1024];
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
@Override
public void onCreate() {
super.onCreate();
mContext = new WeakReference<Context>(getApplicationContext());
JodaTimeAndroid.init(this);
setupDatabase();
ArrayList<RoutingProfile> profiles = RoutingProfile.loadRoutingProfiles(this);
for (RoutingProfile profile : profiles)
{
copyFromAssets(profile.xmlFile,"USA");
copyFromAssets(profile.xmlFile,"Germany");
copyFromAssets(profile.xmlFile,"Japan");
copyFromAssets(profile.xmlFile,"UK");
}
copyFromAssets("2593-UnDotum.ttf");
copyFromAssets("osm-style.xml");
requestQue = Volley.newRequestQueue(this);
imageLoader = new ImageLoader(requestQue,new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
GetRidesListApiRequest.syncRides(this,new GetRidesListApiRequest.SyncCompletionListener() {
@Override
public void fail(boolean invalidPassword) {
//TODO: Initiate retry logic if the first load fails
}
@Override
public void success() {
}
});
File userDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),"LezyneGpsAlly/route");
userDir.mkdirs();
Settings settings = new Settings(this);
userDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),"LezyneGpsAlly/"+settings.username());
userDir.mkdirs();
picasso = new Picasso
.Builder(this)
.downloader(new OkHttpDownloader(getFilesDir()
,10000000))//10,000,000 10 Meg image cache
.build();
overrideFont(getApplicationContext(), "SERIF", "Helvetica.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
overrideFont(getApplicationContext(), "DEFAULT", "Helvetica.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
overrideFont(getApplicationContext(), "SANS_SERIF", "Helvetica.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
overrideFont(getApplicationContext(), "MONOSPACE", "Helvetica.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
}
public static Picasso picasso(Context context){
LezyneLinkApplication self = (LezyneLinkApplication)context.getApplicationContext();
return self.picasso;
}
private void setupDatabase() {
try {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "lezyne-db2", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
} catch (RuntimeException e)
{
File file = new File("lezyne-db2");
file.delete();
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "lezyne-db2", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
}
public DaoSession getDaoSession() {
return daoSession;
}
public static SqlRideDao getSqlRideDao(Context context) {
return ((LezyneLinkApplication) context.getApplicationContext()).getDaoSession().getSqlRideDao();
}
public static SqlStravaAthleteDao getStravaAthleteDao(Context context) {
return ((LezyneLinkApplication) context.getApplicationContext()).getDaoSession().getSqlStravaAthleteDao();
}
public static SqlStravaSegmentDao getStravaSegmentDao(Context context) {
return ((LezyneLinkApplication) context.getApplicationContext()).getDaoSession().getSqlStravaSegmentDao();
}
public static PlaceDao getPlaceDao(Context context) {
return ((LezyneLinkApplication) context.getApplicationContext()).getDaoSession().getPlaceDao();
}
public static PlaceSearchKeyDao getPlaceSearchKeyDao(Context context) {
return ((LezyneLinkApplication) context.getApplicationContext()).getDaoSession().getPlaceSearchKeyDao();
}
/**
* Using reflection to override default typeface
* NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
* @param context to work with assets
* @param defaultFontNameToOverride for example "monospace"
* @param customFontFileNameInAssets file name of the font from assets
*/
public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
try {
customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);
final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible(true);
defaultFontTypefaceField.set(null, customFontTypeface);
} catch (Exception e) {
// Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
}
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
}
}
-编辑--
我终于按照本文https://stackoverflow.com/a/50983181/1247248中与Java 8有关的说明进行了工作