gpt4 book ai didi

android - android.content.Context.getString 中的 NPE 导致应用程序在启动时崩溃

转载 作者:行者123 更新时间:2023-12-03 03:01:53 31 4
gpt4 key购买 nike

我们遇到了一次非常奇怪的崩溃,它指向系统类。它出现在应用程序启动时。

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.android/com.myapp.android.main.BaseMainActivity}: java.lang.RuntimeException: Unable to create application com.myapp.android.main.MyApp: java.lang.NullPointerException at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5333) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644) at dalvik.system.NativeStart.main(NativeStart.java) Caused by java.lang.RuntimeException: Unable to create application com.myapp.android.main.MyApp: java.lang.NullPointerException at android.app.LoadedApk.makeApplication(LoadedApk.java:529) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5333) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644) at dalvik.system.NativeStart.main(NativeStart.java) Caused by java.lang.NullPointerException at android.content.Context.getString(Context.java:343) at com.myapp.android.api.singletons.AppTrackingInstance.initAdjust(AppTrackingInstance.java:114) at com.myapp.android.api.singletons.AppTrackingInstance.(AppTrackingInstance.java:92) at com.myapp.android.injection.modules.ApplicationScopeModule.provideAppTrackingInstance(ApplicationScopeModule.java:326) at com.myapp.android.injection.modules.ApplicationScopeModule$$ModuleAdapter$ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule$$ModuleAdapter.java:1618) at com.myapp.android.injection.modules.ApplicationScopeModule$$ModuleAdapter$ProvideAppTrackingInstanceProvidesAdapter.get(ApplicationScopeModule$$ModuleAdapter.java:1552) at dagger.internal.Linker$SingletonBinding.get(Linker.java:364) at com.myapp.android.main.MyApp$$InjectAdapter.injectMembers(MyApp$$InjectAdapter.java:70) at com.myapp.android.main.MyApp$$InjectAdapter.injectMembers(MyApp$$InjectAdapter.java:23) at dagger.ObjectGraph$DaggerObjectGraph.inject(ObjectGraph.java:281) at com.myapp.android.main.MyApp$1.run(MyApp.java:57) at com.myapp.android.main.MyApp.onCreate(MyApp.java:51) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007) at android.app.LoadedApk.makeApplication(LoadedApk.java:526) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5333) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644) at 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);
}
}

从实现和堆栈跟踪中我们得到崩溃原因:

Caused by java.lang.NullPointerException at android.content.Context.getString(Context.java:343)

这意味着当用户启动应用程序时,Dagger 会注入(inject)到 AppTrackingInstance “损坏的”应用程序上下文中。这怎么可能呢?我们广泛使用Dagger,并且这个上下文注入(inject)到很多地方都没有问题。仅在某些特定情况下(我无法重现)应用程序会因上下文损坏而在启动时崩溃。

崩溃出现在不同的设备和操作系统版本上,主要是在 4.x 操作系统上,但在某些 5.0.2 操作系统版本上也很少出现: 1 screenshot 2 screenshot 3 screenshot

由于这是应用程序启动时的崩溃,我对此进行了很多调查并发现了非常相似的问题( 12app crash on update )。

我使用了一些测试设备 - Nexus 4 (Android 5.0.1)、Samsung S3 (Android 4.3) - 并尝试重现该问题:

  • 在有/没有互联网连接的情况下打开应用程序
  • 打开/关闭应用程序 50 倍
  • 打开应用程序,从游戏市场卸载,从游戏市场安装回来并再次打开
  • 从不同的深层链接打开应用程序
  • 从移动网站打开应用程序
  • 从游戏市场安装应用程序,但不要打开它。从深层链接冷启动
  • 通过推送通知打开应用程序
  • 使用不同区域设置打开应用程序
  • 打开最近的申请
  • 清除应用数据并打开
  • 安装旧的生产版本,手动更新到最新的生产版本
  • 安装旧的生产版本,从游戏市场更新到最新版本
  • 浏览应用程序 XXX 分钟,然后从游戏市场更新到最新版本

在此测试期间发生了 0 次崩溃,但崩溃仍然出现在用户设备上,我不知道为什么会发生。

可能是由于 multidexDagger 1 造成的,但我不能自信地说。

最佳答案

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{.......

我曾经有过这样的堆栈跟踪,听起来绝对没有那么可怕。 这意味着,MyApponCreate()中抛出了异常。

context.getResources(),您提供给 AppTrackingInstance 类的内容为 null,导致崩溃。

为什么 getResources() 返回 null (=> 发生崩溃)对我来说听起来像是竞争条件,尤其是,这种情况并非每次都会发生(据我从帖子中了解到)。

由于我也在使用 Dagger1 和 MultiDex 并且没有这个问题,我可以猜测,可能的解决方案是开始延迟初始化 ObjectGraph

这个 fragment 对我来说就像一个魅力:

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 中 - 我在应用程序中使用的每个 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
}
}
}

它应该对您有帮助,因为在第一个 Activity(ActivityBase 的扩展)的 onCreate() 期间,资源肯定已经定义了,因此 getResources() 不应返回 null。

另外两个选项是

  • 避免多重索引
  • 当你的上下文已满时(但是,一旦 getResources() 失败 - 谁知道还会出现什么问题,我担心它会导致其他崩溃 - 恕我直言)

希望对您有帮助。

关于android - android.content.Context.getString 中的 NPE 导致应用程序在启动时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34785907/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com