Android 屏幕旋转和通知后应用强制关闭(片段)

Android Application Force Closes after Screen Rotation and Notification (Fragment)

所以我的应用程序有一个带有内置可运行计时器的片段,一旦时间达到 0,它将在设备上创建一个通知。但是,在屏幕方向后,应用程序强制关闭并 logcat 产生 "Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference"

这是完整的logcat:

     java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
        at android.content.ComponentName.<init>(ComponentName.java:77)
        at android.content.Intent.<init>(Intent.java:4160)
        at com.example.android.courtcounter.tabs.TimerFragment.createNotification(TimerFragment.java:178)
        at com.example.android.courtcounter.tabs.TimerFragment.run(TimerFragment.java:52)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

错误发生在这里:

           //Creates the notification from the Main Activity class
public void createNotification() {
    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(getActivity())
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle("Score Counter and Timer")
                    .setContentText("Time's up!");
    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent(this.getActivity(), TimerFragment.class);

    // The stack builder object will contain an artificial back stack for the
    // started Activity.
    // This ensures that navigating backward from the Activity leads out of
    // your application to the Home screen.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent =
            stackBuilder.getPendingIntent(
                    0,
                    PendingIntent.FLAG_UPDATE_CURRENT
            );
    int mID = 001;
    mBuilder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager =
            (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
    // mId allows you to update the notification later on.
    mNotificationManager.notify(mID,mBuilder.build());
}

显然在方向改变后通知会导致 "attempt to invoke method on a null object reference" 问题。

这里是我调用我创建的通知方法的地方:

    private Runnable timerRunnable = new Runnable() {
    @Override
    public void run() {
        if (timeLeft > 501) {
            timerTextViewSetUp();
            timerHandler.postDelayed(this, 500);
            timeLeft = timeLeft - 500;
            //Log.v(TimerFragment.class.getSimpleName(), "The timer has been set");
        } else if (timeLeft<501 && timeLeft>0) {
            timeLeft = 0;
            timerTextView.setText("0:00");
            timerHandler.removeCallbacks(this);
            vibrate();
            createNotification();
            setPauseButtonToStartButton();
        }

我不知道这是否与此有关,但这是我的 onSavedInstanceState 代码:

    @Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    //Save state information
    savedInstanceState.putLong(TIME_LEFT_KEY, timeLeft);

}

这是在 onCreateView 中:

    if (savedInstanceState != null) {
        timeLeft = savedInstanceState.getLong(TIME_LEFT_KEY);
        timerHandler.postDelayed(timerRunnable, 0);
        //Log.v(TimerFragment.class.getSimpleName(), Long.toString(timeLeft));
    }

不胜感激,谢谢!

方向更改导致 activity 重新创建。使用 removeCallbacks(Runnable r) 删除可运行对象,这样它就不会在旧的 activity 被销毁后被调用。一旦创建了新的 activity,您就可以重新创建可运行对象和处理程序。