android爱上Android

[崩溃] Android应用自动重启

2023-03-06  本文已影响0人  尹学姐

背景

在App开发过程中,我们经常需要自动重启的功能。比如:

那我们如何实现自动重启的功能呢?我们都知道如何杀掉进程,但是当我们的进程被杀掉之后,如何唤醒呢?

这篇文章就来和大家介绍一下,实现应用自动重启的几种方法。

方法1 AlarmManager

    private void setAlarmManager(){
        Intent intent = new Intent();
        intent.setClass(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC, System.currentTimeMillis()+100, pendingIntent);
        Process.killProcess(Process.myPid());
        System.exit(0);
    }

使用AlarmManager实现自动重启的核心思想:创建一个100ms之后的Alarm任务,等Alarm任务到执行时间了,会自动唤醒App。

缺点:

方法2 直接启动Activity

private void restartApp(){
    Intent intent = new Intent(this, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    Process.killProcess(Process.myPid());
    System.exit(0);
}

缺点:

方法3 ProcessPhoenix

JakeWharton大神开源了一个叫ProcessPhoenix的库,这个库可以实现无缝重启app。

实现原理其实很简单,我们先讲怎么使用,然后再来分析源码。

使用方法

首先引入ProcessPhoenix库,这个库不需要初始化,可以直接使用。

implementation 'com.jakewharton:process-phoenix:2.1.2'

使用1:如果想重启app后进入首页:

ProcessPhoenix.triggerRebirth(context);

使用2:如果想重启app后进入特定的页面,则需要构造具体页面的intent,当做参数传入:

Intent nextIntent = //...
ProcessPhoenix.triggerRebirth(context, nextIntent);

有一点需要特别注意。

if (ProcessPhoenix.isPhoenixProcess(this)) {
  return;
}

源码

ProcessPhoenix的原理:

先来看看ManifestActivity的注册代码:

 <activity
        android:name=".ProcessPhoenix"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:process=":phoenix"
        android:exported="false"
        />

可以看到这个Activity确实是在:phoenix进程启动的,且是Translucent透明的。

整个ProcessPhoenix的代码只有不到120行,非常简单。我们来看下triggerRebirth做了什么。

  public static void triggerRebirth(Context context) {
    triggerRebirth(context, getRestartIntent(context));
  }

不带intenttriggerRebirth,最后也会调用到带intenttriggerRebirth方法。

getRestartIntent会获取主进程的Launch Activity

  private static Intent getRestartIntent(Context context) {
    String packageName = context.getPackageName();
    Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    if (defaultIntent != null) {
      return defaultIntent;
    }
  }

所以要调用不带intenttriggerRebirth,必须在当前Appmanifest里,指定Launch Activity,否则会抛出异常。

接着来看看真正的triggerRebirth方法:

  public static void triggerRebirth(Context context, Intent... nextIntents) {
    if (nextIntents.length < 1) {
      throw new IllegalArgumentException("intents cannot be empty");
    }
    // 第一个activity添加new_task标记,重新开启一个新的stack
    nextIntents[0].addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);

    Intent intent = new Intent(context, ProcessPhoenix.class);
    // 这里是为了防止传入的context非Activity
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context.
    // 将待启动的intent作为参数,intent是parcelable的
    intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents)));
    // 将主进程的pid作为参数
    intent.putExtra(KEY_MAIN_PROCESS_PID, Process.myPid());
    // 启动ProcessPhoenix Activity
    context.startActivity(intent);
  }

triggerRebirth方法,主要的功能是启动ProcessPhoenix Activity,相当于启动了:phoenix进程。同时,会将nextIntents和主进程的pid作为参数,传给新启动的ProcessPhoenix Activity

下面我们再来看看,ProcessPhoenix ActivityonCreate方法,看看新进程启动后做了什么。

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 首先杀死主进程
    Process.killProcess(getIntent().getIntExtra(KEY_MAIN_PROCESS_PID, -1)); // Kill original main process

    ArrayList<Intent> intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS);
    // 再启动主进程的intents
    startActivities(intents.toArray(new Intent[intents.size()]));
    // 关闭当前Activity,杀掉当前进程
    finish();
    Runtime.getRuntime().exit(0); // Kill kill kill!
  }

:phoenix进程主要做了以下事情:

总结

如果App有自动重启的需求,比较推荐使用ProcessPhoenix的方法。

原理其实非常简单:

我们可以直接在工程里引入ProcessPhoenix开源库,也可以自己用代码实现这样的机制,总之都比较简单。

上一篇下一篇

猜你喜欢

热点阅读