Android 从通知转到片段时出错
Android Error going to fragments from notification
我在 from/sending 通知片段时遇到问题。我会尽可能清楚地解释我的场景,以便向问题展示。
我有一个 activity、MyWorkout.java,这个 activity 有一个可扩展的列表视图。可扩展列表视图上的所有项目都会将用户发送到第二个 activity,WorkoutDaysActivity。他们都发送了一个单独的额外意图,所以我知道用户点击了哪个项目。在 WorkoutDaysActivity.java 中,创建了 3 个片段,分别是星期一、星期三和星期五。每个 activity 我都有单独的 classes。这些 classes 具有回收器视图和计时器。我有它,所以当计时器结束时,用户会收到通知。这有效,但是当我尝试将用户从通知发送到 WorkoutDaysActivity 时,它崩溃并出现以下错误。
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)
它也发送给我的行是它试图根据从 MyWorkout.java 传递的意图设置标题(下面的 switch 语句)。我猜这是因为当他们从通知而不是从 MyWorkout.java 到达此 class 时未传递意图,因此字符串标题为空。我的问题是我不知道如何解决这个问题。如果我将它发送到 MyWorkout.java,通知工作正常,但如果可能,我更愿意将它发送回设置计时器的位置。
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);
}
这是计时器所在的位置 (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();
}
});
非常感谢任何帮助!
我设法解决了这个问题,我会post这里的解决方案,以防将来有人遇到同样的问题。
这实际上是一个非常简单的修复,我所要做的就是在通知代码中添加额外的意图。
所以从 MyWorkout.java 我将这个意图传递给了 WorkoutDaysActivity:
Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
intent.putExtra("workout", "w29w1");
startActivity(intent);
在锻炼日 activity,我有那个意图,并将其作为参数传递给所有三个片段,如下所示:
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);
然后在我发出通知的每个片段中我必须添加 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());
}
其中 workout3 是:
args = getArguments();
workout3 = args.getString("workout");
我在 from/sending 通知片段时遇到问题。我会尽可能清楚地解释我的场景,以便向问题展示。
我有一个 activity、MyWorkout.java,这个 activity 有一个可扩展的列表视图。可扩展列表视图上的所有项目都会将用户发送到第二个 activity,WorkoutDaysActivity。他们都发送了一个单独的额外意图,所以我知道用户点击了哪个项目。在 WorkoutDaysActivity.java 中,创建了 3 个片段,分别是星期一、星期三和星期五。每个 activity 我都有单独的 classes。这些 classes 具有回收器视图和计时器。我有它,所以当计时器结束时,用户会收到通知。这有效,但是当我尝试将用户从通知发送到 WorkoutDaysActivity 时,它崩溃并出现以下错误。
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)
它也发送给我的行是它试图根据从 MyWorkout.java 传递的意图设置标题(下面的 switch 语句)。我猜这是因为当他们从通知而不是从 MyWorkout.java 到达此 class 时未传递意图,因此字符串标题为空。我的问题是我不知道如何解决这个问题。如果我将它发送到 MyWorkout.java,通知工作正常,但如果可能,我更愿意将它发送回设置计时器的位置。
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);
}
这是计时器所在的位置 (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();
}
});
非常感谢任何帮助!
我设法解决了这个问题,我会post这里的解决方案,以防将来有人遇到同样的问题。
这实际上是一个非常简单的修复,我所要做的就是在通知代码中添加额外的意图。
所以从 MyWorkout.java 我将这个意图传递给了 WorkoutDaysActivity:
Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
intent.putExtra("workout", "w29w1");
startActivity(intent);
在锻炼日 activity,我有那个意图,并将其作为参数传递给所有三个片段,如下所示:
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);
然后在我发出通知的每个片段中我必须添加 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());
}
其中 workout3 是:
args = getArguments();
workout3 = args.getString("workout");