我们遇到了一个非常奇怪的崩溃,指向系统类。它出现在应用程序启动时。
致命异常:java.lang.RuntimeException: 无法启动活动 ComponentInfo {com.myapp.android / com.myapp.android.main.BaseMainActivity}: java.lang.RuntimeException:无法创建应用程序 com.myapp.android.main.MyApp:java.lang.NullPointerException 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app.ActivityThread.main(ActivityThread.java:5333)处 在java.lang.reflect.Method.invokeNative(Method.java)处 在java.lang.reflect.Method.invoke(Method.java:515)处 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:828)处 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)处 在dalvik.system.NativeStart.main(NativeStart.java)处,由java.lang.RuntimeException引起:无法创建应用程序 com.myapp.android.main.MyApp:java.lang.NullPointerException 在android.app.LoadedApk.makeApplication(LoadedApk.java:529)处 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app.ActivityThread.main(ActivityThread.java:5333)处 在java.lang.reflect.Method.invokeNative(Method.java)处 在java.lang.reflect.Method.invoke(Method.java:515)处 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:828)处 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)处 在dalvik.system.NativeStart.main(NativeStart.java)处,由java.lang.NullPointerException引起 在android.content.Context.getString(Context.java:343)处 在com.myapp.android.api.singletons.AppTrackingInstance.initAdjust(AppTrackingInstance.java:114)处 在com.myapp.android.api.singletons.AppTrackingInstance。(AppTrackingInstance.java:92)处 在com.myapp.android.injection.modules.ApplicationScopeModule.provideAppTrackingInstance(ApplicationScopeModule.java:326)处 在com.myapp.android.injection.modules.ApplicationScopeModule $$ ModuleAdapter $ ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule $$ ModuleAdapter.java:1618)处 在com.myapp.android.injection.modules.ApplicationScopeModule $$ ModuleAdapter $ ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule $$ ModuleAdapter.java:1552)处 在dagger.internal.Linker $ SingletonBinding.get(Linker.java:364)处 在com.myapp.android.main.MyApp $$ InjectAdapter.injectMembers(MyApp $$ InjectAdapter.java:70)处 在com.myapp.android.main.MyApp $$ InjectAdapter.injectMembers(MyApp $$ InjectAdapter.java:23)处 在dagger.ObjectGraph $ DaggerObjectGraph.inject(ObjectGraph.java:281)处 在com.myapp.android.main.MyApp $ 1.run(MyApp.java:57)处 在com.myapp.android.main.MyApp.onCreate(MyApp.java:51)处 在android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)处 在android.app.LoadedApk.makeApplication(LoadedApk.java:526)处 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app 我们使用
致命异常:java.lang.RuntimeException: 无法启动活动 ComponentInfo {com.myapp.android / com.myapp.android.main.BaseMainActivity}: java.lang.RuntimeException:无法创建应用程序 com.myapp.android.main.MyApp:java.lang.NullPointerException 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app.ActivityThread.main(ActivityThread.java:5333)处 在java.lang.reflect.Method.invokeNative(Method.java)处 在java.lang.reflect.Method.invoke(Method.java:515)处 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:828)处 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)处 在dalvik.system.NativeStart.main(NativeStart.java)处,由java.lang.RuntimeException引起:无法创建应用程序 com.myapp.android.main.MyApp:java.lang.NullPointerException 在android.app.LoadedApk.makeApplication(LoadedApk.java:529)处 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app.ActivityThread.main(ActivityThread.java:5333)处 在java.lang.reflect.Method.invokeNative(Method.java)处 在java.lang.reflect.Method.invoke(Method.java:515)处 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:828)处 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)处 在dalvik.system.NativeStart.main(NativeStart.java)处,由java.lang.NullPointerException引起 在android.content.Context.getString(Context.java:343)处 在com.myapp.android.api.singletons.AppTrackingInstance.initAdjust(AppTrackingInstance.java:114)处 在com.myapp.android.api.singletons.AppTrackingInstance。(AppTrackingInstance.java:92)处 在com.myapp.android.injection.modules.ApplicationScopeModule.provideAppTrackingInstance(ApplicationScopeModule.java:326)处 在com.myapp.android.injection.modules.ApplicationScopeModule $$ ModuleAdapter $ ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule $$ ModuleAdapter.java:1618)处 在com.myapp.android.injection.modules.ApplicationScopeModule $$ ModuleAdapter $ ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule $$ ModuleAdapter.java:1552)处 在dagger.internal.Linker $ SingletonBinding.get(Linker.java:364)处 在com.myapp.android.main.MyApp $$ InjectAdapter.injectMembers(MyApp $$ InjectAdapter.java:70)处 在com.myapp.android.main.MyApp $$ InjectAdapter.injectMembers(MyApp $$ InjectAdapter.java:23)处 在dagger.ObjectGraph $ DaggerObjectGraph.inject(ObjectGraph.java:281)处 在com.myapp.android.main.MyApp $ 1.run(MyApp.java:57)处 在com.myapp.android.main.MyApp.onCreate(MyApp.java:51)处 在android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)处 在android.app.LoadedApk.makeApplication(LoadedApk.java:526)处 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)处 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)处 在android.app.ActivityThread.access $ 800(ActivityThread.java:151)处 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1342)处 在android.os.Handler.dispatchMessage(Handler.java:110)处 在android.os.Looper.loop(Looper.java:193)处 在android.app 我们使用
Dagger 1
,我们的应用程序使用了 multidex
。
Dagger 模块:
@Module(
library = true,
injects = {
MyApp.class
}
)
public class ApplicationScopeModule {
private final MyApp application;
public ApplicationScopeModule(MyApp application) {
this.application = application;
}
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return application.getApplicationContext();
}
@Provides
@Singleton
AppTrackingInstance provideAppTrackingInstance(@ForApplication Context context) {
return new AppTrackingInstance(context);
}
}
MyApp类:
package com.myapp.android.main;
public class MyApp extends MultiDexApplication {
private ObjectGraph objectGraph;
@Inject
AppTrackingInstance appTrackingInstance;
@Override
public void onCreate() {
super.onCreate();
// workaround for multi-dex enabled projects
// taken from http://frogermcs.github.io/MultiDex-solution-for-64k-limit-in-Dalvik/
// multi-dex separates dex files, and some classes going to additional dex file.
// Additional .dex files are loaded in Application.attachBaseContext(Context) method
// (by MultiDex.install(Context) invokation). It means, that before this moment
// we can’t use classes from them. So i.e. we cannot declare static fields
// with types attached out of main .dex file.
// Otherwise we’ll get java.lang.NoClassDefFoundError.
//
// the issue should be fixed on the Android level
//
new Runnable() {
@Override
public void run() {
initFabric();
objectGraph = ObjectGraph.create(getModules().toArray());
objectGraph.inject(MyApp.this);
appTrackingInstance.trackAppLaunch();
}
}.run();
}
private void initFabric() {
Fabric.with(MyApp.this, new Crashlytics.Builder().core(new CrashlyticsCore.Builder().disabled(BuildConfig.IS_DEBUG_BUILD).build()).build());
}
public List<Object> getModules() {
return Arrays.<Object>asList(new ApplicationScopeModule(this));
}
public ObjectGraph getObjectGraph() {
return objectGraph;
}
}
AppTrackingInstance类:
package com.myapp.android.api.singletons;
public class AppTrackingInstance {
Context context;
public AppTrackingInstance(Context context) {
this.context = context;
initAdjust();
}
private void initAdjust() {
// "broken" context here
String variable = context.getString(R.string.adjust_variable);
}
}
从实现和堆栈跟踪中,我们得到了崩溃原因:
由 java.lang.NullPointerException 引起 at android.content.Context.getString(Context.java:343)
这意味着当用户启动应用程序时,Dagger
将 "损坏的" 应用程序上下文注入到 AppTrackingInstance
中。这怎么可能呢?
我们广泛使用 Dagger
,并且在许多地方注入上下文而没有问题。只有在某些特定情况下(我无法复制)应用程序由于上下文错误而在启动时崩溃。
崩溃出现在不同的设备和操作系统版本上,主要是在4.x操作系统上,但也偶尔出现在某些5.0.2操作系统版本上:
由于应用程序启动时崩溃,我进行了大量调查,并发现了相似的问题(1,2,应用程序更新时崩溃)。
然后我拿了一些测试设备 - Nexus 4(Android 5.0.1),三星S3(Android 4.3) - 并尝试重现这个问题:
- 在有/没有网络连接的情况下打开应用程序
- 打开/关闭应用程序50次
- 打开应用程序,从Play市场卸载,再从Play市场安装并重新打开
- 从不同的深度链接打开应用程序
- 从移动网站打开应用程序
- 从Play市场安装应用程序,不要打开它。从深度链接进行冷启动
- 从推送通知中打开应用程序
- 使用不同的语言环境打开应用程序
- 从最近使用列表中打开应用程序
- 清除应用程序数据并打开
- 安装旧的生产版本,手动更新到最新的生产版本
- 安装旧的生产版本,从Play市场更新到最新版本
- 浏览应用程序XXX分钟,然后从Play市场更新到最新版本
这些测试过程中没有出现任何崩溃,但是崩溃仍然会在用户设备上出现,我不知道为什么会发生。
可能是由于multidex
或Dagger 1
导致的,但我不能确定。
BuildConfig
变量和flavors。 - Veaceslav GaidarjiR.string.adjust_variable
已经正确翻译了吗?另外,为了重现崩溃问题,你可以尝试使用其他语言。 - David Medenjak