0

I'm having a problem with notifications coming from/sending to fragments. I'll try to explain my scenario as clear as possible to show to issue.

I have an activity, MyWorkout.java, this activity has an expandable list view. All items on expandable list view send the user to the second activity, WorkoutDaysActivity. They all send a seperate extra intent, so I know which item the user clicked. In WorkoutDaysActivity.java, 3 fragments are created, Monday, Wednesday, and Friday. I have separate classes for each activity. These classes have a recycler view and a timer. I have it so when the timer finishes, the user gets a notification. This works, but when I try to send the user to WorkoutDaysActivity from the notification, it crashes with the below error.

    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
                                                                                at com.bestworkouts.sheikoworkout.WorkoutDaysActivity.addPages(WorkoutDaysActivity.java:45)
                                                                                at com.bestworkouts.sheikoworkout.WorkoutDaysActivity.onCreate(WorkoutDaysActivity.java:29)

The line that it sends me too is where it tries to set the title(switch statement below) based on the intent passed from MyWorkout.java. I'm guessing that is because the intent is not passed as they getting to this class from the notification rather then from MyWorkout.java, therefore the string title is null. My problem is I have no idea how to fix this. The notification works fine if I send it to MyWorkout.java, but I'd prefer to send it back to where the timer is set if possible.

public class WorkoutDaysActivity extends BaseActivity{

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.workout_days);
    mToolBar = activateToolbar();
    setUpNavigationDrawer();



    ViewPager vp = (ViewPager) findViewById(R.id.view_pager);
    this.addPages(vp);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
    tabLayout.setupWithViewPager(vp);
    tabLayout.setOnTabSelectedListener(listener(vp));
}

//ADD ALL PAGES
private void addPages(ViewPager pager) {
    MyFragPagerAdapter adapter = new MyFragPagerAdapter(getSupportFragmentManager());
    Intent intent = getIntent();
    String workout = intent.getStringExtra("workout");
    Bundle args = new Bundle();
    args.putString("workout", workout);
    String title = args.getString("workout");
    switch(title) {
        case "w29w1" : {
            getSupportActionBar().setTitle("Workout 29 Week 1");
            break;
        }
        case "w29w2" : {
            getSupportActionBar().setTitle("Workout 29 Week 2");
            break;
        }
MondayFragment mondayFragment = new MondayFragment();
    mondayFragment.setArguments(args);
    adapter.addPage(mondayFragment);
    WedFragment wedFragment = new WedFragment();
    wedFragment.setArguments(args);
    adapter.addPage(wedFragment);
    FridayFragment fridayFragment = new FridayFragment();
    fridayFragment.setArguments(args);
    adapter.addPage(fridayFragment);
    pager.setAdapter(adapter);
}

This is where the timer is (MondayFragment.java):

private Button btnStart;
private Button btnStop;
private Button btnReset;
private CountDownTimer mCountDownTimer;
private TextView txtViewRest;

private void start() {
    mCountDownTimer = new CountDownTimer(5000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            txtViewRest.setText("Rest Remaining: " + millisUntilFinished / 1000 + " seconds.");
        }

        @Override
        public void onFinish() {
            txtViewRest.setText("Done!");
            showNotification();
        }
    }.start();
}
public void cancel() {
    if (mCountDownTimer != null) {
        mCountDownTimer.cancel();
        txtViewRest.setText("Rest Remaining: 5 seconds");
    } else return;
}
public void reset() {
    if (mCountDownTimer != null) {
        mCountDownTimer.cancel();
        txtViewRest.setText("Rest Remaining: 5 Seconds");
    } else return;
}

   public void showNotification() {
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext());
    builder.setSmallIcon(R.drawable.sheikoicon);
    builder.setContentTitle("Sheiko Rest Timer");
    builder.setContentText("Rest timer is up, start your set!");
    builder.setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE);
    builder.setAutoCancel(true);
    Intent intent = new Intent(getActivity(), WorkoutDaysActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(getContext());
    stackBuilder.addParentStack(WorkoutDaysActivity.class);
    stackBuilder.addNextIntent(intent);
    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_NO_CREATE);
    builder.setContentIntent(pendingIntent);
    NotificationManager NM = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
    NM.notify(0, builder.build());
}

  @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    SharedPreferences pref = this.getActivity().getSharedPreferences("MyPref", 0);
   View view = inflater.inflate(R.layout.monday_fragment, null);

    txtViewRest = (TextView) view.findViewById(R.id.txtViewRest);
    btnStart = (Button) view.findViewById(R.id.btnStart);
    btnStop = (Button) view.findViewById(R.id.btnStop);
    btnReset = (Button) view.findViewById(R.id.btnReset);

    btnStart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            start();
        }
    });
    btnStop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            cancel();
        }
    });
    btnReset.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            reset();
        }
    });

Any and all help is greatly appreciated!

LBJ33
  • 425
  • 11
  • 29
  • Line 45 in addPages method, something is null there. – AndroidRuntimeException Aug 23 '16 at 18:32
  • Yes I think it is because it is suppose to be getting intent from the previous class.. is there anyway I can save the state of the fragment or something? So if I send it to my fragment is has the same state as before I got the notification? – LBJ33 Aug 23 '16 at 18:34
  • sure, check this post http://stackoverflow.com/questions/22505327/android-save-restore-fragment-state – AndroidRuntimeException Aug 23 '16 at 18:42
  • Thanks! im not sure if thats my problem though.. I think it has to do with my flags or something in the showNotification method – LBJ33 Aug 23 '16 at 19:07
  • "WorkoutDaysActivity.java:45" This means the error occurs on line 45 of WorkoutDaysActivity.java. Which line is this? – Code-Apprentice Aug 23 '16 at 23:25
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Code-Apprentice Aug 23 '16 at 23:25
  • That's where the switch statement switches the string title from the extra intent.. I know what a NPE is, I just don't know how to fix it in this case as it's not getting the intent because it's coming from notification – LBJ33 Aug 24 '16 at 00:29
  • I've edited the question to hopefully make the problem a bit clearer – LBJ33 Aug 24 '16 at 16:03

1 Answers1

0

I managed to fix the problem, I will post the solution here in case anyone has the same problem in the future.

It was actually a very simple fix, all I had to do was put the extra intent in the notification code.

So from MyWorkout.java I had this intent passed to WorkoutDaysActivity:

Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
                    intent.putExtra("workout", "w29w1");
                    startActivity(intent);

In workout days activity, I had that intent, and passed it as an argument to all three fragments like so:

Intent intent = getIntent();
    String workout = intent.getStringExtra("workout");
    Bundle args = new Bundle();
    args.putString("workout", workout);

    MondayFragment mondayFragment = new MondayFragment();
    mondayFragment.setArguments(args);
    adapter.addPage(mondayFragment);
    WedFragment wedFragment = new WedFragment();
    wedFragment.setArguments(args);
    adapter.addPage(wedFragment);

and then in each fragment where I made the notification I had to add the intent.putExtra

public void showNotification() {
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext());
    builder.setSmallIcon(R.drawable.sheikoicon);
    builder.setContentTitle("Rest Timer");
    builder.setContentText("Rest timer is up, start your set!");
    builder.setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE);
    builder.setAutoCancel(true);
    Intent intent = new Intent(getActivity(), WorkoutDaysActivity.class);
    intent.putExtra("workout", workout3);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(getContext());
    stackBuilder.addParentStack(WorkoutDaysActivity.class);
    stackBuilder.addNextIntent(intent);
    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    builder.setContentIntent(pendingIntent);
    NotificationManager NM = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
    NM.notify(0, builder.build());
}

Where workout3 is:

 args = getArguments();
    workout3 = args.getString("workout");
LBJ33
  • 425
  • 11
  • 29