המערכת שולחת את המשתמש לאפליקציה אחרת

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

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

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

יצירה של כוונה מרומזת

אובייקטים מרומזים של Intent לא מצהירים על שם המחלקה של הרכיב שעליו רוצים להתחיל, אלא מצהירים במקום זאת על לבצע. הפעולה מציינת מה אתם רוצים לעשות, כמו צפייה, לערוך, לשלוח או לקבל משהו.

שיוך של פעולות Intent לנתונים

אובייקטים מסוג Intent כוללים לעיתים קרובות גם נתונים ביחד עם הפעולה, למשל הכתובת שרוצים להציג או הודעת האימייל שרוצים לשלוח. בהתאם ל-Intent שרוצים ליצור, הנתונים יכולים להיות Uri, אחד מכמה סוגי נתונים אחרים, או שכוונת הכוונה לא צריכה נתונים בכלל.

אם הנתונים הם Uri, יש constructor פשוט של Intent() שאפשר להשתמש בו כדי להגדיר את הפעולה, .

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

Kotlin

val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
    Intent(Intent.ACTION_DIAL, number)
}

Java

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

כשהאפליקציה שלך מפעילה את הכוונה הזו באמצעות התקשרות ל-startActivity(), אפליקציית 'טלפון' מבצעת שיחה למספר הטלפון הנתון.

הנה כמה כוונות אחרות, הפעולה ונתוני Uri שלהן זוגות:

הצגת מפה

Kotlin

// Map point based on address
val mapIntent: Intent = Uri.parse(
        "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"
).let { location ->
    // Or map point based on latitude/longitude
    // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level
    Intent(Intent.ACTION_VIEW, location)
}

Java

// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

צפייה בדף אינטרנט

Kotlin

val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage ->
    Intent(Intent.ACTION_VIEW, webpage)
}

Java

Uri webpage = Uri.parse("https://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

הוספת תוספות ל-Intent

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

כברירת מחדל, המערכת קובעת את סוג ה-MIME המתאים שנדרש על ידי Intent על סמך הנתונים של Uri כלולים. אם לא כוללים Uri ב Intent, בדרך כלל צריך להשתמש בפונקציה setType() כדי לציין את הסוג של נתונים שמשויכים לכוונה. הגדרת סוג MIME מציינת גם אילו סוגים של הפעילויות צריכות לקבל את הכוונה.

הנה עוד כמה כוונות שמוסיפות נתונים כדי לציין את הפעולה הרצויה:

שליחת אימייל עם קובץ מצורף

Kotlin

Intent(Intent.ACTION_SEND).apply {
    // The intent does not have a URI, so declare the "text/plain" MIME type
    type = "text/plain"
    putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@example.com")) // recipients
    putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    putExtra(Intent.EXTRA_TEXT, "Email message text")
    putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"))
    // You can also attach multiple items by passing an ArrayList of Uris
}

Java

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jan@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris

יצירת אירוע ביומן

הערה: ה-Intent הזה עבור אירוע ביומן נתמך רק באמצעות API ברמה 14 ומעלה.

Kotlin

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply {
    val beginTime: Calendar = Calendar.getInstance().apply {
        set(2021, 0, 23, 7, 30)
    }
    val endTime = Calendar.getInstance().apply {
        set(2021, 0, 23, 10, 30)
    }
    putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis)
    putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis)
    putExtra(Events.TITLE, "Ninja class")
    putExtra(Events.EVENT_LOCATION, "Secret dojo")
}

Java

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance();
beginTime.set(2021, 0, 23, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2021, 0, 23, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

הערה: חשוב להגדיר את Intent באופן ספציפי ככל האפשר. לדוגמה, אם רוצים להציג תמונה באמצעות Intent ACTION_VIEW, עליך לציין סוג MIME של image/*. האפשרות הזו מונעת מאפליקציות שיכולות "לצפות" סוגים אחרים של נתונים (כמו אפליקציית מפות) שמופעל על ידי הכוונה.

התחלת פעילות מתוך כוונה

לאחר יצירת Intent והגדרת המידע הנוסף, יש להתקשר למספר startActivity() כדי לשלוח אותו למערכת:

Kotlin

startActivity(intent)

Java

startActivity(intent);

צריך לטפל במצב שבו אף אפליקציה לא יכולה לקבל כוונה

למרות שכוונות רבות מטופלות בהצלחה על ידי אפליקציה אחרת שמותקנת במכשיר – כמו אפליקציית טלפון, אימייל או יומן – האפליקציה צריכה להכין למצב שבו אף פעילות לא יכולה לטפל בכוונה של האפליקציה. בכל פעם שאתם לעורר כוונה, להיות מוכנים לקלוט ActivityNotFoundException מצב כזה יכול לקרות אם אין פעילות אחרת שיכולה לטפל בכוונה של האפליקציה:

Kotlin

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

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

תיבת דו-שיח של הבהרה

אם המערכת מזהה יותר מפעילות אחת שיכולה לטפל בכוונה, היא מציגה תיבת דו-שיח (נקראת לפעמים 'תיבת דו-שיח של הבהרה') כדי לבחור באיזו אפליקציה להשתמש, כפי שמוצג באיור 1. אם יש רק אחד פעילות שמטפלת בכוונה, המערכת מיד מפעילה אותה.

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

איור 1. דוגמה לבחירה תיבת דו-שיח שמופיעה כאשר יותר מאפליקציה אחת יכולה לטפל בכוונה.

דוגמה מלאה

הנה דוגמה מלאה שמדגימה איך ליצור כוונה לצפייה במפה, כדי לוודא שהכוונה קיימת כדי לטפל בכוונה, ואז להתחיל בה:

Kotlin

// Build the intent.
val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California")
val mapIntent = Intent(Intent.ACTION_VIEW, location)

// Try to invoke the intent.
try {
    startActivity(mapIntent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

// Build the intent.
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Try to invoke the intent.
try {
    startActivity(mapIntent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

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

איור 2. תיבת דו-שיח של בורר.

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

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

כדי להציג את הבורר, צריך ליצור Intent באמצעות createChooser() ולהעביר אותו אל startActivity(). לדוגמה:

Kotlin

val intent = Intent(Intent.ACTION_SEND)

// Create intent to show chooser
val chooser = Intent.createChooser(intent, /* title */ null)

// Try to invoke the intent.
try {
    startActivity(chooser)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);

// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, /* title */ null);

// Try to invoke the intent.
try {
    startActivity(chooser);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

תוצג תיבת דו-שיח עם רשימת אפליקציות שמגיבות לכוונה שהועברה ל-method createChooser(). הפרמטר title יכול להיות צוין אם הפעולה היא לא ACTION_SEND או ACTION_SEND_MULTIPLE