没有打开应用程序一段时间后按下按钮时,Android应用程序崩溃?

问题描述:

我正在制作一个应用程序,如果我通常使用它,它可以正常工作,没有崩溃。有两个交换片段的活动,其中一个有两个按钮。如果该应用程序未使用一段时间(小时)并重新打开该应用程序,则如果我按下其中一个按钮,应用程序将崩溃。这只会发生,如果我退出应用程序的主页按钮,如果我退出按Back几次然后这个问题不会发生。没有打开应用程序一段时间后按下按钮时,Android应用程序崩溃?

我也可以复制这个崩溃,如果我打开应用程序,按主页按钮返回到Android主屏幕,然后按我的高级任务杀手应用程序按钮。当我再次打开应用程序时,它打开它留下的相同片段(这很奇怪,我认为在使用任务杀手之后它会重新开始),并且如果我按下其中一个按钮,应用程序崩溃。

编辑:我发现通过它传递我tempmainfrag为空,当我恢复在下面的代码)的应用程序,这两个saveButtonClicked()和deleteButtonClicked(成为一个问题的logcat:

/* 
* Copyright (C) 2012 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 
package com.example.android.fragments; 

import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.os.Bundle; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentTransaction; 
import android.util.Log; 
import android.view.View; 
import android.view.animation.Animation; 
import android.view.animation.AnimationUtils; 
import android.view.inputmethod.InputMethodManager; 
import android.widget.CheckBox; 
import android.widget.EditText; 
import android.widget.TimePicker; 
import android.widget.Toast; 

public class MainActivity extends FragmentActivity 
     implements MainListFragment.OnListSelectedListener { 

    MainListFragment tempmainfrag; 
    InfoFragment infofrag; 
    int mainPosition = -1; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.mainlayout); 

     // Check whether the activity is using the layout version with 
     // the fragment_container FrameLayout. If so, we must add the first fragment 
     if (findViewById(R.id.fragment_container) != null) { //meaning, if using phone version 

      // However, if we're being restored from a previous state, 
      // then we don't need to do anything and should return or else 
      // we could end up with overlapping fragments. 
      if (savedInstanceState != null) { 
       return; 
      } 



      // Create an instance of MainListFragment 
      tempmainfrag = new MainListFragment(); //made a context parameter to pass the context 

      // In case this activity was started with special instructions from an Intent, 
      // pass the Intent's extras to the fragment as arguments 
      tempmainfrag.setArguments(getIntent().getExtras()); 



      // Add the fragment to the 'fragment_container' FrameLayout 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.fragment_container, tempmainfrag).commit(); 

      Log.i("mydebug","TEMPMAINFRAG: " + tempmainfrag); 
     } 
    } 

    public void onResume() 
    { 
     super.onResume(); 


    } 


    public void onItemSelected(int position, String schedulename, String[] ampm, boolean[] days, int[] times, boolean vibrate) { 
     // The user selected a list item 

     //////////////////////////////TWO PANE LAYOUT STUFF/////////////////////////////////// 
     // Capture the article fragment from the activity layout 
//  InfoFragment articleFrag = (InfoFragment) 
//    getSupportFragmentManager().findFragmentById(R.id.article_fragment); //article_fragment exists in layout-large 
// 
//  if (articleFrag != null) { 
//   // If article frag is available, we're in two-pane layout... 
// 
//   // Call a method in the ArticleFragment to update its content 
//   articleFrag.updateArticleView(position); 
// 
//  } else { 
      // phone layout - swap frags 

      mainPosition = position; 

      // Create fragment and give it an argument for the selected article 
      infofrag = new InfoFragment(); 
      Bundle args = new Bundle(); 
      args.putInt(infofrag.ARG_POSITION, position); 

      //new stuff to add info 
      args.putString(infofrag.ARG_NAME, schedulename);  
      args.putBooleanArray(infofrag.ARG_DAYS, days); 
      args.putIntArray(infofrag.ARG_TIMES, times); 
      args.putBoolean(infofrag.ARG_VIBRATE, vibrate); 
      args.putStringArray(infofrag.ARG_AMPM, ampm); 

      infofrag.setArguments(args); 
      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

      // Replace whatever is in the fragment_container view with this fragment, 
      // and add the transaction to the back stack so the user can navigate back 
      transaction.replace(R.id.fragment_container, infofrag); 
      transaction.addToBackStack(null); 

      // Commit the transaction 
      transaction.commit(); 

    } 

    public void saveButtonClicked(View view) { //pass the click to the mainlistfragment 
     Log.i("mydebug","TEMPMAINFRAG: " + tempmainfrag); 
     Log.i("mydebug","enter2222!!!!!!"); 
     boolean redo = false; 
     //create toast 
     Toast toast; 

     //get title 
     EditText titletext = (EditText)this.findViewById(R.id.titletext); 

     //get checkboxes 
     CheckBox check1 = (CheckBox)this.findViewById(R.id.monbox); //recreate checkboxes from view in activity (doesnt extend Activity 
     CheckBox check2 = (CheckBox)this.findViewById(R.id.tuebox); //so use getActivity()) 
     CheckBox check3 = (CheckBox)this.findViewById(R.id.wedbox); 
     CheckBox check4 = (CheckBox)this.findViewById(R.id.thubox); 
     CheckBox check5 = (CheckBox)this.findViewById(R.id.fribox); 
     CheckBox check6 = (CheckBox)this.findViewById(R.id.satbox); 
     CheckBox check7 = (CheckBox)this.findViewById(R.id.sunbox); 
     CheckBox vibratebox = (CheckBox)this.findViewById(R.id.vibratecheckbox); 

     //get times 
     TimePicker startpicker = (TimePicker)this.findViewById(R.id.starttimepicker); 
     TimePicker stoppicker = (TimePicker)this.findViewById(R.id.stoptimepicker); 

     EditText temppp = titletext; 
     //check for input errors 
     if(titletext.getText().toString().length() == 0) //if title is empty 
     { 
      redo = true; 
      toast = Toast.makeText(view.getContext(), "Enter an event name", 4); 
      toast.show(); 

      //some sick-ass shake animations!!! 
      Animation shake = AnimationUtils.loadAnimation(titletext.getContext(), R.anim.shake_big); 
      this.findViewById(R.id.titletext).startAnimation(shake); 
     } 
     else if((!check1.isChecked()) && (!check2.isChecked()) && (!check3.isChecked()) && 
       (!check4.isChecked()) && (!check5.isChecked()) && (!check6.isChecked()) && 
       (!check7.isChecked())) //if all checkboxes arent checked 
     { 
      redo = true; 
      toast = Toast.makeText(view.getContext(), "At least one day of week must be checked", 4); 
      toast.show(); 

      //more sick-ass shake animations!!! 
      Animation shake = AnimationUtils.loadAnimation(titletext.getContext(), R.anim.shake_small); 
      this.findViewById(R.id.checkboxes).startAnimation(shake); 
      this.findViewById(R.id.daysofweek).startAnimation(shake); 
      this.findViewById(R.id.frequencytext).startAnimation(shake); 
     } 

     if(!redo) //if all info is fine 
     { 
      //check to see if time goes into next day 
      if((startpicker.getCurrentHour() > stoppicker.getCurrentHour())|| 
        ((startpicker.getCurrentHour() == stoppicker.getCurrentHour()) 
          && (startpicker.getCurrentMinute() >= stoppicker.getCurrentMinute()))) 
      { 
       toast = Toast.makeText(view.getContext(), "Note: Stop time is earlier than start time, so this schedule stops at next day", Toast.LENGTH_LONG); 
       toast.show(); 
      } 

      toast = Toast.makeText(view.getContext(), "Schedule saved", Toast.LENGTH_LONG); 
      toast.show(); 

      //changing old schedule to new one 
      boolean[] tempdays = {check1.isChecked(), check2.isChecked(), check3.isChecked(), check4.isChecked(), 
        check5.isChecked(), check6.isChecked(), check7.isChecked()}; 

      tempmainfrag.mainObjectList.changeSchedule(mainPosition, titletext.getText().toString(), tempdays, vibratebox.isChecked(), 
        startpicker.getCurrentHour()-1, startpicker.getCurrentMinute(), stoppicker.getCurrentHour()-1, stoppicker.getCurrentMinute()); 

      //used to hide keyboard in case its still open when displaying list 
      InputMethodManager imm = (InputMethodManager)this.getSystemService(
         Context.INPUT_METHOD_SERVICE); 
       imm.hideSoftInputFromWindow(titletext.getWindowToken(), 0); 

      this.onBackPressed(); //replicates backpress to go back to list 
     } 
    } 

    public void deleteButtonClicked(View view) 
    { 
     //make a notification 

     AlertDialog.Builder builder = new AlertDialog.Builder(this); 
     builder.setTitle("Delete?"); 
     builder.setIcon(R.drawable.trash_icon); 
     builder.setMessage("Are you sure you wish to delete this schedule?") 
      .setCancelable(false) 
      .setPositiveButton("Delete", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 
        tempmainfrag.mainObjectList.removeSchedule(mainPosition); 

        tempmainfrag.exit(); 
       } 
      }) 
      .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 
        dialog.dismiss(); 
       } 
      }); 
     AlertDialog alert = builder.create(); 
     alert.show(); 
    } 

    public void hideKeyboard() //hides keyboard, called whenever reverting back to list 
    { 
     InputMethodManager imm = (InputMethodManager)getSystemService(
        Context.INPUT_METHOD_SERVICE); 
      imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); 
    } 


} 

我在onResume中尝试了一些解决方案,但想不出任何想法?非常感谢你们。

+0

任务杀手应用程序是胡扯。不要使用它们。 – 2013-02-21 23:17:06

+1

在崩溃时打印到LogCat的内容是什么?当“活动”进入后台时,Android可能会将其销毁。我的赌注是你有'静态'变量,在重新创建活动后有不正确的值,或者你可以依赖某些在活动生命周期中不能保存和重新创建的值。编辑您的问题并附上崩溃的LogCat输出。此外,发布活动代码*永远不会*伤害,但可以帮助访问者(有时*很多*)更快的诊断。 – andr 2013-02-21 23:21:06

我同意@andr的意思,你可能有一些静态变量,在任务kill之后变量变为空或空,因此如果你试图调用这些变量,你将面临一些错误。我认为这是事实,我可能是错误的,但这取决于你在LogCat中拥有什么。

如果我试图用高级任务杀手退出它,我的应用程序也崩溃了。原因是因为我使用了一些静态变量,在任务结束后变成空的“”。为了避免应用程序崩溃,在我实现类似这样的每个活动中。

希望这可以帮助你。或者您可以提供LogCat或更多信息,以便其他人可以帮助您。

public void onCreate(Bundle savedInstance){ 
     super.onCreate(savedInstance); 

     //check whether global/static variables are empty or not 
     //retrieve back the variables or intent it back to other activity 
     if(globalvariables.UserName.equals(""){ 
       //execute something to deal with it 
     } 
}