התחלת פעילות מהתראה

כשמתחילים פעילות מתוך התראה, צריך לשמור על חוויית הניווט שהמשתמש מצפה לה. הקשה על לחצן 'הקודם' צריכה להחזיר את המשתמש למסך הבית דרך תהליך העבודה הרגיל של האפליקציה, ופתיחת מסך הפריטים האחרונים צריכה להציג את הפעילות כמשימה נפרדת. כדי לשמור על חוויית הניווט הזו, צריך להתחיל את הפעילות במשימה חדשה.

הגישה הבסיסית להגדרת ההתנהגות של ההקשה על ההתראה מתוארת במאמר יצירת התראה בסיסית. בדף הזה מוסבר איך להגדיר PendingIntent לפעולה של ההתראה כדי ליצור משימה חדשה ומקבץ פעילויות קודמות (back stack). האופן שבו עושים את זה תלוי בסוג הפעילות שמתחילים:

  • פעילות רגילה: פעילות שקיימת כחלק מזרימת חוויית המשתמש הרגילה של האפליקציה. כשמשתמש מגיע ל-Activity מההתראה, המשימה החדשה צריכה לכלול מקבץ פעילויות קודמות (back stack) מלא, כדי שהמשתמש יוכל להקיש על הכפתור "הקודם" ולנווט במעלה ההיררכיה של האפליקציה.
  • פעילות מיוחדת: המשתמש רואה את הפעילות הזו רק אם היא התחילה מהתראה. במובן מסוים, הפעילות הזו מרחיבה את ממשק המשתמש של ההתראות, כי היא מספקת מידע שקשה להציג בהתראה עצמה. לפעילות הזו לא צריך מקבץ פעילויות קודמות (back stack).

הגדרת פעילות רגילה של PendingIntent

כדי להתחיל Activity רגילה מההתראה, צריך להגדיר את PendingIntent באמצעות TaskStackBuilder כך שייווצר מקבץ פעילויות קודמות (back stack) חדש, באופן הבא.

הגדרה של היררכיית הפעילויות באפליקציה

כדי להגדיר את ההיררכיה הטבעית של הפעילויות, מוסיפים את המאפיין android:parentActivityName לכל רכיב <activity> בקובץ המניפסט של האפליקציה. מקרה לדוגמה:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<!-- MainActivity is the parent for ResultActivity. -->
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity" />
    ...
</activity>

יצירת PendingIntent עם מקבץ פעילויות קודמות (back stack)

כדי להתחיל פעילות שכוללת מקבץ פעילויות קודמות (back stack) של פעילויות, יוצרים מופע של TaskStackBuilder וקוראים ל-addNextIntentWithParentStack(), ומעבירים לו את Intent של הפעילות שרוצים להתחיל.

כל עוד מגדירים את פעילות האב לכל פעילות כמו שמתואר בהמשך, אפשר לקרוא ל-getPendingIntent() כדי לקבל PendingIntent שכולל את כל מקבץ פעילויות קודמות (back stack).

// Create an Intent for the activity you want to start.
val resultIntent = Intent(this, ResultActivity::class.java)
// Create the TaskStackBuilder.
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
    // Add the intent, which inflates the back stack.
    addNextIntentWithParentStack(resultIntent)
    // Get the PendingIntent containing the entire back stack.
    getPendingIntent(
        0,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
}

אם צריך, אפשר להוסיף ארגומנטים לאובייקטים Intent במערך על ידי קריאה ל-TaskStackBuilder.editIntentAt(). לפעמים זה נדרש כדי להבטיח שפעילות במקבץ פעילויות קודמות (back stack) תציג נתונים משמעותיים כשהמשתמש ינווט אליה.

אחר כך אפשר להעביר את PendingIntent להתראה כרגיל:

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentIntent(resultPendingIntent)
    // ...
}
with(NotificationManagerCompat.from(this)) {
    notify(NOTIFICATION_ID, builder.build())
}

הגדרה של אובייקט PendingIntent לפעילות מיוחדת

מכיוון שפעילות מיוחדת שמתחילה מהתראה לא צריכה מחסנית חזרה, אפשר ליצור את PendingIntent על ידי קריאה ל-getActivity(). עם זאת, צריך להגדיר את אפשרויות המשימה המתאימות במניפסט.

  1. במניפסט, מוסיפים את המאפיינים הבאים לרכיב <activity>.

    android:taskAffinity=""
    בנוסף לדגל FLAG_ACTIVITY_NEW_TASK שבו משתמשים בקוד, צריך להגדיר את המאפיין הזה כריק כדי לוודא שהפעילות הזו לא תועבר למשימת ברירת המחדל של האפליקציה. משימות קיימות עם ההעדפה שמוגדרת כברירת מחדל באפליקציה לא יושפעו.
    android:excludeFromRecents="true"
    הפעולה מחריגה את המשימה החדשה ממסך הפעולות האחרונות, כך שהמשתמש לא יוכל לחזור אליה בטעות.

    כך זה נראה בדוגמה הבאה:

    <activity
    android:name=".ResultActivity"
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:excludeFromRecents="true">
    </activity>

  2. יוצרים את ההתראה ושולחים אותה:

    1. יוצרים Intent שמתחיל את Activity.
    2. כדי להגדיר את Activity להתחלה במשימה חדשה וריקה, קוראים ל-setFlags() עם הדגלים FLAG_ACTIVITY_NEW_TASK ו-FLAG_ACTIVITY_CLEAR_TASK.
    3. יוצרים PendingIntent על ידי התקשרות אל getActivity().

    כך זה נראה בדוגמה הבאה:

    val notifyIntent = Intent(this, ResultActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val notifyPendingIntent = PendingIntent.getActivity(
        this, 0, notifyIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

  3. מעבירים את PendingIntent להתראה כרגיל:

    val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
        setContentIntent(notifyPendingIntent)
        // ...
    }
    with(NotificationManagerCompat.from(this)) {
        notify(NOTIFICATION_ID, builder.build())
    }

מידע נוסף על האפשרויות השונות של המשימות ועל אופן הפעולה של מקבץ הפעילויות הקודמות (back stack) זמין במאמר משימות ומקבץ הפעילויות הקודמות (back stack).