Cách mô phỏng Android giết quá trình của tôi


174

Android sẽ giết một tiến trình nếu nó ở chế độ nền và HĐH quyết định nó cần tài nguyên (RAM, CPU, v.v.). Tôi cần có khả năng mô phỏng hành vi này trong quá trình thử nghiệm để tôi có thể đảm bảo rằng ứng dụng của mình hoạt động chính xác. Tôi muốn có thể thực hiện việc này theo cách tự động để tôi có thể kiểm tra xem ứng dụng có hoạt động chính xác bất cứ khi nào điều này xảy ra hay không, điều đó có nghĩa là tôi sẽ phải kiểm tra điều này trong mọi hoạt động, v.v.

Tôi biết làm thế nào để giết quá trình của tôi. Đó không phải là vấn đề. Vấn đề là khi tôi giết quá trình của tôi (sử dụng DDMS, adb shell kill, Process.killProcess(), vv) Android không khởi động lại nó cùng một cách mà nó sẽ nếu hệ điều hành Android đã giết nó chính nó.

Nếu HĐH Android giết quá trình (do yêu cầu tài nguyên), khi người dùng quay lại ứng dụng, Android sẽ tạo lại quy trình và sau đó tạo lại hoạt động hàng đầu trên ngăn xếp hoạt động (gọi onCreate()).

Mặt khác, nếu tôi giết tiến trình, Android giả định rằng hoạt động trên đỉnh của ngăn xếp hoạt động bị xử lý kém , do đó, nó sẽ tự động tạo lại quy trình và sau đó xóa hoạt động hàng đầu khỏi ngăn xếp hoạt động và tạo lại hoạt động bên dưới hoạt động hàng đầu (gọi onCreate () `). Đây không phải là hành vi tôi muốn. Tôi muốn hành vi tương tự như khi Android giết quá trình.

Chỉ để giải thích bằng hình ảnh, nếu ngăn xếp hoạt động của tôi trông như thế này:

    ActivityA -> ActivityB -> ActivityC -> ActivityD

Nếu Android giết quá trình và người dùng quay lại ứng dụng, Android sẽ tạo lại quy trình và tạo ActivityD.

Nếu tôi giết tiến trình, Android sẽ tạo lại quy trình và tạo ActivityC.


4
Bạn có thể không chỉ tạo ra số lượng quy trình cần thiết để giết bạn trong nền không?
Alex W


2
@Pang Tôi nghĩ bạn đang thiếu điểm. Tôi biết làm thế nào để phát hiện ra rằng Android đã giết quá trình. Tôi đã có mã xử lý các điều kiện này. Những gì tôi muốn làm là kiểm tra đúng cách (và theo cách tự động) kiểm tra mã này . Để làm được điều đó, tôi cần một số cách để có thể kích động Android để giết quá trình của tôi theo cách chính xác giống như cách nó thường làm dưới áp lực tài nguyên. Câu hỏi được liên kết, trong khi thú vị, không thêm bất kỳ giá trị nào ở đây.
David Wasser


@IgorGanapolsky Cảm ơn các liên kết, nhưng thực sự không có liên kết nào có giải pháp cho vấn đề này.
David Wasser

Câu trả lời:


127

Cách tốt nhất để kiểm tra điều này đối với tôi là làm điều này:

  • Mở ActivityD trong ứng dụng của bạn
  • Nhấn nút Home
  • Nhấn Terminate Applicationtrong cửa sổ Logcat trong Android Studio (điều này sẽ giết quá trình ứng dụng, đảm bảo bạn chọn thiết bị của mình và xử lý trong danh sách thả xuống Logcat ở trên cùng)
  • Quay trở lại ứng dụng với Home nhấn hoặc mở ứng dụng (tùy thuộc vào thiết bị)
  • Ứng dụng sẽ bắt đầu trong ActivityD được tạo lại (ActivityA, ActivityB, ActivityC đã chết và sẽ được tạo lại khi bạn quay lại với chúng)

Trên một số thiết bị, bạn cũng có thể quay lại ứng dụng (ActivityD) với Ứng dụng -> Biểu tượng trình khởi chạy của bạn nhưng trên các thiết bị khác, nó sẽ khởi động ActivityA thay thế.

Đây là những gì tài liệu Android đang nói về điều đó:

Thông thường, hệ thống sẽ xóa một tác vụ (loại bỏ tất cả các hoạt động khỏi ngăn xếp phía trên hoạt động gốc) trong một số trường hợp khi người dùng chọn lại tác vụ đó từ màn hình chính. Thông thường, điều này được thực hiện nếu người dùng chưa truy cập tác vụ trong một khoảng thời gian nhất định, chẳng hạn như 30 phút.


2
Cảm ơn câu trả lời của bạn nhưng nó không hữu ích với tôi vì tôi cần một cách tự động để làm điều này, để kiểm tra tự động.
David Wasser

1
Điều này thực sự hữu ích cho tôi.
John Roberts

6
Điều này không tự động nhưng nó hoạt động hoàn hảo cho mục đích của tôi. Điều rất quan trọng là không bỏ qua bước 2 . Bạn phải gửi ứng dụng xuống nền trước khi dừng quá trình trong DDMS để nó hoạt động. Đối với những người tự hỏi nơi trích dẫn tài liệu đến từ đây . Mặc dù tôi không chắc chúng thực sự liên quan đến chủ đề vì nó liên quan đến <activity>thẻ trong bảng kê khai.
Tony Chan

1
Chính xác những gì tôi cần. Cảm ơn bạn. Đối với những người không biết, DDMS có trong Eclipse, đi đến Cửa sổ -> Mở phối cảnh và bạn sẽ tìm thấy nó ở đó.
Richard

4
Ngoài ra, bạn có thể đi đến "Tùy chọn phát triển" và đặt giới hạn nền thành "không có quy trình nền" sau đó mỗi khi bạn nhấn về nhà, quy trình sẽ chết.
Joao Gavazzi

56

Điều này dường như làm việc cho tôi:

adb shell am kill <package_name>

Điều này khác với adb shell killđề cập của OP.

Lưu ý rằng sự trợ giúp cho am killlệnh nói:

am kill: Kill all processes associated with <PACKAGE>.  Only kills.
  processes that are safe to kill -- that is, will not impact the user
  experience.

Vì vậy, nó sẽ không giết quá trình nếu nó ở phía trước. Điều này dường như hoạt động như OP muốn ở chỗ nếu tôi điều hướng khỏi ứng dụng của mình, sau đó chạy adb shell am kill <package_name>nó sẽ giết ứng dụng (tôi đã xác nhận điều này bằng cách sử dụng pstrên thiết bị). Sau đó, nếu tôi quay lại ứng dụng, tôi đã quay lại hoạt động mà tôi đã tham gia trước đây - tức là trong ví dụ của OP, quy trình được tạo lại và tạo ActivityD (chứ không phải là ActivityC như hầu hết các phương thức giết khác dường như kích hoạt).

Xin lỗi tôi là một vài năm muộn cho OP, nhưng hy vọng những người khác sẽ thấy điều này hữu ích.


Cảm ơn! đây là những gì tôi đang tìm kiếm! Tôi muốn xác định rằng lệnh này hành xử khác hơn adb shell am force-stop. Tha cuối cùng cũng sẽ xóa mọi nội dung đang chờ xử lý liên quan đến ứng dụng của bạn (như Thông báo) trong khi ứng dụng đầu tiên thì không.
bonnyz 11/03/2015

Chỉ cho bất cứ ai điều tra mã nguồn hệ điều hành để xem mã nào nó chạy khi nó giết một quá trình để lấy lại bộ nhớ - đặt cược của tôi là mã giống như am kill.
androidguy

không hoạt động trên Android 7.1 Samsung J5. pshiển thị ứng dụng của tôi
Valgaal

17

Một phương pháp khác, có thể là một phương pháp có thể viết được vì nó không yêu cầu DDMS:

Thiết lập một lần: đi tới Tùy chọn nhà phát triển, chọn Cài đặt giới hạn quy trình nền, thay đổi giá trị từ 'Giới hạn tiêu chuẩn' thành 'Không có quy trình nền'.

Khi bạn cần khởi động lại quá trình, nhấn nút home. Quá trình sẽ bị hủy (bạn có thể xác minh trong logcat / Android Monitor trong studio - quá trình sẽ được đánh dấu [DEAD]). Sau đó chuyển trở lại ứng dụng bằng trình chuyển đổi tác vụ.


2
Hấp dẫn. Tôi nghĩ rằng điều đó không ảnh hưởng đến Dịch vụ Tiền cảnh, phải không?
IgorGanapolsky

Tôi cần phải làm điều này trên các thiết bị thực tế chạy Android cũ như phiên bản cũ, vì vậy đây không phải là bất kỳ trợ giúp nào.
David Wasser

13

Câu hỏi này đã cũ nhưng, có một câu trả lời cho câu hỏi này không yêu cầu adb, Android Studio, v.v. Yêu cầu duy nhất là API 23 hoặc mới hơn.

Để mô phỏng khởi động lại ứng dụng bằng HĐH, hãy cài đặt ứng dụng trong khi ứng dụng của bạn đang chạy, vô hiệu hóa (sau đó bạn có thể bật) quyền và trả lại ứng dụng từ các ứng dụng gần đây. Khi quyền bị vô hiệu hóa, HĐH sẽ tắt ứng dụng nhưng vẫn giữ trạng thái lưu. Khi người dùng trả lại ứng dụng, ứng dụng và hoạt động cuối cùng (với trạng thái đã lưu) được tạo lại.

Phương pháp 'Không có quy trình nền' đôi khi gây ra hành vi tương tự, nhưng không phải lúc nào cũng vậy. Ví dụ: nếu ứng dụng đang chạy dịch vụ nền, "Không có quy trình nền" không làm gì cả. Nhưng ứng dụng có thể bị giết bởi hệ thống bao gồm các dịch vụ của nó. Phương pháp cho phép hoạt động ngay cả khi ứng dụng có dịch vụ.

Thí dụ:

Ứng dụng của chúng tôi có hai hoạt động. ActivityA là hoạt động chính được bắt đầu từ launcher. ActivityB được bắt đầu từ ActivityA. Tôi sẽ chỉ hiển thị các phương thức onCreate, onStart, onStop, onDestroy. Android luôn gọi onSaveInstanceState trước khi gọi onStop, bởi vì một hoạt động ở trạng thái dừng có thể bị hệ thống giết chết. [ https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle]

Phương pháp cho phép:

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop (the order is like this, it is stopped after new one is started)
<go settings>
ActivityB onStop
<disable a permission>
//Application is killed, but onDestroy methods are not called.
//Android does not call onDestroy methods if app will be killed.
<return app by recent apps>
Application onCreate (this is the important part. All static variables are reset.)
ActivityB onCreate WITH savedInstance (user does not notice activity is recreated)
//Note that ActivityA is not created yet, do not try to access it.
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity is recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

Tôi muốn so sánh các phương pháp khác được đề cập trong các câu trả lời khác.

Không giữ các hoạt động: Điều này không giết chết ứng dụng.

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
ActivityA onDestroy (do not keep)
<return launcher by home button>
ActivityB onStop
ActivityB onDestroy (do not keep) 
<retun app from recent apps>
// NO Application onCreate
ActivityB onCreate WITH savedInstance (user does not notice activity recreated)
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

Phương thức dừng lực lượng: Không lưu trữ các trạng thái đã lưu

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
<go settings>
ActivityB onStop
<force stop, return app from recent apps>
Application onCreate
ActivityA onCreate WITHOUT savedInstance 
//This is important part, app is destroyed by user.
//Root activity of the task is started, not the top activity.
//Also there is no savedInstance.

~ " ứng dụng có thể bị giết bởi hệ thống bao gồm cả dịch vụ của nó ". Không phải dịch vụ tiền cảnh ...
IgorGanapolsky

@DavidWasser Đọc thông số kỹ thuật! developer.android.com/guide/components/service.html#Foreground Dịch vụ tiền cảnh là dịch vụ mà người dùng chủ động nhận biết và không phải là ứng cử viên để hệ thống tiêu diệt khi thiếu bộ nhớ.
IgorGanapolsky

3
Tài liệu @IgorGanapolsky là tốt, đặc biệt là nếu nó đầy đủ và chính xác (điều không may là không), nhưng tôi thường dựa nhiều hơn vào các quan sát cá nhân thực tế. Tôi đã thấy một tiền cảnh Servicebị giết rất nhiều lần. Ngay cả khi hệ thống không có bộ nhớ thấp. Hầu hết các nhà sản xuất thiết bị đã viết "tối ưu hóa" và "cải tiến" của riêng họ cho HĐH Android để tiết kiệm pin. Rất nhiều thiết bị có "sát thủ" khó chịu hơn nhiều so với Android tiêu chuẩn.
David Wasser

@DavidWasser Quan sát công bằng. Vì vậy, sau tất cả những năm này, bạn đã đưa ra một giải pháp?
IgorGanapolsky

@IgorGanapolsky Không. Tôi không tìm thấy giải pháp nào cho vấn đề này. Đó là lý do tại sao câu hỏi vẫn còn mở.
David Wasser

7

Tôi đến bữa tiệc rất muộn và một vài người trước tôi đã đưa ra câu trả lời đúng nhưng để đơn giản hóa cho bất kỳ ai đến sau tôi chỉ cần nhấn nút home và chạy lệnh này:

adb shell ps | grep <package name> | awk '{print $2}' | xargs adb shell run-as <package name again> kill

Ứng dụng sẽ không mất trạng thái và theo kinh nghiệm của riêng tôi, ứng dụng này hoạt động giống như hệ điều hành đã giết ứng dụng trong nền. Điều này chỉ hoạt động cho các ứng dụng được gỡ lỗi


Tôi nhận được'grep' is not recognized as an internal or external command, operable program or batch file.
Dale

Nhưng tôi đã làm điều đó khi ở trong vỏ run-as <package name> kill 7379, nhưng nó đưa tôi vào hoạt động trước đó, không phải là hoạt động tôi đang ở khi tôi nhấn nút home.
Dale

6

Đây là cách bạn làm điều đó trong Android Studio.

  1. Có thiết bị của bạn ở Chế độ gỡ lỗi được kết nối với máy tính của bạn.
  2. Mở ứng dụng trên thiết bị của bạn và đi đến bất kỳ hoạt động nào bạn muốn kiểm tra "Quay trở lại từ đó".
  3. Nhấn nút Home trên thiết bị của bạn.
  4. Trong Android Studio, truy cập Android Monitor -> Màn hình và nhấn biểu tượng Chấm dứt ứng dụng.
  5. Bây giờ bạn có thể quay lại ứng dụng của mình thông qua các ứng dụng gần đây hoặc bằng cách nhấp vào biểu tượng trình khởi chạy của nó, hành vi đã giống nhau trong các thử nghiệm của tôi.

2
Đây không phải là bất kỳ trợ giúp. Tôi cần phải làm điều này theo chương trình, trong một bộ thử nghiệm. Nhưng dù gì cũng cảm ơn.
David Wasser

Ngoài ra, câu trả lời này khá giống với câu trả lời từ Mark.
David Wasser

Bất kỳ ý tưởng làm thế nào để làm điều này thông qua UIAutomator hoặc Espresso?
IgorGanapolsky

Tôi không thể tìm thấy Android Monitor - Monitors. Phải là một cái gì đó họ đã thoát khỏi. Tôi đang ở phiên bản 3.2.1
Dale

1
Màn hình thiết bị Android @Dale không được dùng trong Android Studio 3.1 và bị xóa khỏi Android Studio 3.2.
Valgaal

5

Đặt ứng dụng ở chế độ nền với nút HOME

Chọn quy trình của bạn trong chế độ "Đăng nhập" trong Android Studio, sau đó nhấp vào Kết thúc ứng dụng ở góc dưới cùng

nút chấm dứt

Bây giờ hãy khởi chạy ứng dụng của bạn từ launcher trên thiết bị Android


EDIT: Theo internet, sau đây cũng hoạt động:

 adb shell am kill [my-package-name]

EDIT từ tương lai: Một điều cần lưu ý, đã có một sự thay đổi trong Android Studio 4.0, nếu bạn sử dụng Runtừ AS, thì Terminatesẽ phát hành a Force Stop.

Tuy nhiên, nếu bạn khởi chạy từ trình khởi chạy sau đó và THÌ bạn cố gắng mô phỏng theo cách này, thì bạn sẽ nhận được kết quả bạn muốn (hành vi bộ nhớ thấp).


Đây là một câu trả lời trùng lặp
Onik

@Onik Tất cả những người khác có một loạt các lông tơ không cần thiết như ddms và bất cứ điều gì. Mặc dù về mặt kỹ thuật, stackoverflow.com/a/41975750/2413303 cũng nói điều tương tự. Có lẽ tôi nên thêm hình ảnh.
EpicPandaForce

Điều này không hữu ích. Tôi có một khai thác thử nghiệm và tôi không thể thực hiện các hành động này từ khai thác thử nghiệm. Ngoài ra, hành vi không giống như những gì xảy ra khi Android giết quá trình.
David Wasser

the behaviour is not the same as what happens when Android kills the processđúng vậy
EpicPandaForce 04/07/18

Quá trình này cho tôi thấy hoạt động trước đó, không phải hoạt động khi nhấn nút home.
Dale

2

Bạn có thể thực hiện các bước tiếp theo để tái tạo hành vi tìm kiếm:

  1. Mở ứng dụng của bạn, điều hướng đến hoạt động hàng đầu
  2. Sử dụng bảng thông báo để điều hướng đến bất kỳ ứng dụng toàn màn hình nào khác (ví dụ: cài đặt hệ thống - ở góc trên cùng bên phải)
  3. Giết quá trình nộp đơn của bạn
  4. Nhấn nút quay lại

1
Cảm ơn câu trả lời của bạn nhưng nó không hữu ích với tôi vì tôi cần một cách tự động để làm điều này, để kiểm tra tự động.
David Wasser

Vì vậy, đây là phương pháp duy nhất mà tôi tìm thấy thực sự sẽ mô phỏng bộ nhớ xóa Android và giết ứng dụng của bạn (cấp API của tôi là 19 và vì vậy tôi không thể sử dụng lệnh send-trim-memory). Các lệnh khác như adb shell am force-stop com.my.app.package hoặc kill, sẽ không sao chép cùng một quy trình chính xác theo quy trình trên sẽ!
Mark Garcia

2

Trong tùy chọn Nhà phát triển trong Cài đặt, chọn 'Không giữ hoạt động', điều này sẽ hủy các hoạt động ngay khi bạn điều hướng khỏi chúng.

Lưu ý: Theo nhận xét hữu ích bên dưới, chỉ sử dụng điều này nếu bạn không quan tâm đến việc xóa các giá trị tĩnh.


Điều này thực sự giống như giải pháp đã được đăng - và bị từ chối - một năm trước. Sự khác biệt duy nhất dường như là ứng dụng được sử dụng để đặt nó trên trình giả lập, so với các điện thoại gần đây hỗ trợ nó.
Chris Stratton

1
Xin lỗi, như Chris Stratton nói, đây là khá nhiều gợi ý giống như câu trả lời khác. Đây không phải là về các hoạt động hoàn thiện Android. Đây là về Android giết chết toàn bộ quá trình (điều này thực hiện, khá thường xuyên và hiệu quả, đặc biệt là trên các thiết bị HTC chạy Android 4.x).
David Wasser

6
Điều này là gần như tốt nhưng nó sẽ không giết chết quá trình, nó chỉ phá hủy các hoạt động. Nó có nghĩa là gì? Hoạt động của bạn sẽ được mở bằng saveInstanceState nhưng tất cả các biến tĩnh vẫn đang trong quá trình. Sau quá trình tiêu diệt tất cả các biến tĩnh cũng được xóa.
Đánh dấu

1

Nhấn nút Home và đặt ứng dụng vào nền trước. Sau đó dừng hoặc hủy quá trình từ DDMS hoặc ADB.


Cảm ơn câu trả lời của bạn nhưng nó không hữu ích với tôi vì tôi cần một cách tự động để làm điều này, để kiểm tra tự động.
David Wasser

Android sẽ không bao giờ giết quá trình của bạn nếu hoạt động của bạn hiện đang ở phía trước. Bạn đang cố gắng kiểm tra một điều kiện sẽ không bao giờ xảy ra. Nếu hoạt động của bạn ở chế độ nền, thì trạng thái của nó đã được lưu và không có sự khác biệt nào giữa việc bạn giết thủ công và Android giết chết nó trong bộ nhớ thấp, tức là quá trình chỉ bị giết; không có gì đặc biệt về việc giết chết bộ nhớ thấp. Khi bộ nhớ khả dụng trở lại, các dịch vụ dính của bạn sẽ được khởi động lại (trừ ngày 4.4) và khi bạn nhấn vào biểu tượng hoặc tác vụ gần đây, trạng thái ngăn xếp và hoạt động sẽ được khôi phục.
Monstieur

3
Trong ví dụ của bạn, nó sẽ quay trở lại Hoạt động C vì bạn đã giết quá trình trong khi Hoạt động D hiển thị trên màn hình (điều này sẽ không bao giờ xảy ra ngay cả dưới bộ nhớ thấp) và trạng thái của Hoạt động C đã được lưu vì nó ở dưới nền. Quá trình của bạn sẽ chỉ bị giết nếu nó hoàn toàn không ở phía trước, tức là trạng thái của Hoạt động D sẽ được lưu khi nó đi vào nền và do đó sẽ được khôi phục ngay cả khi quy trình của bạn bị giết. Để thực hiện các thử nghiệm của bạn trên từng hoạt động, bạn phải gửi ứng dụng xuống nền trước khi bạn tắt nó.
Monstieur

Ý của bạn là gì ~ " và đặt ứng dụng vào nền trước "?
IgorGanapolsky

1

Bạn cũng có thể kết nối với thiết bị / trình giả lập của mình từ thiết bị đầu cuối với adb shell, sau đó nhận PID của quy trình của bạn ps | grep <your_package_namevà thực hiện kill -9 <pid>. Sau đó mở ứng dụng thu nhỏ của bạn từ bộ chọn ứng dụng gần đây và nó sẽ khởi động lại hoạt động cuối cùng


Có phải giống như Android giết chết một quá trình trong điều kiện bộ nhớ thấp? Tôi nghĩ OP đặc biệt muốn điều đó ...
IgorGanapolsky

1
@IgorGanapolsky về mặt lý thuyết là, mặc dù bạn không thể làm điều đó trên một thiết bị thực tế nếu nó không được root.
Fran Marzoa

0

Căn nguyên của vấn đề của bạn dường như là vấn đề của bạn Activityở phía trước khi bạn giết tiến trình.

Bạn có thể quan sát điều này bằng cách nhấn dừng trong DDMS khi Activitycó thể nhìn thấy (xảy ra chính xác những gì bạn mô tả) và so sánh điều đó với nhấn dừng sau khi về nhà và sau đó quay lại ứng dụng.

Chỉ cần chắc chắn rằng moveTaskToBack(true)bằng cách nào đó trong các bài kiểm tra của bạn.


0

Tôi không chắc đây là câu trả lời mà bạn đang tìm kiếm, nó giống như một suy nghĩ logic hơn.

Tôi không nghĩ rằng bạn thực sự có thể thực hiện một thử nghiệm hoàn toàn tự động, cách duy nhất để mô phỏng nó, đó là tạo lại nó, AKA có rất nhiều hoạt động mà Android sẽ giết ứng dụng của bạn.

Vì vậy, ý tưởng hoặc đề xuất của tôi là tạo ra một ứng dụng nhỏ khác, liên tục xuất hiện các hoạt động mới, cho đến khi Android hết bộ nhớ và bắt đầu giết chết quá trình làm nền.

Một cái gì đó trong dòng:

Bắt đầu hoạt động i -> Kiểm tra quá trình chạy nếu ứng dụng có trong danh sách, tăng i và khởi động lại vòng lặp mà không đóng hoạt động hiện tại, khác -> giảm i và đóng hoạt động hiện tại, quay lại trước đó và kiểm tra lại ...


0

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à ActivityRecordtrườ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, haveStategiá trị nằm falsegiữ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 TerminatorActivitykhi 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 .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.