Mina Dahesh Mina Dahesh - 8 days ago 5
Android Question

NullPointerException in android: how to set context?

How can I fix this error?

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
ACTIVITY.onNewIntent(Adult1Activity.java:243)


This is the method that includes this error:

private void ExtendedNotification(String time) {
Intent resultIntent = new Intent(this, Adult1Activity.class);

resultIntent.putExtra("A", "restore");
PendingIntent restoreIntent = PendingIntent.getActivity(Adult1Activity.this, 0, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

resultIntent.putExtra("A", "close");
PendingIntent closeIntent = PendingIntent.getActivity(Adult1Activity.this, 2, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

final NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(Adult1Activity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("App Name")
.setContentText(time)
.setAutoCancel(true)
.addAction(new NotificationCompat.Action(R.mipmap.ic_launcher, "Restore", restoreIntent))
.addAction(new NotificationCompat.Action(R.mipmap.ic_launcher, "Close", closeIntent))
.setContentIntent(restoreIntent);

notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;

notificationManager.notify(0, notification);
}
@Override
protected void onNewIntent(Intent intent) {
switch (intent.getStringExtra("A")) {
case "restore":
tv.setText(timeString);
break;

case "close":
countDownTimer.cancel();
isRunning = false;
notificationManager.cancel(0);
CloseApp();
break;
}


I think the problem is not using context in it.

There is a Counter with StopBTN in my app and I create notification with 2 buttons. One of them is RestoreBTN that it shows my ACTIVITY class. Now as I click on StopBTN, this error shows.

Answer

You might want to set a constant for extra key, to avoid typos or something that looks like A but typed in wrong language. Also it's good to have constants for actions

private static final String EXTRA_A = "A";
private static final String A_RESTORE = "restore";
private static final String A_CLOSE = "close";

I don't know if you do, but not call onNewIntent() manually. Also onNewIntent() might not be called if your Activity is destroyed when you click on notification. You need to make two entries to check for intent, one for when activity is already running and you get onNewIntent(), and one if it's re-created and you get intent in onCreate()

@Override
protected void onCreate(Bundle b) {
    super.onCreate(b);
    // init views and stuff, and in final onCreate line handle the intent
    handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent); // Make sure to call super
    handleIntent(intent);
}

The crash means that your Intent does not really contain extra "A". You cannot use switch on a null string, thus you'd be safe if you check if A is null.

private void handleIntent(Intent intent) {
    final String a = intent.getStringExtra(EXTRA_A);
    if (a != null) {
        switch (a) {
           case A_RESTORE:
               ...

           case A_CLOSE:
               ...

Do not modify the same intent for different PendingIntents. They are mutable and getActivity() does not create a defensive copy.

final Intent resultIntentRestore = new Intent(this, Adult1Activity.class);
resultIntentRestore.putExtra(EXTRA_A, A_RESTORE);
PendingIntent restoreIntent = PendingIntent.getActivity(Adult1Activity.this, 
        0, resultIntentRestore, PendingIntent.FLAG_UPDATE_CURRENT);

final Intent resultIntentClose = new Intent(this, Adult1Activity.class);
resultIntentClose.putExtra(EXTRA_A, A_CLOSE);
PendingIntent closeIntent = PendingIntent.getActivity(Adult1Activity.this, 
        2, resultIntentClose, PendingIntent.FLAG_UPDATE_CURRENT);
Comments