Khi quá trình ứng dụng chết, Android sẽ duyệt các bản ghi hoạt động (các mục đại diện cho các hoạt động trong ngăn xếp lịch sử) và quyết định những mục nào sẽ giữ trong lịch sử và những mục nào cần xóa khỏi nó.
Một trong những điểm chính ở đây là ActivityRecord
trường được gọi haveState
, mà các kỹ sư của Android Framework mô tả là "chúng ta đã có trạng thái hoạt động cuối cùng chưa?".
Theo mặc định, Android coi hoạt động đó có trạng thái. Hoạt động trở nên không trạng thái khi ứng dụng báo cáo cho dịch vụ quản lý tác vụ hoạt động mà hoạt động đó đã hoạt động trở lại và điều này hợp lệ cho đến khi ứng dụng thông báo khung mà hoạt động đã vào trạng thái Dừng. Nói một cách đơn giản, haveState
giá trị nằm false
giữa hoạt động onResume()
được gọi và onStop()
hoặc onSaveInstanceState()
được gọi, tùy thuộc vào phiên bản mục tiêu của ứng dụng.
Nếu tôi giết tiến trình, Android sẽ tạo lại quy trình và tạo ActivityC.
Trong trường hợp này ActivityD không có android:stateNotNeeded="true"
thuộc tính trong bảng kê khai ứng dụng và nó hiện đang chạy ở nền trước, vì vậy Android sẽ xóa nó khỏi lịch sử vì hệ thống chưa đạt được trạng thái cuối cùng.
Cách mô phỏng Android giết quá trình của tôi
Như đã được đề cập nhiều lần, bạn có thể chỉ cần di chuyển ứng dụng vào nền, do đó, hoạt động hàng đầu trong ngăn xếp hoạt động trở lại sẽ lưu trạng thái của nó và sau đó bạn có thể tắt quy trình ứng dụng thông qua Android Debug Bridge, Android Studio hoặc sử dụng Quy trình nền Giới hạn thuộc tính trong Tùy chọn nhà phát triển. Sau đó, hoạt động gần đây của bạn sẽ được tạo lại thành công.
Mặc dù vậy, cũng có một cách đơn giản khác để kiểm tra kịch bản chết của quy trình ứng dụng. Biết tất cả những điều được mô tả ở trên và thực tế, rằng nếu bạn bắt đầu ActivityE mới từ ActivityD hiện đang chạy, thì cuộc onStop()
gọi lại ActivityD chỉ được gọi sau onResume()
phương thức ActivityE , bạn có thể thực hiện thủ thuật sau.
class TerminatorActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val isPrePie = applicationInfo.targetSdkVersion < Build.VERSION_CODES.P
val callbacks = TerminatorLifecycleCallbacks(isPrePie)
(applicationContext as Application).registerActivityLifecycleCallbacks(callbacks)
}
private class TerminatorLifecycleCallbacks(
// Before P onSaveInstanceState() was called before onStop(), starting with P it's
// called after
// Used to schedule the death as app reports server that activity has stopped
// after the latest of these was invoked
private val isPrePie: Boolean
) : ActivityLifecycleCallbacksDefault {
private val handler = Handler(Looper.getMainLooper())
override fun onActivityPostStopped(activity: Activity) {
if (isPrePie) {
terminate()
}
}
override fun onActivityPostSaveInstanceState(activity: Activity, outState: Bundle) {
if (!isPrePie) {
terminate()
}
}
fun terminate() {
handler.postDelayed(
{
Process.killProcess(Process.myPid()) // This is the end...
},
LAST_MILLIS
)
}
companion object {
// Let's wait for a while, so app can report and server can handle the update
const val LAST_MILLIS = 100L
}
}
private interface ActivityLifecycleCallbacksDefault : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
}
}
Sau đó, chỉ bắt đầu TerminatorActivity
khi bạn muốn giết ứng dụng.
Cuối cùng, có một công cụ nhẹ giúp đơn giản hóa việc kiểm tra cái chết của quá trình ứng dụng của bạn, được gọi là Venom .