When using app, all app processes were killed after the permission was disabled. This is the first time I have encountered…

A bug from the test mention:

During the live broadcast, the app live broadcast crashed after the camera permission was set to disable.

Bug emersion

By repetition, that’s true, but it’s the NPE or something. It has nothing to do with camera permissions. Plug in your phone and start debugging. Look at the logs. Open the app and go to system Settings to change the app’s camera permissions from allowed to forbidden. Logcat logs are gone, and all the app processes are killed, not a single one. Click on the app from the recent task list or desktop Icon. The white screen appears for a short time and then crashes. The process creates and then reconstructs the activity at the top of the stack. However, if the program reads an object stored in memory, an NPE crashes. This is… Try wechat. I’m surprised. Wechat it restarted, re-start the cold start process.

Why app processes get killed

Android Marshmallow Dynamic Permission Change Kills all Application Processes Since this is how the Android system works, let’s figure out how to keep the app from crashing in this situation.

The solution

OnCreate: bundle! = null

Many people consider checking if the bundle is null in the onCreate method of the base class to determine if the activity has been rebuilt. This method is based on the fact that the onCreate method of the activity on the top of the stack does not have a null bundle, and the system automatically passes in the bundle.

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState ! = null) { val intent = Intent(this, LaunchActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) overridePendingTransition(0, 0) finish() } }Copy the code

However, if the application needs to store the bundle, this method is not applicable

Through ActivityLifecycleCallbacks

Another method found: In Application to define a Boolean type of attribute, isKilled = true to true by default, registered ActivityLifecycleCallbacks callback, in onActivityCreated method, If the activity is launched, set application.iskilled to false. If it is true that the Application has been rebuilt, jump to Launch and kill the Activity that has been rebuilt. Applications can’t normal use Concrete implementation: custom PreventProcessKill class, and implement Application. ActivityLifecycleCallbacks interface

class PreventProcessKill: Application.ActivityLifecycleCallbacks { companion object { const val TAG = "PreventProcessKill" } private var activityCount = 0 override fun onActivityCreated(activity: Activity? , bundle: Bundle?) { Logs.e(TAG, "onActivityCreated activity=($activity) bundle=($bundle)") if (activity ! = null && activity is LaunchActivity) { if (activityCount == 0 || activity.isTaskRoot()) { Logs.e(TAG, "onActivityCreated set isKilled false ") MyApplication.isKilled = false } } if (MyApplication.isKilled) { Logs.e(TAG, "OnActivityCreated isKilled == true, start restartApp") return; } } override fun onActivityStarted(activity: Activity?) { Logs.e(TAG, "onActivityStarted activity=$activity") activityCount++ } override fun onActivityResumed(activity: Activity?) { Logs.e(TAG, "onActivityResumed activity=$activity") } override fun onActivityPaused(activity: Activity?) { Logs.e(TAG, "onActivityPaused activity=$activity") } override fun onActivityStopped(activity: Activity?) { Logs.e(TAG, "onActivityStopped activity=$activity") activityCount-- } override fun onActivitySaveInstanceState(activity: Activity? , bundle: Bundle?) { Logs.e(TAG, "onActivitySaveInstanceState activity=($activity) bundle=($bundle)") } override fun onActivityDestroyed(activity: Activity?) {log. E (TAG, "onActivityDestroyed activity=$activity")} /** * Destroyed process */ private fun restartApp(activity: activity?) { val intent = Intent(activity, LaunchActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK activity? .startActivity(intent) activity? .overridePendingTransition(0, 0) activity? .finish() } }Copy the code

Define the isKilled attribute in the Application, which defaults to true.

public class MyApplication extends MultiDexApplication {
    public boolean isKilled = true;
}
Copy the code

At the end of the article

The second method I think is a little bit better than the onCreate method to determine if the bundle is empty.

The problem with both methods is that when you open the app, the screen goes blank for a while. Wechat has no white screen. Really want to ask the person of wechat is how to deal with.