วิธีจำลอง Android ที่ฆ่ากระบวนการของฉัน


174

Android จะฆ่ากระบวนการหากอยู่ในพื้นหลังและระบบปฏิบัติการต้องการทรัพยากร (RAM, CPU และอื่น ๆ ) ฉันต้องสามารถจำลองพฤติกรรมนี้ในระหว่างการทดสอบเพื่อให้มั่นใจได้ว่าแอปพลิเคชันของฉันทำงานได้อย่างถูกต้อง ฉันต้องการที่จะสามารถทำสิ่งนี้ด้วยวิธีอัตโนมัติเพื่อให้ฉันสามารถทดสอบว่าแอปพลิเคชันทำงานอย่างถูกต้องหรือไม่เมื่อใดก็ตามที่เกิดเหตุการณ์นี้ขึ้นซึ่งหมายความว่าฉันจะต้องทดสอบสิ่งนี้ในทุกกิจกรรมเป็นต้น

ฉันรู้วิธีฆ่ากระบวนการของฉัน นั่นไม่ใช่ปัญหา ปัญหาคือว่าเมื่อฉันฆ่ากระบวนการของฉัน (ใช้ DDMS, adb shell kill, Process.killProcess()ฯลฯ ) Android ไม่เริ่มต้นใหม่ได้เช่นเดียวกับที่มันจะถ้าระบบปฏิบัติการ Android ได้ฆ่าตัวเอง

หากระบบปฏิบัติการ Android ฆ่ากระบวนการ (เนื่องจากความต้องการทรัพยากร) เมื่อผู้ใช้กลับสู่การประยุกต์ใช้ Android จะสร้างกระบวนการแล้วสร้างกิจกรรมบนสแต็กิจกรรม (เรียกonCreate())

ในทางกลับกันถ้าฉันฆ่ากระบวนการAndroid จะถือว่ากิจกรรมที่ด้านบนของกิจกรรมสแต็คนั้นมีพฤติกรรมที่ไม่ดีดังนั้นมันจะสร้างกระบวนการขึ้นมาใหม่โดยอัตโนมัติแล้วเอากิจกรรมด้านบนออกจากกิจกรรมสแต็ก กิจกรรมยอดนิยม (เรียก onCreate () `) นี่ไม่ใช่พฤติกรรมที่ฉันต้องการ ฉันต้องการพฤติกรรมเช่นเดียวกับเมื่อ Android ฆ่ากระบวนการ

เพียงเพื่ออธิบายเป็นภาพหากกองกิจกรรมของฉันมีลักษณะดังนี้:

    ActivityA -> ActivityB -> ActivityC -> ActivityD

หาก Android ฆ่ากระบวนการและผู้ใช้กลับสู่แอปพลิเคชัน Android จะสร้างกระบวนการขึ้นใหม่และสร้าง ActivityD

หากฉันฆ่ากระบวนการ Android จะสร้างกระบวนการขึ้นใหม่และสร้าง ActivityC


4
คุณไม่สามารถสร้างจำนวนของกระบวนการที่ต้องการฆ่าคุณในเบื้องหลังได้หรือไม่?
อเล็กซ์ W


2
@Pang ฉันคิดว่าคุณไม่มีจุด ฉันรู้วิธีตรวจจับว่า Android ได้ฆ่ากระบวนการแล้ว ฉันมีรหัสที่จัดการกับเงื่อนไขเหล่านี้ สิ่งที่ฉันต้องการจะทำคือการอย่างถูกต้อง (และในทางอัตโนมัติ) ทดสอบรหัสนี้ เพื่อที่จะทำเช่นนั้นฉันต้องการวิธีที่จะสามารถกระตุ้น Android ให้ฆ่ากระบวนการของฉันในลักษณะเดียวกับที่มันทำตามปกติภายใต้แรงกดดันของทรัพยากร คำถามที่เชื่อมโยงในขณะที่น่าสนใจไม่ได้เพิ่มคุณค่าใด ๆ ที่นี่
David Wasser


@IgorGanapolsky ขอบคุณสำหรับลิงก์ แต่จริงๆแล้วไม่มีลิงก์เหล่านั้นที่มีวิธีแก้ไขปัญหา
David Wasser

คำตอบ:


127

วิธีทดสอบที่ดีที่สุดสำหรับฉันคือทำสิ่งนี้:

  • เปิด ActivityD ในแอปพลิเคชันของคุณ
  • กดปุ่มหน้าแรก
  • กดTerminate Applicationในหน้าต่าง Logcat ใน Android Studio (นี่จะเป็นการฆ่าแอพให้แน่ใจว่าคุณเลือกอุปกรณ์ของคุณและดำเนินการในรายการดรอปดาวน์ Logcat ที่ด้านบน)
  • กลับไปที่แอปพลิเคชันด้วยการกดหน้าแรกหรือแอปที่เปิดนาน ๆ (ขึ้นอยู่กับอุปกรณ์)
  • แอปพลิเคชันจะเริ่มต้นในการสร้างใหม่ ActivityD (ActivityA, ActivityB, ActivityC จะตายและจะถูกสร้างขึ้นใหม่เมื่อคุณกลับไปที่พวกเขา)

ในบางอุปกรณ์คุณสามารถกลับไปที่แอปพลิเคชัน (ActivityD) ด้วยแอปพลิเคชั่น -> ไอคอนตัวเรียกใช้งานของคุณ แต่บนอุปกรณ์อื่นมันจะเริ่ม ActivityA แทน

นี่คือสิ่งที่ Android เอกสารกำลังพูดเกี่ยวกับที่:

โดยปกติระบบจะล้างภารกิจ (ลบกิจกรรมทั้งหมดออกจากสแต็กเหนือกิจกรรมรูท) ในบางสถานการณ์เมื่อผู้ใช้เลือกภารกิจนั้นซ้ำจากหน้าจอหลัก โดยทั่วไปสิ่งนี้จะเกิดขึ้นหากผู้ใช้ไม่ได้เข้าชมงานเป็นระยะเวลาหนึ่งเช่น 30 นาที


2
ขอบคุณสำหรับคำตอบของคุณ แต่มันไม่มีประโยชน์สำหรับฉันเพราะฉันต้องการวิธีการอัตโนมัติในการทดสอบอัตโนมัติ
David Wasser

1
มันมีประโยชน์จริง ๆ สำหรับฉัน
John Roberts

6
สิ่งนี้ไม่อัตโนมัติ แต่ทำงานได้อย่างสมบูรณ์แบบสำหรับวัตถุประสงค์ของฉัน มันเป็นสิ่งสำคัญมากที่จะไม่ข้ามขั้นตอนที่ 2 คุณต้องส่งแอปไปที่พื้นหลังก่อนที่จะหยุดกระบวนการใน DDMS เพื่อให้การทำงานนี้ สำหรับผู้ที่สงสัยว่าคำพูดของหมอมาจากที่ใด แม้ว่าฉันไม่แน่ใจว่าพวกเขาเกี่ยวข้องกับหัวข้อจริงหรือไม่เนื่องจากเป็นเรื่องเกี่ยวกับ<activity>แท็กในไฟล์ Manifest
Tony Chan

1
สิ่งที่ฉันต้องการ ขอบคุณ. สำหรับผู้ที่ไม่รู้ DDMS อยู่ใน Eclipse ไปที่ Window -> Open Perspective และคุณควรพบมันที่นั่น
Richard

4
หรือคุณสามารถไปที่ "ตัวเลือกการพัฒนา" และตั้งค่าขีด จำกัด พื้นหลังเป็น "ไม่มีกระบวนการพื้นหลัง" จากนั้นทุกครั้งที่คุณกดปุ่มโฮมกระบวนการจะตาย
Joao Gavazzi

56

ดูเหมือนว่าจะใช้งานได้สำหรับฉัน:

adb shell am kill <package_name>

สิ่งนี้แตกต่างadb shell killจากที่ OP กล่าวถึง

โปรดทราบว่าความช่วยเหลือสำหรับam killคำสั่งระบุว่า:

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

ดังนั้นมันจะไม่ฆ่ากระบวนการหากอยู่ในเบื้องหน้า ดูเหมือนว่าจะทำงานได้ตามที่ OP ต้องการหากฉันออกไปจากแอพของฉันการเรียกใช้adb shell am kill <package_name>จะทำให้แอปหยุดทำงาน (ฉันยืนยันการใช้งานpsบนอุปกรณ์) ถ้าฉันกลับไปที่แอพฉันกลับมาในกิจกรรมที่ฉันทำก่อนหน้านี้ - ในตัวอย่างของ OP กระบวนการจะถูกสร้างขึ้นใหม่และสร้าง ActivityD (แทนที่จะเป็น ActivityC เหมือนกับวิธีฆ่าคนอื่น ๆ

ขออภัยฉันใช้เวลาสองสามปีที่ผ่านมาสำหรับ OP แต่หวังว่าคนอื่นจะพบว่ามีประโยชน์นี้


ขอบคุณ! นี่คือสิ่งที่ฉันกำลังมองหา! adb shell am force-stopฉันต้องการที่จะระบุได้ว่าคำสั่งนี้มีลักษณะการทำงานที่แตกต่างกว่า Tha อันสุดท้ายจะลบการค้างอยู่ที่เกี่ยวข้องกับแอพของคุณ (เช่นการแจ้งเตือน) ในขณะที่อันแรกไม่ได้ทำ
bonnyz

จุดไปยังทุกคนที่สำรวจรหัสที่มาของระบบปฏิบัติการเพื่อดูว่ารหัสมันจะทำงานเมื่อมันฆ่ากระบวนการที่จะเรียกคืนหน่วยความจำ - am killเดิมพันของฉันคือมันเป็นรหัสเดียวกับ
androidguy

ไม่ทำงานบน Android 7.1 Samsung J5 psแสดงแอพของฉัน
Valgaal

17

วิธีอื่นอาจเป็นวิธีที่ใช้สคริปต์ได้เนื่องจากไม่ต้องการ DDMS:

ตั้งค่าครั้งเดียว: ไปที่ตัวเลือกนักพัฒนาเลือกการตั้งค่าขีด จำกัด กระบวนการพื้นหลังเปลี่ยนค่าจาก 'ขีด จำกัด มาตรฐาน' เป็น 'ไม่มีกระบวนการพื้นหลัง'

เมื่อคุณต้องการเริ่มกระบวนการให้กดปุ่มโฮม กระบวนการจะถูกฆ่า (คุณสามารถตรวจสอบใน logcat / Android Monitor ในสตูดิโอ - กระบวนการจะถูกทำเครื่องหมาย [DEAD]) จากนั้นสลับกลับไปที่แอปโดยใช้ตัวสลับงาน


2
น่าสนใจ ฉันคิดว่านั่นไม่ส่งผลกระทบต่อบริการเบื้องหน้าใช่ไหม
IgorGanapolsky

ฉันต้องทำสิ่งนี้กับอุปกรณ์จริงที่ใช้ Android ที่เก่าถึง 2.3.3 ดังนั้นจึงไม่มีความช่วยเหลือใด ๆ
David Wasser

13

คำถามนี้เก่า แต่มีคำตอบสำหรับคำถามนี้ที่ไม่ต้องการ adb, Android Studio เป็นต้นข้อกำหนดเพียงอย่างเดียวคือ API 23 หรือใหม่กว่า

ในการจำลองการรีสตาร์ทแอพโดยระบบปฏิบัติการให้ไปที่การตั้งค่าแอพขณะที่แอพของคุณกำลังทำงานปิดการใช้งาน (จากนั้นคุณสามารถเปิดใช้งาน) การอนุญาตและส่งคืนแอพจากแอพล่าสุด เมื่อปิดใช้งานการอนุญาตระบบปฏิบัติการจะฆ่าแอป แต่เก็บสถานะอินสแตนซ์ที่บันทึกไว้ เมื่อผู้ใช้ส่งคืนแอปแอปและกิจกรรมล่าสุด (พร้อมสถานะที่บันทึก) จะถูกสร้างขึ้นใหม่

บางครั้งวิธีการ 'ไม่มีกระบวนการพื้นหลัง' ทำให้เกิดพฤติกรรมเดียวกัน แต่ไม่เสมอไป ตัวอย่างเช่นหากแอปกำลังเรียกใช้บริการพื้นหลัง "ไม่มีกระบวนการพื้นหลัง" ไม่ทำอะไรเลย แต่แอปสามารถถูกฆ่าโดยระบบรวมถึงบริการของมัน วิธีการอนุญาตใช้งานได้แม้ว่าแอปจะมีบริการก็ตาม

ตัวอย่าง:

แอพของเรามีสองกิจกรรม ActivityA เป็นกิจกรรมหลักที่เริ่มต้นจากตัวเรียกใช้ ActivityB เริ่มต้นจาก ActivityA ฉันจะแสดงเฉพาะวิธีการสร้าง, onStart, onStop, onDestroy Android เรียกร้องให้ SaveInstanceState เสมอก่อนที่จะเรียก onStop เพราะกิจกรรมที่อยู่ในสถานะหยุดสามารถถูกฆ่าโดยระบบ [ https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle]

วิธีการอนุญาต:

<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

ฉันต้องการเปรียบเทียบวิธีอื่น ๆ ที่กล่าวถึงในคำตอบอื่น ๆ

อย่าเก็บกิจกรรม: สิ่งนี้ไม่ได้ฆ่าแอปพลิเคชัน

<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

วิธีบังคับหยุด: ไม่เก็บสถานะอินสแตนซ์ที่บันทึกไว้

<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.

~ " แอปสามารถถูกฆ่าโดยระบบรวมถึงบริการ " ไม่ใช่บริการเบื้องหน้า ...
IgorGanapolsky

@DavidWasser อ่านข้อมูลจำเพาะ! developer.android.com/guide/components/services.html#Foreground บริการเบื้องหน้าคือบริการที่ผู้ใช้รับรู้อย่างแข็งขันและไม่ใช่ผู้สมัครที่จะฆ่าระบบเมื่อหน่วยความจำเหลือน้อย
IgorGanapolsky

3
@IgorGanapolsky เอกสารเป็นเรื่องที่ดีโดยเฉพาะอย่างยิ่งถ้ามันสมบูรณ์และถูกต้อง (ซึ่งน่าเสียดายที่ไม่ใช่) แต่ฉันมักจะพึ่งพาข้อสังเกตส่วนตัวที่เกิดขึ้นจริง ฉันเคยเห็นฉากหน้าServiceถูกฆ่าตายหลายครั้ง แม้ว่าระบบจะมีหน่วยความจำไม่น้อย ผู้ผลิตอุปกรณ์ส่วนใหญ่ได้เขียน "การเพิ่มประสิทธิภาพ" ของตนเองและ "การปรับปรุง" ลงใน Android OS เพื่อประหยัดพลังงานแบตเตอรี่ อุปกรณ์จำนวนมากมี "นักฆ่า" ที่ก้าวร้าวมากกว่า Android มาตรฐาน
David Wasser

@DavidWasser สังเกตอย่างยุติธรรม ดังนั้นหลังจากหลายปีที่ผ่านมาคุณคิดวิธีแก้ปัญหาหรือไม่?
IgorGanapolsky

@IgorGanapolsky ไม่ฉันไม่พบวิธีแก้ไขปัญหานี้ นั่นเป็นสาเหตุที่คำถามยังคงเปิดอยู่
David Wasser

7

ฉันไปงานปาร์ตี้ช้ามากและอีกหลายคนก่อนที่ฉันจะให้คำตอบที่ถูกต้องเหมือนกัน แต่เพื่อให้ง่ายขึ้นสำหรับผู้ที่มาหลังจากฉันเพียงกดปุ่มโฮมแล้วเรียกใช้คำสั่งนี้:

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

แอปจะไม่สูญเสียสถานะและจากประสบการณ์ของฉันเองสิ่งนี้ทำงานในลักษณะเดียวกับที่ OS ฆ่าแอปในเบื้องหลัง ใช้งานได้กับแอพพลิเคชั่นที่สร้างขึ้นมาเท่านั้น


ฉันได้รับ'grep' is not recognized as an internal or external command, operable program or batch file.
Dale

แต่ฉันทำมันในเปลือกrun-as <package name> kill 7379แต่มันทำให้ฉันทำกิจกรรมก่อนหน้านี้ไม่ใช่กิจกรรมที่ฉันทำเมื่อฉันกดปุ่มโฮม
Dale

6

นี่คือวิธีที่คุณทำใน Android Studio

  1. เชื่อมต่ออุปกรณ์ของคุณในโหมดดีบักเชื่อมต่อกับคอมพิวเตอร์ของคุณ
  2. เปิดแอปบนอุปกรณ์ของคุณและไปที่กิจกรรมใดก็ตามที่คุณต้องการทดสอบ "กลับไปที่คนตาย"
  3. กดปุ่ม Home บนอุปกรณ์ของคุณ
  4. ใน Android Studio ไปที่ Android Monitor -> มอนิเตอร์และกดไอคอนยุติการใช้งาน
  5. ตอนนี้คุณสามารถกลับไปที่แอพของคุณผ่านแอพล่าสุดหรือคลิกที่ไอคอนตัวเรียกใช้งานพฤติกรรมในการทดสอบของฉันก็เหมือนกัน

2
นี่ไม่ได้ช่วยอะไรเลย ฉันต้องทำสิ่งนี้โดยทางโปรแกรมในชุดทดสอบ แต่ขอบคุณล่ะค่ะ
David Wasser

นอกจากนี้คำตอบนี้เหมือนกันกับคำตอบของ Mark
David Wasser

มีความคิดอย่างไรในการทำสิ่งนี้ผ่านทาง UIAutomator หรือ Espresso?
IgorGanapolsky

Android Monitor - Monitorsฉันไม่สามารถหา ต้องเป็นสิ่งที่พวกเขากำจัดไป ฉันใช้งาน 3.2.1
Dale

1
@Dale Android Device Monitor เลิกใช้แล้วใน Android Studio 3.1 และลบออกจาก Android Studio 3.2
Valgaal

5

วางแอปพลิเคชันในพื้นหลังด้วยปุ่มหน้าแรก

เลือกกระบวนการของคุณในโหมด "Logcat" ใน Android Studio จากนั้นคลิกยุติแอปพลิเคชันที่มุมด้านล่าง

ปุ่มยกเลิก

ตอนนี้เปิดแอปของคุณจากตัวเรียกใช้บนอุปกรณ์ Android


แก้ไข:ตามอินเทอร์เน็ตต่อไปนี้ยังใช้งานได้:

 adb shell am kill [my-package-name]

แก้ไขจากอนาคต:สิ่งที่ควรทราบมีการเปลี่ยนแปลงใน Android Studio 4.0 หากคุณใช้Runจาก AS แล้วจะออกTerminateForce Stop

อย่างไรก็ตามหากคุณเปิดใช้งานจากตัวเรียกใช้งานในภายหลังและจากนั้นคุณลองจำลองด้วยวิธีนี้คุณจะได้ผลลัพธ์ที่ต้องการ (พฤติกรรมของหน่วยความจำต่ำ)


นี่เป็นคำตอบที่ซ้ำกัน
Onik

@Onik อื่น ๆ ทั้งหมดมีพวงปุยที่ไม่จำเป็นเช่น ddms และอะไรก็ตาม แม้ว่าในทางเทคนิคใช่แล้วstackoverflow.com/a/41975750/2413303พูดในสิ่งเดียวกัน บางทีฉันควรเพิ่มรูปภาพ
EpicPandaForce

สิ่งนี้ไม่เป็นประโยชน์ ฉันมีสายรัดทดสอบและไม่สามารถดำเนินการเหล่านี้ได้จากชุดทดสอบ นอกจากนี้พฤติกรรมไม่เหมือนกับสิ่งที่เกิดขึ้นเมื่อ Android ฆ่ากระบวนการ
David Wasser

the behaviour is not the same as what happens when Android kills the processใช่มันคือ
EpicPandaForce

กระบวนการนี้แสดงกิจกรรมก่อนหน้านี้ไม่ใช่กิจกรรมของเมื่อกดปุ่มโฮม
Dale

2

คุณสามารถทำขั้นตอนถัดไปเพื่อทำให้เกิดพฤติกรรมตามที่ต้องการ:

  1. เปิดแอปของคุณนำทางไปยังกิจกรรมยอดนิยม
  2. ใช้แผงการแจ้งเตือนเพื่อนำทางไปยังแอปพลิเคชันแบบเต็มหน้าจออื่น (ตัวอย่างเช่นไปที่การตั้งค่าระบบ - ที่มุมบนขวา)
  3. ฆ่ากระบวนการสมัครของคุณ
  4. กดปุ่มย้อนกลับ

1
ขอบคุณสำหรับคำตอบของคุณ แต่มันไม่มีประโยชน์สำหรับฉันเพราะฉันต้องการวิธีการอัตโนมัติในการทดสอบอัตโนมัติ
David Wasser

ดังนั้นนี่เป็นวิธีเดียวที่ฉันพบว่าจะจำลองหน่วยความจำในการล้าง Android และฆ่าแอปของคุณ (ระดับ API ของฉันคือ 19 ดังนั้นฉันจึงไม่สามารถใช้คำสั่ง send-trim-memory) คำสั่งอื่น ๆ เช่น adb shell am บังคับให้หยุด com.my.app.package หรือ kill จะไม่สร้างกระบวนการที่แน่นอนเหมือนเดิมซึ่งทำตามขั้นตอนข้างต้น!
มาร์คการ์เซีย

2

ในตัวเลือกนักพัฒนาภายใต้การตั้งค่าเลือก 'ไม่เก็บกิจกรรม' ซึ่งจะทำลายกิจกรรมทันทีที่คุณออกไปจากพวกเขา

หมายเหตุ: ตามความคิดเห็นที่เป็นประโยชน์ด้านล่างใช้เฉพาะในกรณีที่คุณไม่สนใจเกี่ยวกับค่าคงที่ที่จะถูกล้าง


นี่เป็นวิธีเดียวกับโซลูชันที่โพสต์แล้วและถูกปฏิเสธเมื่อหนึ่งปีก่อน ความแตกต่างเพียงอย่างเดียวคือแอปพลิเคชั่นที่ใช้ตั้งค่าบนอีมูเลเตอร์และโทรศัพท์รุ่นล่าสุดที่รองรับ
Chris Stratton

1
ขออภัย Chris Stratton กล่าวว่านี่เป็นคำแนะนำเดียวกับคำตอบอื่น ๆ นี่ไม่เกี่ยวกับกิจกรรมการจบของ Android นี่เป็นเรื่องเกี่ยวกับ Android ที่ฆ่ากระบวนการทั้งหมด (ซึ่งทำได้ค่อนข้างสม่ำเสมอและมีประสิทธิภาพโดยเฉพาะบนอุปกรณ์ HTC ที่ใช้ Android 4.x)
David Wasser

6
อันนี้เกือบจะดี แต่มันจะไม่ฆ่ากระบวนการมันทำลายกิจกรรมเท่านั้น มันหมายความว่าอะไร? กิจกรรมของคุณจะถูกเปิดพร้อมกับ saveInstanceState แต่ตัวแปรสแตติกทั้งหมดยังคงอยู่ในกระบวนการ หลังจากกระบวนการฆ่าตัวแปรสแตติกทั้งหมดจะถูกล้างออกด้วย
ทำเครื่องหมาย

1

กดปุ่มโฮมแล้ววางแอพไว้ในพื้นหลังก่อน จากนั้นหยุดหรือฆ่ากระบวนการจาก DDMS หรือ ADB


ขอบคุณสำหรับคำตอบของคุณ แต่มันไม่มีประโยชน์สำหรับฉันเพราะฉันต้องการวิธีการอัตโนมัติในการทดสอบอัตโนมัติ
David Wasser

Android จะไม่ฆ่ากระบวนการของคุณหากกิจกรรมของคุณอยู่ในเบื้องหน้า คุณกำลังพยายามทดสอบเงื่อนไขที่จะไม่เกิดขึ้น หากกิจกรรมของคุณอยู่ในพื้นหลังสถานะของกิจกรรมนั้นจะได้รับการบันทึกแล้วและไม่มีความแตกต่างระหว่างการที่คุณฆ่ามันด้วยตนเองและ Android จะฆ่ามันภายใต้หน่วยความจำต่ำนั่นคือกระบวนการเพิ่งถูกฆ่า ไม่มีอะไรพิเศษเกี่ยวกับการฆ่าความทรงจำต่ำ เมื่อหน่วยความจำพร้อมใช้งานอีกครั้งบริการติดหนึบของคุณจะเริ่มต้นใหม่ (ยกเว้นใน 4.4) และเมื่อคุณแตะที่ไอคอนหรืองานล่าสุดสถานะสแต็คและกิจกรรมจะถูกกู้คืน
Monstieur

3
ในตัวอย่างของคุณมันจะกลับไปที่กิจกรรม C เพราะคุณฆ่ากระบวนการในขณะที่กิจกรรม D ปรากฏบนหน้าจอ (สิ่งนี้จะไม่เกิดขึ้นแม้ในหน่วยความจำต่ำ) และสถานะของกิจกรรม C ถูกบันทึกไว้เนื่องจากอยู่ในพื้นหลัง กระบวนการของคุณจะถูกฆ่าหากไม่ได้อยู่เบื้องหน้าเลยนั่นคือสถานะของกิจกรรม D จะได้รับการบันทึกเมื่อมันเข้าสู่พื้นหลังและจะถูกกู้คืนแม้ว่ากระบวนการของคุณจะถูกฆ่า เพื่อทำการทดสอบของคุณในแต่ละกิจกรรมคุณต้องส่งแอปไปที่พื้นหลังก่อนที่คุณจะฆ่ามัน
Monstieur

อะไรที่คุณหมายถึง ~ " และใส่ app ในพื้นหลังแรก "?
IgorGanapolsky

1

นอกจากนี้คุณยังสามารถเชื่อมต่อกับอุปกรณ์ของคุณ / จำลองจากสถานีด้วยadb shellแล้วได้รับ PID ของกระบวนการของคุณด้วยและดำเนินการps | grep <your_package_name kill -9 <pid>จากนั้นเปิดแอพที่ย่อเล็กสุดจากตัวเลือกแอพล่าสุดและมันจะเริ่มต้นกิจกรรมล่าสุดอีกครั้ง


นั่นเป็นเช่นเดียวกับ Android ที่ฆ่ากระบวนการภายใต้เงื่อนไขหน่วยความจำต่ำหรือไม่? ฉันคิดว่า OP ต้องการเป็นพิเศษ ...
IgorGanapolsky

1
@IgorGanapolsky ตามหลักวิชาแล้วแม้ว่าคุณจะไม่สามารถทำได้บนอุปกรณ์จริงถ้ามันไม่ได้ถูกรูท
Fran Marzoa

0

รากของปัญหาของคุณดูเหมือนว่าActivityอยู่ในเบื้องหน้าเมื่อคุณฆ่ากระบวนการ

คุณสามารถสังเกตสิ่งนี้ได้โดยกดหยุดใน DDMS เมื่อActivityมองเห็นได้ (เกิดขึ้นตามที่คุณอธิบาย) และเปรียบเทียบกับการกดหยุดหลังจากที่บ้านและกลับมาที่แอป

เพียงแค่ให้แน่ใจว่าmoveTaskToBack(true)อย่างใดในการทดสอบของคุณ


0

ฉันไม่แน่ใจว่านี่คือคำตอบที่คุณกำลังมองหามันเหมือนมีเหตุผลคิด

ฉันไม่คิดว่าคุณจะสามารถทำการทดสอบอัตโนมัติได้อย่างสมบูรณ์วิธีเดียวที่จะจำลองมันจะเป็นการสร้างใหม่ AKA มีกิจกรรมมากมายที่ Android จะฆ่าแอปพลิเคชันของคุณ

ดังนั้นความคิดหรือข้อเสนอแนะของฉันคือการสร้างแอพเล็ก ๆ ขึ้นมาใหม่ซึ่งทำให้กิจกรรมใหม่ ๆ เกิดขึ้นเรื่อย ๆ จนกระทั่ง Android มีหน่วยความจำไม่เพียงพอและเริ่มฆ่ามันเป็นพื้นหลัง

บางสิ่งบางอย่างในบรรทัด:

เริ่มกิจกรรม i -> ตรวจสอบกระบวนการทำงานหากแอพอยู่ในรายการเพิ่ม i และรีสตาร์ทลูปโดยไม่ปิดกิจกรรมปัจจุบันมิฉะนั้น -> ลด i และปิดกิจกรรมปัจจุบันกลับไปก่อนหน้าและตรวจสอบอีกครั้ง ...


0

เมื่อกระบวนการแอปพลิเคชันตายไป Android จะทำการบันทึกกิจกรรม (รายการจะแสดงกิจกรรมในสแต็คประวัติ) และตัดสินใจว่าจะเก็บรายการใดไว้ในประวัติและรายการที่จะลบออกจากนั้น

หนึ่งในประเด็นสำคัญที่นี่คือActivityRecordฟิลด์ที่เรียกว่าhaveStateวิศวกร Android Framework อธิบายว่า "เราได้รับสถานะกิจกรรมล่าสุดแล้วหรือยัง"

ตามค่าเริ่มต้น Android จะถือว่ากิจกรรมนั้นมีสถานะ กิจกรรมจะไร้สัญชาติเมื่อแอปพลิเคชันรายงานไปยังบริการตัวจัดการงานกิจกรรมที่กิจกรรมดำเนินการต่อและกิจกรรมนี้จะใช้ได้จนกระทั่งแอปพลิเคชันแจ้งเฟรมเวิร์กที่กิจกรรมได้เข้าสู่สถานะหยุดทำงาน ในคำง่าย ๆhaveStateคุณค่าคือfalseระหว่างกิจกรรมที่onResume()เรียกว่าและonStop()หรือonSaveInstanceState()ถูกเรียกขึ้นอยู่กับรุ่นเป้าหมายของแอปพลิเคชัน

หากฉันฆ่ากระบวนการ Android จะสร้างกระบวนการขึ้นใหม่และสร้าง ActivityC

ในกรณีนี้ ActivityD ไม่มีandroid:stateNotNeeded="true"แอตทริบิวต์ในรายการแอปพลิเคชันและกำลังทำงานในเบื้องหน้าดังนั้น Android จะลบออกจากประวัติเนื่องจากระบบไม่ได้รับสถานะล่าสุด

วิธีจำลอง Android ที่ฆ่ากระบวนการของฉัน

ตามที่ได้กล่าวมาหลายครั้งคุณสามารถย้ายแอปพลิเคชั่นไปยังพื้นหลังดังนั้นกิจกรรมยอดนิยมในแบ็คอัพกิจกรรมจะบันทึกสถานะของมันและหลังจากนั้นคุณสามารถฆ่ากระบวนการแอปพลิเคชันผ่าน Android Debug Bridge, Android Studio หรือใช้ กระบวนการพื้นหลัง จำกัด คุณสมบัติในตัวเลือกนักพัฒนา หลังจากนั้นกิจกรรมล่าสุดของคุณจะถูกสร้างขึ้นใหม่สำเร็จ

แม้จะมีวิธีการง่าย ๆ อีกวิธีหนึ่งในการทดสอบสถานการณ์การเสียชีวิตของกระบวนการสมัคร รู้ทั้งหมดที่อธิบายไว้ข้างต้นและข้อเท็จจริงที่ว่าถ้าคุณเริ่มต้น ActivityE ใหม่จาก ActivityD ที่กำลังทำงานอยู่ดังนั้นการonStop()เรียกกลับActivityD จะถูกเรียกใช้หลังจากonResume()เมธอดActivityE คุณสามารถทำตามเคล็ดลับต่อไปนี้

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) {}
    }
}

จากนั้นก็เริ่ม TerminatorActivityเมื่อคุณต้องการฆ่าแอปพลิเคชัน

ในตอนท้ายมีเครื่องมือที่มีน้ำหนักเบาที่ช่วยลดการทดสอบของการตายของขั้นตอนการสมัครของคุณเรียกว่าพิษ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.