Anton
Anton

Reputation: 570

Local variable become null (Android)

from my android application I got a strange error message: NullPointerException (in last line code).

public static Integer getDefaultCalendarId(Context context) {
    String calendarInSettings = PrefsHelper.getDefaultCalendar(context);
    Calendar calendar = PrefsHelper.getCalendarFromPrefKey(context, calendarInSettings);
    if (calendar == null || !calendar.canEventEdit()) {
        return calculateDefaultCalendar(context);
    }
    boolean isChecked = false;
    for (Calendar checkedCalendar : PrefsHelper.getCheckedCalendars(context)) {
        if (checkedCalendar.getId() == calendar.getId()) {
            isChecked = true;
            break;
        }
    }

    (1114 line) return isChecked ? calendar.getId() : calculateDefaultCalendar(context); // NullPointerException
}

Exception occurred on Samsung GT-N7000.

How could this happen?

Update:

calculateDefaultCalendar can return null, but getDefaultCalendarId return value - Integer (nullable)!

Stacktrace:

java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx.trial/xxx.view.EventEditActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
at android.app.ActivityThread.access$600(ActivityThread.java:127)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:986)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:753)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at xxx.EventHelper.java.lang.Integer getDefaultCalendarId(android.content.Context)(SourceFile:1114)
at xxx.view.EventEditActivity.void onCreate(android.os.Bundle)(SourceFile:306)
at android.app.Activity.performCreate(Activity.java:4470)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
... 11 more
java.lang.NullPointerException
at xxx.EventHelper.java.lang.Integer getDefaultCalendarId(android.content.Context)(SourceFile:1114)
at xxx.view.EventEditActivity.void onCreate(android.os.Bundle)(SourceFile:306)
at android.app.Activity.performCreate(Activity.java:4470)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
at android.app.ActivityThread.access$600(ActivityThread.java:127)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:986)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:753)
at dalvik.system.NativeStart.main(Native Method)

update 2

calculateDefaultCalendar:

private static Integer calculateDefaultCalendar(final Context context) {
    String account = PrefsHelper.getAccountName(context);
    if (account != null) {
        for (Calendar calendar : PrefsHelper.getCheckedCalendars(context)) {
            if (calendar.getOwnerAccount().equals(account) && calendar.canEventEdit()) {
                return calendar.getId();
            }
        }
    }

    for (Calendar calendar : PrefsHelper.getCheckedCalendars(context)) {
        if (calendar.canEventEdit()) {
            return calendar.getId();
        }
    }

    return null;
}

Update 3

The error repeats regularly on:

product / android version

LT26i_1257-3921 / 4.0.4

MK16i_1249-8137 / 4.0.4

SCH-I500 / 2.3.5

SCH-I500 / 4.0.4

Upvotes: 1

Views: 777

Answers (3)

Code-Apprentice
Code-Apprentice

Reputation: 83577

If calender.getId() returns an int, you are running into issues with auto-boxing. Since the most likely culprit is the return value of calculateDefaultCalendar(), most likely the compiler is trying to auto-unbox the null return value. To fix this, you can simply manually box the return value of calender.getId() with Integer.valueOf(calendar.getId()). This will ensure that the returned value is boxed as an Integer and then the return value of calculateDefaultCalendar() won't be auto-unboxed.

Upvotes: 1

Miserable Variable
Miserable Variable

Reputation: 28761

return isChecked ? calendar.getId() : calculateDefaultCalendar(context);

I suspect calendar.getId() returns int not Integer. This would mean that calculateDefaultCalendar(context), which returns an Integer, first needs to be auto-unboxed to int and the resulting int has to be auto-boxed to an Integer. If isChecked is false and calculateDefaultCalendar(context) returns null then this will result in NPE. See the following simplified equivalent code, for example:

class N2 {
  public static void main(String args[])
  {
    System.out.println(check()); 
  }
  static Integer check()
  {
    return false ? 0 : fNull(); 
  }
  static Integer fNull() 
  {
    return null;
  }
}

A search for relevant terms auto-boxing, NullPointerException and ternary brings up many similar hots.

Upvotes: 3

Ben
Ben

Reputation: 57297

Stating the obvious, one of these is null:

  • calendar (eliminated, called successfully previously in code)

  • The return from getId() (eliminated, called successfully previously in code)

  • The return from calculateDefaultCalendar

  • context (eliminated, called successfully previously in code)

Looks like calculateDefaultCalendar is returning null for some reason. We'll need the code for that before we can help any more.


OK, now that we have calculateDefaultCalendar, we can keep eliminating. From your comment, it looks like the problem is that these two conditional statements

if (calendar.getOwnerAccount().equals(account) && calendar.canEventEdit()) {
    return calendar.getId();
}

and

if (calendar.canEventEdit()) {
    return calendar.getId();
}

are not evaluating to true (otherwise they would return an integer, you say). So, the next thing to do is make sure that

  • account is not null
  • canEventEdit() is true

Usually, NPE tracing is like this, it's pretty easy. Just work backwards through the code until something puts out NULL, and that's the source.

Upvotes: 0

Related Questions