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


122

ฉันต้องการทราบว่าผู้ใช้จะกลับไปที่หน้าจอหลักหรือไม่หากเขาออกจากกิจกรรมปัจจุบัน


1
สิ่งนี้อาจช่วยได้: stackoverflow.com/questions/2590581/activities-stack
bigstones

43
เพิ่งพบว่ามีฟังก์ชั่นในกิจกรรมที่เรียกว่าisTaskRootซึ่งฉันคิดว่าสามารถช่วยคุณได้
H9kDroid

คำตอบ:


116

UPDATE (ก.ค. 2558):

เนื่องจากgetRunningTasks ()เลิกใช้งานแล้วจาก API 21 จะดีกว่าถ้าทำตามคำตอบraukodraug หรือEd Burnette one (ฉันชอบอันที่สองมากกว่า)


มีความเป็นไปเพื่อตรวจสอบงานในปัจจุบันและสแต็คของพวกเขาใช้เป็นActivityManager

ดังนั้นเพื่อตรวจสอบว่ากิจกรรมเป็นกิจกรรมสุดท้ายหรือไม่:

  • ขอสิทธิ์ android.permission.GET_TASKS ในรายการ
  • ใช้รหัสต่อไปนี้:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

โปรดทราบว่าโค้ดด้านบนจะใช้ได้เฉพาะในกรณีที่คุณมีงานเดียว หากมีความเป็นไปได้ที่จะมีงานจำนวนมากสำหรับแอปพลิเคชันของคุณคุณจะต้องตรวจสอบองค์ประกอบtaskListอื่น ๆ อ่านเพิ่มเติมเกี่ยวกับงานTasks และ Back Stack



25
H9kDroid ได้ให้คำแนะนำที่ถูกต้อง คำตอบที่เลือกคือแฮ็ค เราควรทำอย่างถูกวิธีโดยใช้isTaskRoot()วิธีการ
Sufian

@ ซูเฟียนมันแฮ็คที่ไหนโดยเฉพาะ? โค้ดนี้เป็นตรรกะและใช้ Android API แบบเปิดตามที่ตั้งใจจะใช้ (เช่นควรใช้ getRunningTasks เพื่อเรียกใช้งานและอาจต้องการเรียกใช้โดยมีวัตถุประสงค์เพื่อวิเคราะห์งานเหล่านี้เท่านั้น) การใช้ get (0) มีการบันทึกไว้อย่างดีและมีเหตุผล 'ส่งคืนรายการของงานที่กำลังทำงานอยู่โดยงานล่าสุดจะเป็นงานแรกและงานเก่าตามลำดับ'
sandrstar

2
getRunningTasks () เลิกใช้งานแล้วใน API ระดับ 21
gilchris

ฉันสามารถทำสิ่งเดียวกันกับชิ้นส่วน ถ้าใช่แล้วอย่างไร โปรดช่วย
Sagar Devanga

1
@ Mr.Drew ดูคำตอบที่ได้รับการโหวตสูงสุดจาก @ raukodraug
David Wasser

167

ฉันจะโพสต์ความคิดเห็นของ@ H9kDroidเป็นคำตอบที่ดีที่สุดสำหรับผู้ที่มีคำถามคล้ายกัน

คุณสามารถใช้isTaskRoot ()เพื่อทราบว่ากิจกรรมนั้นเป็นรากฐานของงานหรือไม่

ฉันหวังว่านี่จะช่วยได้


1
โปรดระบุโค้ดบรรทัดเดียวเพื่อให้ชัดเจนเกี่ยวกับวิธีใช้ isTaskRoot ขอบคุณ
Kaveesh Kanwal

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
ปัญหาเดียวคือใน <= 4.4 ฉันเห็นว่ามันมีพฤติกรรมที่แตกต่างจากใน> = 5.x ดูเหมือนว่าจะส่งคืนเท็จเสมอ
chubbsondubs

ฉันคิดว่าคุณควรพิจารณารวมโค้ดตัวอย่างที่ให้ไว้ในความคิดเห็นลงในคำตอบเพื่อให้ง่ายขึ้นสำหรับผู้อ่านในอนาคต
Isac

คำตอบที่ดีเยี่ยม ในกรณีของฉันหลังจากที่ผู้ใช้คลิกที่การแจ้งเตือนกิจกรรมอาจเป็นรูทหากพวกเขาปิดแอปพลิเคชันก่อน
dave o grady

19

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

วิธีแก้ปัญหา:ฉันใช้isTaskRoot()ซึ่งส่งคืนจริงหากกิจกรรมปัจจุบันเป็นเพียงกิจกรรมในสแต็กของคุณและนอกเหนือจากฉันยังจัดการกรณีที่หากฉันมีกิจกรรมบางอย่างในสแต็กให้ไปที่กิจกรรมสุดท้ายในสแต็กแทนที่จะเปิดกิจกรรมที่กำหนดเองใหม่

ในกิจกรรมของคุณ

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }


5

แม้ว่าอาจมีวิธีที่จะบรรลุเป้าหมายนี้ได้ (ดูคำตอบอื่น ๆ ) ฉันขอแนะนำว่าคุณไม่ควรทำเช่นนั้น แอปพลิเคชัน Android ปกติไม่จำเป็นต้องรู้ว่าหน้าจอหลักกำลังจะแสดงหรือไม่

หากคุณกำลังพยายามบันทึกข้อมูลให้ใส่รหัสประหยัดข้อมูลในเมธอด onPause () หากคุณกำลังพยายามให้ผู้ใช้เปลี่ยนใจเกี่ยวกับแอปพลิเคชันที่มีอยู่คุณสามารถสกัดกั้นคีย์ขึ้น / ลงสำหรับปุ่มย้อนกลับและวิธี onBackPressed () และนำเสนอด้วยข้อความ "คุณแน่ใจหรือไม่" รวดเร็ว


1
ถ้าฉันต้องการให้บริการทำงานตราบเท่าที่ผู้ใช้ยังไม่ออกจากกิจกรรม ฉันไม่สามารถดักฟังก์ชั่นใด ๆ เช่น onStop ได้เนื่องจากสามารถเรียกใช้ฟังก์ชันเหล่านี้ได้หลังจากปิดหน้าจอแล้ว
Michael

2
หากบริการพื้นหลังเปิดตัวกิจกรรมบางทีคุณอาจต้องการทราบว่านั่นเป็นกิจกรรมเดียวบนสแต็กหรือไม่
Matt W

4

วิธีหนึ่งในการติดตามสิ่งนี้คือการใส่เครื่องหมายเมื่อคุณเริ่มกิจกรรมใหม่และตรวจสอบว่ามีเครื่องหมายอยู่หรือไม่

เมื่อใดก็ตามที่คุณเริ่มกิจกรรมใหม่ให้ใส่เครื่องหมาย:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

จากนั้นคุณสามารถตรวจสอบได้ดังนี้:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
ใช้ไม่ได้หากกิจกรรมถูกฆ่าและสแต็กกิจกรรมถูกสร้างขึ้นใหม่ - แต่ละกิจกรรมตามความต้องการ
AlikElzin-kilaka

3

ปัญหาในการแก้ปัญหาของ sandrstar ActivityManagerคือคุณต้องได้รับอนุญาตเพื่อรับงานด้วยวิธีนี้ ฉันพบวิธีที่ดีกว่า:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Activityด้านล่างกอง allways ควรจะได้รับหมวดหมู่นี้โดยเริ่มต้นในขณะที่กิจกรรมอื่น ๆ ที่ไม่ควรจะได้รับ
แต่แม้ว่าสิ่งนี้จะล้มเหลวในบางอุปกรณ์คุณสามารถตั้งค่าได้ในขณะที่เริ่มActivity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

จะเป็นอย่างไรหากเปิดกิจกรรมจากการแจ้งเตือนแบบพุช พวกเขาไม่มี CATEGORY LAUNCHER
nbtk

ฉันค่อนข้างแน่ใจว่าส่วนที่สองของคำตอบของฉันยังคงใช้ได้ คุณสามารถกำหนดหมวดหมู่เป็นคำใบ้ในเจตนา ในกรณีนี้อาจเป็นไปตามเจตนาของบริบทการแจ้งเตือนของคุณ นอกเหนือจากนั้นคุณอาจใช้แฟล็กสำหรับสิ่งนี้ ดูลิงก์นี้สำหรับการสร้างการแจ้งเตือนด้วยความตั้งใจ: stackoverflow.com/questions/13716723/…
A. binzxxxxxx

ถึงกระนั้นหากกิจกรรมที่เก่าแก่ที่สุดของคุณคือ MainActivity และตอนนี้กลับมาทำงานต่อจากนั้นคุณจะได้รับการแจ้งเตือนแบบพุชและคุณตั้งค่า pendingIntent ให้เปิดด้วย CATEGORY_LAUNCHER คุณจะมี 2 กิจกรรมในหมวดหมู่นี้ อาจจะทำงานที่แตกต่างกัน
nbtk

ฉันไม่แน่ใจว่ามันทำงานอย่างไรกับการแจ้งเตือน ฉันไม่เคยใช้มันเหมือนที่คุณทำที่นี่ ฉันค่อนข้างแน่ใจว่ามีวิธีง่ายๆในการใช้วิธีนี้ แต่ฉันไม่ได้แตะรหัส Android ตั้งแต่ไตรมาสที่ 1 ปี 2014 บางทีคุณอาจต้องการใช้ประเภทที่สองสำหรับกรณีนี้? หรือฟันธงบ้าง? แต่ฉันเดาว่ามันคงทำงานแบบนี้ แล้วจะเริ่มกิจกรรมหลักและเพิ่มข้อมูลเมตาเพื่อเปิดกิจกรรมที่ถูกต้องได้อย่างไร?
อ. binzxxxxxx

2

ฉันได้สร้างคลาสพื้นฐานสำหรับกิจกรรมทั้งหมดของฉันขยายAppCompatActivityและซึ่งมีตัวนับแบบคงที่:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

สิ่งนี้ได้ผลดีพอสมควรแล้ว และไม่คำนึงถึงเวอร์ชัน API แน่นอนว่ากิจกรรมทั้งหมดจะต้องขยายคลาสพื้นฐานนี้ซึ่งในกรณีของฉัน

แก้ไข:ฉันสังเกตเห็นอินสแตนซ์หนึ่งเมื่อตัวนับลดลงเป็นศูนย์ก่อนที่แอปจะออกอย่างสมบูรณ์ซึ่งก็คือเมื่อมีการเปลี่ยนการวางแนวและเปิดเพียงกิจกรรมเดียวเท่านั้น เมื่อการวางแนวเปลี่ยนไปกิจกรรมจะถูกปิดและอีกกิจกรรมหนึ่งถูกสร้างขึ้นดังนั้นจึงonDestroyedถูกเรียกสำหรับกิจกรรมสุดท้ายจากนั้นonCreateจะถูกเรียกเมื่อกิจกรรมเดียวกันถูกสร้างขึ้นพร้อมกับการวางแนวที่เปลี่ยนไป พฤติกรรมนี้ต้องได้รับการพิจารณา; อาจใช้OrientationEventListener


0

การดำเนินการของ Android กองกิจกรรม, ผมขอแนะนำให้คุณอ่านเกี่ยวกับเรื่องนี้ที่นี่ getCallingActivity()ดูเหมือนว่าสิ่งที่คุณต้องการจะทำก็คือดึงกิจกรรมโทร: หากกิจกรรมปัจจุบันเป็นกิจกรรมแรกในใบสมัครของคุณและการประยุกต์ใช้เปิดตัวจากหน้าจอที่บ้านก็ควร (ฉันคิด) nullผลตอบแทน


9
ซึ่งจะใช้ไม่ได้เนื่องจาก getCallingActivity () จะคืนค่า null หากกิจกรรมไม่ได้เริ่มต้นผ่าน startActivityForResult ()
H9kDroid

0

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

นอกจากนี้คุณไม่แน่ใจว่าการเริ่มต้นกิจกรรมของคุณจากรายการ "กิจกรรมล่าสุด" สามารถตรวจพบได้ด้วยการตั้งค่าข้อมูลพิเศษบางอย่างไว้ล่วงหน้าเพื่อวัตถุประสงค์ในการเปิดกิจกรรมเนื่องจากจะถูกนำกลับมาใช้ในกรณีนั้น

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