我们有一个非常奇怪的崩溃,它指向系统类。它出现在应用程序启动时。
致命异常: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) at 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) at 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) at 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) at 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) at 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) at 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.ActivityThread.main(ActivityThread.java:5333) at 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)
我们使用Dagger 1
,我们的应用是multidex
- ed。
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引起 在android.content.Context.getString(Context.java:343)
这意味着当用户启动应用程序时,Dagger
会注入AppTrackingInstance
&#34;已损坏&#34;应用背景。怎么可能?
我们广泛使用Dagger
,并且在许多地方注入了这种上下文而没有任何问题。仅在某些特定情况下(我无法重现)应用程序因启动环境而崩溃。
崩溃出现在不同的设备和操作系统版本上,主要是在4.x操作系统上,但在某些5.0.2操作系统版本上也很少出现:
由于应用程序启动时出现崩溃,我已对其进行了大量调查,发现了非常类似的问题(1,2,app crash on update)。
我采用了一些测试设备 - Nexus 4(Android 5.0.1),三星S3(Android 4.3) - 并试图重现这个问题:
0崩溃,但崩溃仍然出现在用户设备上,我不知道它为什么会发生。
可能是由multidex
或Dagger 1
引起的,但我无法自信地说。
答案 0 :(得分:2)
致命异常:java.lang.RuntimeException:无法启动活动 ComponentInfo {.......
我有一次这样的堆栈跟踪,听起来绝对不是那么可怕。 这意味着,onCreate()
的MyApp
引发了异常。
即。 context.getResources()
,您提供给AppTrackingInstance
类的内容为null,导致崩溃。
为什么getResources()
为我返回null
(=&gt;崩溃)的原因听起来像竞争条件,尤其是因为它不是每次都发生(来自我从帖子中了解到的)。
由于我也在使用Dagger1和MultiDex,我没有这个问题,我猜,可能的解决方案是开始懒惰地初始化ObjectGraph
。
这个片段对我来说就像一个魅力:
public final class ApplicationScopeModule {
private final Context applicationContext;
public ApplicationScopeModule(final Context applicationContext) {
this.applicationContext = applicationContext;
}
@Provides
@Singleton
@SuppressWarnings("unused") // invoked by Dagger
public Context provideApplicationContext() {
return applicationContext;
}
@Provides
@Singleton
@SuppressWarnings("unused") // invoked by Dagger
public Analytics provideAnalytics(Context context) {
return new DefaultAnalytics(context);
}
//...<other providers>..
}
MyApplication
,扩展了Application
:
public class MyApplication extends Application {
private ObjectGraph objectGraph;
private final Object lock = new Object();
@Override
public void onCreate() {
super.onCreate();
}
protected List<Object> getModules() {
final ArrayList<Object> modules = new ArrayList<>();
modules.add(new ApplicationScopeModule(getApplicationContext()));
return modules;
}
public ObjectGraph getApplicationGraph() {
synchronized (lock) {
if (objectGraph == null) {
objectGraph = ObjectGraph.create(getModules().toArray());
}
return objectGraph;
}
}
}
然后在ActivityBase
中 - 我在app中使用的每个Activity
的基类:
public abstract class FragmentActivityBase extends ActionBarActivity {
private ObjectGraph activityGraph;
@Override
protected void onCreate(final Bundle savedInstanceState) {
inject(this);
super.onCreate(savedInstanceState);
}
public void inject(final Object object) {
try {
if (activityGraph == null) {
final MyApplication application = (MyApplication) getApplication();
activityGraph = application.getApplicationGraph();
}
activityGraph.inject(object);
} catch (IllegalArgumentException e) {
//log error
}
}
}
它应该对您有所帮助,因为在第一个onCreate()
Activity
的扩展名ActivityBase
期间,资源肯定已经定义,因此getResources()
不应该返回null
另外两个选项是
我希望,这有帮助。
答案 1 :(得分:0)
似乎没有初始化Context对象。此调用出错:
@Provides
@Singleton
AppTrackingInstance provideAppTrackingInstance(@ForApplication Context context) {
return new AppTrackingInstance(context);
}
验证此方法中的上下文是否为null。我相信问题就在那里。