เจตนา - ถ้ากิจกรรมกำลังดำเนินอยู่ให้นำมาไว้ข้างหน้ามิฉะนั้นจะเริ่มกิจกรรมใหม่ (จากการแจ้งเตือน)


129

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

สิ่งที่ฉันต้องการให้ทำคือการนำกิจกรรมที่ระบุในการแจ้งเตือนที่ค้างอยู่ไปข้างหน้าถ้ามันกำลังทำงานอยู่หรือไม่ก็เริ่มทำ

จนถึงตอนนี้เจตนา / ความตั้งใจที่รอดำเนินการสำหรับการแจ้งเตือนที่ฉันมีอยู่

private static PendingIntent prepareIntent(Context context) {
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

และแปลกบางครั้งมันใช้งานได้บางครั้งมันไม่ ... ฉันรู้สึกว่าฉันได้ลองทุกชุดผสมกันแล้ว

คำตอบ:


131

คุณสามารถใช้สิ่งนี้:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

ซึ่งจะทำงานคล้ายกับ"singleInstance"แต่จะไม่มีภาพเคลื่อนไหวแปลก ๆ


15
+1 คุณควรเป็นคำตอบที่ยอมรับได้ ความแตกต่างอยู่ที่นี่: developer.android.com/guide/topics/manifest/…
user1032613

1
ในการชี้แจงให้ใช้ singleTask หากคุณมีหลายกิจกรรมในแอพและนี่คือ parent ซึ่งเป็น singleInstance หากคุณมีเพียงกิจกรรมเดียว
frostymarvelous

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

ฉันมีแผนที่ Messenger คู่กิจกรรม ฉันต้องการแสดงอินสแตนซ์ของกิจกรรมถ้าฉันได้รับข้อความจากมัน มีวิธีใดบ้างในการทำเช่นนี้ เช่น HashMap.get (Messenger) .bringActivityToFront (); ฉันหมายถึงกิจกรรมยังคงทำงานอยู่ ถ้าฉันเปิดงานล่าสุดและคลิกมันจะ onResume (); Cant I onResume () โดยทางโปรแกรม

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

46

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

นี่คือวิธีที่กิจกรรมถูกประกาศเป็นอินสแตนซ์เดียว:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleInstance"/>

นอกจากนี้เพื่อหลีกเลี่ยงภาพเคลื่อนไหวที่ขาด ๆ หาย ๆ เมื่อเปิดใช้งานผ่าน singleInstance คุณสามารถใช้แทน "singleTask" ซึ่งทั้งคู่คล้ายกันมาก แต่มีการอธิบายความแตกต่างที่นี่ตามเอกสารของ Google:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

singleInstance เหมือนกับ "singleTask" ยกเว้นว่าระบบจะไม่เปิดกิจกรรมอื่น ๆ ในงานที่เก็บอินสแตนซ์ กิจกรรมนี้เป็นสมาชิกของงานเพียงคนเดียวเท่านั้น

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

ความนับถือ!


4
ดูเหมือนว่าจะใช้งานได้ แต่ตอนนี้ทุกกิจกรรมใหม่ที่ฉันเปิดตัวจาก MainActivity เดียวเล่นแอนิเมชั่นที่แปลกประหลาดนี้แทนที่จะเป็นสีจางและเกล็ดทั่วไป
urSus

ฉันจะเปิดตัวกิจกรรมใหม่ทุกครั้ง แต่จะล้างอินสแตนซ์ที่ทำงานอยู่ทั้งหมดของมันซึ่งจะเป็นไปได้หรือไม่
urSus

ดีฉันไม่คิดว่าการเคลื่อนไหวที่คุณกล่าวถึงมีอะไรที่จะทำอย่างไรกับ "ทรัพย์สิน singleInstance" ทั้งหมดก็จะเป็นการนำอินสแตนซ์ที่มีอยู่แล้วบางทีที่นิเมชั่นที่คุณกำลังพูดถึงเป็นปัญหาที่แตกต่างกันเสร็จสมบูรณ์ ...
มาร์ติน Cazares

1
ฉันกำลังทดสอบมันอยู่ตอนนี้และก็ใช้ได้ หากฉันลบการตั้งค่าสถานะความตั้งใจทั้งหมดและเพียงตั้งค่า launchMode = "singleInstance" ในไฟล์ Manifest ภาพเคลื่อนไหวแปลก ๆ อยู่ที่นั่นถ้าฉันลบออกมันจะกลับมาเป็นปกติ
urSus

ใช่ตามเอกสารประกอบของ Android ดูเหมือนว่าภาพเคลื่อนไหว "init" จะไม่อยู่ที่นั่นอีกต่อไปเพราะกิจกรรมไม่ได้ถูกกำหนดค่าเริ่มต้นกำลังนำกลับมาใช้ใหม่ ...
Martin Cazares

26

ผมคิดว่าสิ่งที่คุณต้องการในsingleTop Activityมากกว่าหรือsingleTasksingleInstance

<activity android:name=".MyActivity"
          android:launchMode="singleTop"
          ...the rest... >

สิ่งที่เอกสารกล่าวว่าไม่เหมาะกับที่ดีที่สุดที่คุณต้องการ:

[... ] อาจมีการสร้างอินสแตนซ์ใหม่ของsingleTopกิจกรรม "" เพื่อจัดการกับเจตนาใหม่ อย่างไรก็ตามหากภารกิจเป้าหมายมีอินสแตนซ์ที่มีอยู่ของกิจกรรมที่ด้านบนสุดของสแต็กอินสแตนซ์นั้นจะได้รับเจตนาใหม่ (ในการonNewIntent()โทร); ไม่ได้สร้างอินสแตนซ์ใหม่ ในสถานการณ์อื่น - ตัวอย่างเช่นถ้าอินสแตนซ์ที่มีอยู่ของsingleTopกิจกรรม "" อยู่ในภารกิจเป้าหมาย แต่ไม่ใช่ที่ด้านบนสุดของสแต็กหรือถ้าอยู่ด้านบนสุดของสแต็ก แต่ไม่ใช่ในภารกิจเป้าหมาย - ใหม่ จะสร้างและผลักดันอินสแตนซ์บนสแต็ก

นอกเหนือจากนั้น (ไม่มีการเล่นสำนวนที่ตั้งใจ) ฉันมีความต้องการเช่นเดียวกับคุณ ฉันทดสอบlaunchModeธงทั้งหมดเพื่อดูว่าพวกเขาปฏิบัติจริง ๆ อย่างไรและผลที่ได้singleTopคือสิ่งที่ดีที่สุดสำหรับเรื่องนี้: ไม่มีแอนิเมชั่นแปลก ๆ แอพแสดงครั้งเดียวในรายการแอปพลิเคชันล่าสุด (ไม่เหมือนsingleInstanceที่แสดง ไม่อนุญาตให้บุคคลอื่นActivityเป็นส่วนหนึ่งของงาน) และมีพฤติกรรมที่เหมาะสมโดยไม่คำนึงว่าเป้าหมายActivityนั้นมีอยู่แล้วหรือไม่


2
ทำงานจนถึง 22.00 น. ในคืนวันศุกร์และนี่คือสิ่งที่ฉันต้องการ ... ชีวิตนักพัฒนาเศร้า
felixwcf

บันทึกเวลาของฉันมาก! ขอบคุณ!
hetsgandhi

13

นี่คือหัวข้อเก่า แต่สำหรับทุกคนที่ยังคงต้องการคำตอบนี่คือทางออกของฉัน มันอยู่ในรหัสล้วนๆโดยไม่ต้องตั้งค่ารายการ:

private static PendingIntent prepareIntent(Context context) {
  Intent intent = new Intent(context, MainActivity.class);
  intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);      
  return PendingIntent.getActivity(context, NON_ZERO_REQUEST_CODE, intent, 
    PendingIntent.FLAG_UPDATE_CURRENT);
}

ที่นี่ FLAG_ACTIVITY_SINGLE_TOP เปิดกิจกรรมที่มีอยู่หากอยู่ที่ด้านบนสุดของภาระงาน หากไม่อยู่ที่ด้านบน แต่อยู่ในกองซ้อน FLAG_ACTIVITY_CLEAR_TOP จะลบกิจกรรมทั้งหมดที่ด้านบนของกิจกรรมเป้าหมายและแสดง หากกิจกรรมไม่ได้อยู่ในสแต็กงานกิจกรรมใหม่จะถูกสร้างขึ้น จุดสำคัญที่ต้องพูดถึง - พารามิเตอร์ตัวที่สองของ PendingIntent.getActivity (), requestCode ควรมีค่าที่ไม่เป็นศูนย์ (ฉันเรียกมันว่า NON_ZERO_REQUEST_CODE ในตัวอย่างของฉัน) มิฉะนั้นการตั้งค่าสถานะเจตนาจะไม่ทำงาน ฉันไม่รู้ว่าทำไมมันเป็นอย่างที่มันเป็น ตั้งค่าสถานะ FLAG_ACTIVITY_SINGLE_TOP สามารถใช้แทนกันได้กับ android: launchMode = "singleTop" ในแท็กกิจกรรมในรายการ


การต่อสู้มาหลายชั่วโมงด้วยธงเหล่านี้และสงสัยว่าทำไมการเปลี่ยนสถานะความตั้งใจของฉันไม่ได้เปลี่ยนแปลงอะไร รหัสคำขอที่ไม่เป็นศูนย์ ... เป็นจุดสำคัญที่ต้องพูดถึง !!! ใช้งานได้ทันที! ขอบคุณ!
Max Power

9

ฉันรู้ว่ามันเก่า แต่ไม่มีอะไรจากด้านบนมีความเหมาะสมกับใบสมัครของฉัน

นี่คือรหัสที่จะนำแอปของคุณกลับมาที่หน้า - หรือเปิดมันเมื่อมันถูกปิด

Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setPackage(null); // The golden row !!!
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

นี่คือคำตอบที่แท้จริง!
azizbekian

2
ไม่มันไม่ทำงาน - เพิ่มกิจกรรมใหม่ที่ด้านบนของกิจกรรมปัจจุบัน
Tobliug

3

ฉันลองสิ่งนี้และใช้งานได้แม้ว่า IDE จะบ่นเกี่ยวกับรหัส

Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT)
            .setSmallIcon(R.drawable.cast_ic_notification_0)
            .setContentTitle("Title")
            .setContentText("Content")
            .setContentIntent(intent)
            .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
            .setAutoCancel(true)
            /*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/;
    NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(0, mBuilder.build());

2
<activity android: name = ". MainActivity" android: launchMode = "singleTask">
nada

Intent.FLAG_ACTIVITY_REORDER_TO_FRONTไม่ใช่ธงที่ถูกต้องสำหรับPendingINtent.getActivity
rds

@rds คุณสามารถลิงค์แหล่งที่มาได้หรือไม่?
Louis CAD

@LouisCAD ฉันขอโทษฉันไม่สามารถเข้าถึงซอร์สโค้ดได้อีก
nada

@rds ฉันไม่ได้ขอรหัสที่มา แต่สำหรับการเชื่อมโยงของการที่คุณอ่านที่ไม่ได้เป็นธงที่ถูกต้องเมื่อใช้เป็นIntent.FLAG_ACTIVITY_REORDER_TO_FRONT PendingIntentหรือบางทีคุณอาจหมายถึงว่ามันไม่ถูกต้องที่จะผ่านเข้าไปในgetActivityวิธีการ แต่สามารถใช้เป็นIntentแฟล็กที่ใช้เป็นPendingIntent?
Louis CAD

2

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

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);

API11 + เท่านั้น


0

ผมมีปัญหาที่คล้ายกันหลังจากที่เพิ่มการแจ้งเตือนที่พบบนเว็บไซต์การฝึกอบรมหุ่นยนต์ ไม่มีคำตอบอื่นที่นี่ใช้ได้สำหรับฉันอย่างไรก็ตามคำตอบนี้ใช้ได้สำหรับฉัน สรุป:

final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.