Android 错误从通知转到片段

Posted

技术标签:

【中文标题】Android 错误从通知转到片段【英文标题】:Android Error going to fragments from notification 【发布时间】:2016-12-30 16:36:39 【问题描述】:

我遇到来自/发送到片段的通知的问题。我将尝试尽可能清楚地解释我的方案以显示问题。

我有一个活动,MyWorkout.java,这个活动有一个可展开的列表视图。可展开列表视图上的所有项目将用户发送到第二个活动 WorkoutDaysActivity。他们都发送一个单独的额外意图,所以我知道用户点击了哪个项目。在 WorkoutDaysActivity.java 中,创建了 3 个片段,即星期一、星期三和星期五。每个活动我都有单独的课程。这些类有一个回收器视图和一个计时器。我有它,所以当计时器结束时,用户会收到通知。这可行,但是当我尝试从通知中将用户发送到 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 到达此类时,意图没有传递,因此字符串标题为空。我的问题是我不知道如何解决这个问题。如果我将通知发送到 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();
        
    );

非常感谢任何和所有帮助!

【问题讨论】:

addPages 方法中的第 45 行,那里有些内容为空。 是的,我认为这是因为假设它是从上一课获得意图的。无论如何我可以保存片段的状态或其他东西吗?因此,如果我将其发送到我的片段是否与收到通知之前的状态相同? 当然,查看这个帖子***.com/questions/22505327/… 谢谢!我不确定这是否是我的问题.. 我认为这与我的标志或 showNotification 方法中的某些东西有关 "WorkoutDaysActivity.java:45" 这意味着错误发生在 WorkoutDaysActivity.java 的第 45 行。这是哪条线? 【参考方案1】:

我设法解决了这个问题,我会在这里发布解决方案,以防将来有人遇到同样的问题。

这实际上是一个非常简单的修复,我所要做的就是在通知代码中添加额外的意图。

所以我从 MyWorkout.java 将这个意图传递给了 WorkoutDaysActivity:

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

在锻炼日活动中,我有这个意图,并将它作为参数传递给所有三个片段,如下所示:

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());

锻炼3在哪里:

 args = getArguments();
    workout3 = args.getString("workout");

【讨论】:

以上是关于Android 错误从通知转到片段的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.NullPointerException:Android 尝试调用虚拟方法错误

从通知导航到带有 NavController 的片段

设置onclick侦听器在android中无法从一个片段移动到另一个活动[重复]

android从通知栏跳转到相应的activity,回退到前一个activity的问题?

Android导航组件回栈

Android:单击片段中的按钮时如何通知活动? [复制]