Android Activity Recycle and Operation Timeout Handling

  • 2021-06-29 12:10:48
  • OfStack

This example shares the disposal of Android Activity recycling and operation timeout for your reference, as follows

1. Recycling of Activity

Processing for multiple activity exits

Key Code:

1) Create a new activity management class:


public class ActivityCollector {
  private static List<Activity> activityList = new ArrayList<Activity>();
  public static void addActivity(Activity activity){
    activityList.add(activity);
  }
  public static void removeActivity(Activity activity){
    activityList.remove(activity);
  }

  public static void finishAllButLast(){
    Activity activity = activityList.get(activityList.size()-1);
    removeActivity(activity);

    for (Activity activityItem: activityList){
      if (!activityItem.isFinishing()){
        activityItem.finish();
      }
    }

    activityList.clear();
    activityList.add(activity);
  }

  public static void finishAll(){
    for (Activity activity: activityList){
      if (!activity.isFinishing()){
        activity.finish();
      }
    }

    activityList.clear();
  }
}

2) Create the base class BaseActivity and inherit all activity from it.Add to Activity Manager when created and remove from Activity Manager when destroyed.


public class BaseActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityCollector.addActivity(this);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    ActivityCollector.removeActivity(this);
  }
}

If you need to destroy all activity, just call finishAll ()

2. Operation timeout processing

Principle:

1) In stop function of activity, according to app process IMPORTANCE_FOREGROUND judges app in foreground or background
2) In the onResume function of activity, do a timeout check.

Key Code:


abstract public class TimeOutCheckActivity extends BaseActivity {
  private boolean isLeave = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    pref = getSharedPreferences(Constant.CONFIG_NAME, Context.MODE_PRIVATE);
  }

  /**
   *  Callback function for easy testing 
   * @return
  */
  abstract protected String getTag();

  ...... Ellipsis ......

  /***
   *  Execute when the user restores the program to foreground display onResume() Method , In which to determine if timeout .
   */
  @Override
  protected void onResume() {
//    Log.i("Back",getTag() + " , onResume In the foreground: " + isOnForeground());
    super.onResume();
    if (isLeave) {
      isLeave = false;
      timeOutCheck();
    }
  }

  @Override 
  protected void onStop() {
    super.onStop();
    if (!isOnForeground()){
      if (!isLeave && isOpenALP()) {
        isLeave = true;
        saveStartTime();
      }
    }
  }

  public void timeOutCheck() {
    long endtime = System.currentTimeMillis();
    if (endtime - getStartTime() >= Constant.TIMEOUT_ALP * 1000) {
      Util.toast(this, " Timeout , Please re-validate ");
      String alp = pref.getString(Constant.ALP, null);
      if (alp == null || alp == "") {
      } else {
        Intent intent = new Intent(this, UnlockGesturePasswordActivity.class);
        intent.putExtra("pattern", alp);
        intent.putExtra("login",false); // Gesture validation, no login validation 
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        //  Open New Activity
        startActivityForResult(intent, Constant.REQ_COMPARE_PATTERN_TIMEOUT_CHECK);
      }
    }
  }

  public void saveStartTime() {
    pref.edit().putLong(Constant.START_TIME, System.currentTimeMillis()).commit();
  }

  public long getStartTime() {
    long startTime = 0;
    try {
      startTime = pref.getLong(Constant.START_TIME, 0);
    }catch (Exception e){
      startTime = 0;
    }
    return startTime;
  }

  /**
   *  Is the program running on the front end , Running by Enumeration app Realization.Prevent duplicate timeout detection multiple times , Guarantee that only 1 individual activity Entry Timeout Detection 
   * When the user presses home When the key is pressed, the program enters the backend and returns false , caused by other circumstances activity Of stop Function call, returns true
   * @return
  */
  public boolean isOnForeground() {
    ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
    String packageName = getApplicationContext().getPackageName();

    List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
    if (appProcesses == null)
      return false;

    for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
      if (appProcess.processName.equals(packageName)
          && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { 
        return true;
      }
    }

    return false;
  }
}


Supplementary Notes:

The foreground or background can be judged by the difference of importance. The constant IMTANCE in RunningAppProcessInfo is the foreground and background mentioned above. In fact, IMOPORTANCE indicates the importance of this app process, because the process is recycled according to IMOPORTANCE when the system is recycled.Specifically, you can see the documentation.


public static final int IMPORTANCE_BACKGROUND = 400// Backstage  
public static final int IMPORTANCE_EMPTY = 500// Empty process  
public static final int IMPORTANCE_FOREGROUND = 100// Get focus at the front of the screen   Understandable as Activity Life cycle OnResume(); 
public static final int IMPORTANCE_SERVICE = 300// in service  
public static final int IMPORTANCE_VISIBLE = 200// At the front of the screen, not getting focus can be interpreted as Activity Life cycle OnStart();


Related articles: