【问题标题】:NPE at intent.getStringExtra when launched from home screen从主屏幕启动时,intent.getStringExtra 处的 NPE
【发布时间】:2015-08-27 18:18:42
【问题描述】:

在某些运行 Android 5.0 及更高版本的设备上,我的应用在从主屏幕打开时会崩溃,并显示以下消息:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at com.imincode.menitiplus.MainActivity.loadSelectedIntent(MainActivity.java:229)
at com.imincode.menitiplus.MainActivity.onNewIntent(MainActivity.java:213)
at android.app.Instrumentation.callActivityOnNewIntent(Instrumentation.java:1233)
at android.app.ActivityThread.deliverNewIntents(ActivityThread.java:2462)
at android.app.ActivityThread.performNewIntents(ActivityThread.java:2475)
at android.app.ActivityThread.handleNewIntent(ActivityThread.java:2484)
at android.app.ActivityThread.access$1600(ActivityThread.java:148)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)

这是导致错误的代码。

private void loadSelectedIntent(Intent intent){
        if ((intent != null) && (intent.getExtras() != null)){
            Fragment fragment = null;
            FragmentManager fManager = this.getSupportFragmentManager();
            FragmentTransaction transaction = fManager.beginTransaction();
            Bundle bundle;
            if (intent.getStringExtra("intentCaller").equals("expensesRecurring")){
                fragment = new MenuNotifications();
                bundle = new Bundle();
                bundle.putString("tab", "0");
                fragment.setArguments(bundle);
                transaction.replace(R.id.container, fragment, "fragmentMenuNotifications");
                transaction.addToBackStack(null);
                transaction.commit();
            }else if (intent.getStringExtra("intentCaller").equals("creditCard")){
                fragment = new MenuNotifications();
                bundle = new Bundle();
                bundle.putString("tab", "1");
                fragment.setArguments(bundle);
                transaction.replace(R.id.container, fragment, "fragmentMenuNotifications");
                transaction.addToBackStack(null);
                transaction.commit();
            }else if (intent.getStringExtra("intentCaller").equals("locationAlert")){
                fragment = new MenuNotifications();
                bundle = new Bundle();
                bundle.putString("tab", "2");
                fragment.setArguments(bundle);
                transaction.replace(R.id.container, fragment, "fragmentLocationAlert");
                transaction.addToBackStack(null);
                transaction.commit();
            }

        }
    }

具体来说,抛出错误的行是

if (intent.getStringExtra("intentCaller").equals("expensesRecurring"))

loadSelectedIntent 将从 MainActivity 中的 2 个位置调用。 第一个:

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        loadSelectedIntent(intent);
    }

第二个:

@Override
    protected void onResume() {
        super.onResume();
        Intent isThereAnyIntentHere = getIntent();
        if ((isThereAnyIntentHere != null) && (isThereAnyIntentHere.getExtras() != null)){
            loadSelectedIntent(isThereAnyIntentHere);
        }
    }

请注意,只有当用户尝试通过单击主屏幕上的应用图标来启动应用时,才会出现此错误。如果用户在 Play Store 中点击“打开应用”,应用就可以毫无问题地启动。

为什么此错误仅发生在选定设备上,并且仅在从主屏幕启动时发生?

我想通过输入代码

if ((intent != null) && (intent.getExtras() != null))

它肯定会确保 intent.getStringExtra 不为空?

【问题讨论】:

    标签: android


    【解决方案1】:

    intent.getExtras() != null 行仅保证您的意图中有某种额外内容,但这不仅限于您设置的额外内容。启动意图可能包含任何内容。

    问题是intent.getStringExtra() 可以返回null,如果它没有找到您要查找的额外名称。一种快速而肮脏的解决方案是将您的 if 语句颠倒如下:

    if ("expensesRecurring".equals(intent.getStringExtra("intentCaller")))
    

    你也可以检查你的额外内容的无效性,然后像这样消费它:

    if (intent.getStringExtra("intentCaller") != null && intent.getStringExtra("intentCaller").equals("expensesRecurring"))
    

    【讨论】:

    • 我没有按照您的建议进行操作,而是将其进一步提高,使其成为 if ((intent != null) && (intent.getExtras() != null) && (intent.getStringExtra("intentCaller ") != null)) 。应该不是问题吧?现在无法测试。需要先拿到引发此错误的手机。
    • 另一个重要的问题是......为什么它只发生在大约 5% 的手机上?其他 95% 的工作正常工作,但从未抛出此错误。
    • 也许某些版本的android在那里添加了一些额外的东西?我在我的应用程序中遇到了一些虚假的意图,并因此开始进行额外的检查。总之,恐怕我知道的不够多,无法回答这个问题。
    【解决方案2】:

    我想通过输入代码

    if ((intent != null) && (intent.getExtras() != null))
    

    它肯定会确保 intent.getStringExtra 不为空?

    不,您知道 extras 捆绑包不是 null,但您尚未确定特定密钥存在。 getStringExtra documentation

    所以从getExtras documentation我们知道,如果没有任何额外的,它将返回null。

    【讨论】:

    • 感谢您的解释。赞成您的答案,但 Edson Menegatti 已经详细地写了答案,所以要接受他的答案是正确的(在我设法测试它之后)
    猜你喜欢
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多