שליחת נתונים פשוטים לאפליקציות אחרות

מערכת Android משתמשת בכוונות ובתוספים המשויכים אליהן כדי לאפשר למשתמשים לשתף מידע במהירות ובקלות באמצעות האפליקציות המועדפות עליהם.

ב-Android יש למשתמשים שתי דרכים לשתף נתונים בין אפליקציות:

  • חלונית השיתוף של Android מיועדת בעיקר לשליחת תוכן מחוץ לאפליקציה ו/או ישירות למשתמש אחר. לדוגמה, שיתוף כתובת URL עם חבר.
  • פותר הכוונות של Android מתאים במיוחד להעברת נתונים לשלב הבא של משימה מוגדרת היטב. לדוגמה, פתיחת קובץ PDF מהאפליקציה ומתן אפשרות למשתמשים לבחור את הצופה המועדף.

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

למה כדאי להשתמש בקובץ לשיתוף ב-Android

מומלץ מאוד להשתמש בחלונית השיתוף של Android כדי ליצור עקביות למשתמשים בין האפליקציות. אין להציג רשימה משלה של יעדי שיתוף באפליקציה או ליצור וריאציות משלכם של חלונית השיתוף.

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

ל-Android Sharesheet יש גם תכונות שימושיות רבות למפתחים. לדוגמה, תוכלו:

שימוש בגיליון לשיתוף ב-Android

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

שליחת תוכן טקסט

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

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}

val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");

Intent shareIntent = Intent.createChooser(sendIntent, null);
startActivity(shareIntent);

אפשר גם להוסיף פרטים נוספים, כמו נמעני האימייל (EXTRA_EMAIL,‏ EXTRA_CC,‏ EXTRA_BCC), נושא האימייל (EXTRA_SUBJECT) וכו'.

הערה: באפליקציות אימייל מסוימות, כמו Gmail, צריך להוסיף את הערך String[] לפרטים נוספים כמו EXTRA_EMAIL ו-EXTRA_CC. משתמשים ב-putExtra(String, String[]) כדי להוסיף אותם לכוונה.

שליחת תוכן בינארי

שיתוף נתונים בינאריים באמצעות הפעולה ACTION_SEND. מגדירים את סוג ה-MIME המתאים ומוסיפים URI לנתונים בשדה הנוסף EXTRA_STREAM, כפי שמתואר בדוגמה הבאה. האפשרות הזו משמשת בדרך כלל לשיתוף תמונה, אבל אפשר להשתמש בה כדי לשתף כל סוג של תוכן בינארי.

Kotlin

val shareIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    // Example: content://com.google.android.apps.photos.contentprovider/...
    putExtra(Intent.EXTRA_STREAM, uriToImage)
    type = "image/jpeg"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
// Example: content://com.google.android.apps.photos.contentprovider/...
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, null));

לאפליקציה המקבלת צריכה להיות הרשאה לגשת לנתונים שאליהם מפנה השדה Uri. יש שתי דרכים מומלצות לעשות זאת:

  • שומרים את הנתונים ב-ContentProvider שלכם, ומוודאים שלאפליקציות אחרות יש את ההרשאה הנכונה לגשת לספק. המנגנון המועדף להענקת גישה הוא שימוש בהרשאות לכל URI, שהן זמניות ומעניקות גישה רק לאפליקציה המקבלת. אפשר ליצור בקלות ContentProvider כמו זה באמצעות כיתה המסייעת FileProvider.
  • משתמשים ב-MediaStore של המערכת. MediaStore מיועד בעיקר לסוגי MIME של וידאו, אודיו ותמונה. עם זאת, החל מגרסה 3.0 של Android‏ (רמת API 11), אפשר לאחסן בה גם סוגי נתונים שאינם מדיה. למידע נוסף: MediaStore.Files אפשר להוסיף קבצים ל-MediaStore באמצעות scanFile(), ואז Uri בסגנון content:// שמתאים לשיתוף מועבר ל-callback של onScanCompleted() שסיפקתם. שימו לב שאחרי הוספת התוכן למערכת MediaStore, התוכן נגיש לכל אפליקציה במכשיר.

שימוש בסוג ה-MIME הנכון

יש לציין את סוג ה-MIME הספציפי ביותר שזמין לנתונים שאתם שולחים. לדוגמה, משתמשים ב-text/plain כשמשתפים טקסט פשוט. ריכזנו כאן כמה סוגי MIME נפוצים לשליחת נתונים פשוטים ב-Android:

מקבלים נרשמים ל- השולחים שולחים
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
`image/*`
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
סיומות קבצים נתמכות application/pdf

מידע נוסף על סוגי MIME זמין במרשם הרשמי של סוגי המדיה ב-MIME ב-IANA.

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

שיתוף כמה קטעי תוכן

כדי לשתף כמה פריטים של תוכן, משתמשים בפעולה ACTION_SEND_MULTIPLE יחד עם רשימה של מזהי URI שמפנים לתוכן. סוג ה-MIME משתנה בהתאם לסוגי התוכן שאתם משתפים. לדוגמה, אם משתפים שלוש תמונות בפורמט JPEG, צריך להשתמש ב-"image/jpg". כדי לשלב בין סוגי תמונות שונים, אפשר להשתמש ב-"image/*" כדי להתאים פעילות שמטפלת בכל סוגי התמונות. למרות שאפשר לשתף שילוב של סוגים, אנחנו לא מתעלמים בזה, כי לא ברור לנמען מה הוא מיועד לשלוח. אם צריך לשלוח כמה סוגים, משתמשים ב-"*/*". האפליקציה המקבלת היא זו שמנתחת ומעבדת את הנתונים. הנה דוגמה:

Kotlin

val imageUris: ArrayList<Uri> = arrayListOf(
        // Add your image URIs here
        imageUri1,
        imageUri2
)

val shareIntent = Intent().apply {
    action = Intent.ACTION_SEND_MULTIPLE
    putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
    type = "image/*"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, null));

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

הוספת תוכן עשיר לתצוגות מקדימות של טקסט

החל מגרסה 10 של Android‏ (רמת API 29), בחלונית השיתוף של Android מוצגת תצוגה מקדימה של הטקסט שרוצים לשתף. במקרים מסוימים, יכול להיות שקשה להבין את הטקסט ששותף. כדאי לשקול לשתף כתובת URL מורכבת כמו https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4. תצוגה מקדימה עשירה יותר יכולה להבטיח למשתמשים מה ישותף.

אם אתם מציגים תצוגה מקדימה של טקסט, אתם יכולים להגדיר שם, תמונה ממוזערת או את שניהם. צריך להוסיף תיאור ל-Intent.EXTRA_TITLE לפני הקריאה ל-Intent.createChooser(), ולהוסיף תמונה ממוזערת רלוונטית באמצעות ClipData.

הערה: ה-URI של תוכן התמונה מסופק מ-FileProvider, בדרך כלל מ-<cache-path> שהוגדר. מידע נוסף זמין במאמר שיתוף קבצים. חשוב לתת ל-Sharesheet את ההרשאות המתאימות לקריאת כל תמונה שרוצים להשתמש בה כתמונה ממוזערת. למידע נוסף: Intent.FLAG_GRANT_READ_URI_PERMISSION

הנה דוגמה:

Kotlin

 val share = Intent.createChooser(Intent().apply {
      action = Intent.ACTION_SEND
      putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

      // (Optional) Here you're setting the title of the content
      putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

      // (Optional) Here you're passing a content URI to an image to be displayed
      data = contentUri
      flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
  }, null)
  startActivity(share)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/");

// (Optional) Here you're setting the title of the content
sendIntent.putExtra(Intent.EXTRA_TITLE, "Introducing content previews");

// (Optional) Here you're passing a content URI to an image to be displayed
sendIntent.setData(contentUri);
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Show the Sharesheet
startActivity(Intent.createChooser(sendIntent, null));

התצוגה המקדימה נראית כך:

הוספת פעולות בהתאמה אישית לחלונית השיתוף

צילום מסך של פעולות מותאמות אישית בדף השיתוף של Android.

ב-Android מגרסה 14 (API ברמה 34) ואילך, אפליקציות יכולות להוסיף פעולות מותאמות אישית לגיליון השיתוף של Android. הפעולות בהתאמה אישית מוצגות כסמלי פעולה קטנים בחלק העליון של חלונית השיתוף ב-Android, והאפליקציות יכולות לציין כל Intent כפעולה שתופעל כשלוחצים על הסמל.

כדי להוסיף פעולות בהתאמה אישית לחלונית השיתוף של Android, קודם צריך ליצור ChooserAction באמצעות ChooserAction.Builder. אפשר לציין את הערך PendingIntent כפעולה שתתבצע כשלוחצים על הסמל. יוצרים מערך שמכיל את כל הפעולות בהתאמה אישית ומציינים אותו בתור EXTRA_CHOOSER_CUSTOM_ACTIONS של השיתוף Intent.

Kotlin

val sendIntent = Intent(Intent.ACTION_SEND)
    .setType("text/plain")
    .putExtra(Intent.EXTRA_TEXT, text)
val shareIntent = Intent.createChooser(sendIntent, null)
val customActions = arrayOf(
    ChooserAction.Builder(
        Icon.createWithResource(context, R.drawable.ic_custom_action),
        "Custom",
        PendingIntent.getBroadcast(
            context,
            1,
            Intent(Intent.ACTION_VIEW),
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
        )
    ).build()
)
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
context.startActivity(shareIntent)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND)
        .setType("text.plain")
        .putExtra(Intent.EXTRA_TEXT, text);
Intent shareIntent = Intent.createChooser(sendIntent, null);
ChooserAction[] actions = new ChooserAction[]{
        new ChooserAction.Builder(
                Icon.createWithResource(context, R.drawable.ic_custom_action),
                "Custom",
                PendingIntent.getBroadcast(
                        context,
                        1,
                        new Intent(Intent.ACTION_VIEW),
                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT
                )
        ).build()
};
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions);
context.startActivity(shareIntent);

הוספת יעדים מותאמים אישית

ב-Android Sharesheet אפשר לציין עד שני אובייקטים מסוג ChooserTarget שיוצגו לפני קיצורי הדרך לשיתוף והיעדים של הבורר שנטענים מ-ChooserTargetServices. אפשר גם לציין עד שתי כוונות שמפניות לפעילויות שמפורטות לפני הצעות האפליקציות:

מוסיפים את Intent.EXTRA_CHOOSER_TARGETS ואת Intent.EXTRA_INITIAL_INTENTS ל-Intent השיתוף אחרי הקריאה Intent.createChooser():

Kotlin

val share = Intent.createChooser(myShareIntent, null).apply {
    putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray)
    putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray)
}

Java

Intent shareIntent = Intent.createChooser(sendIntent, null);
share.putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray);
share.putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray);

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

החרגת יעדים ספציפיים לפי רכיב

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

מוסיפים את Intent.EXTRA_EXCLUDE_COMPONENTS לכוונה אחרי שמפעילים את Intent.createChooser():

Kotlin

  val share = Intent.createChooser(Intent(), null).apply {
    // Only use for components you have control over
    val excludedComponentNames = arrayOf(ComponentName("com.example.android", "ExampleClass"))
    putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
  }

Java

  Intent shareIntent = Intent.createChooser(new Intent(), null);
  // Only use for components you have control over
  ComponentName[] excludedComponentNames = {
          new ComponentName("com.example.android", "ExampleClass")
  };
  shareIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames);

קבלת מידע על שיתוף

כדאי לדעת מתי המשתמשים משתפים ואיזה יעד הם בוחרים. כדי לקבל את המידע הזה, תוכלו להשתמש ב-ComponentName של היעדים שהמשתמשים בוחרים באמצעות IntentSender בחלונית השיתוף של Android.

קודם יוצרים PendingIntent ל-BroadcastReceiver ומספקים את IntentSender שלו ב-Intent.createChooser():

Kotlin

var share = Intent(Intent.ACTION_SEND)
// ...
val pi = PendingIntent.getBroadcast(
    myContext, requestCode,
    Intent(myContext, MyBroadcastReceiver::class.java),
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
share = Intent.createChooser(share, null, pi.intentSender)

Java

Intent share = new Intent(ACTION_SEND);
...
PendingIntent pi = PendingIntent.getBroadcast(myContext, requestCode,
        new Intent(myContext, MyBroadcastReceiver.class),
        PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
share = Intent.createChooser(share, null, pi.getIntentSender());

ממתינים להתקשרות חזרה למספר MyBroadcastReceiver ומעיינים ב-Intent.EXTRA_CHOSEN_COMPONENT:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
  ...
  val clickedComponent : ComponentName = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

Java

@Override public void onReceive(Context context, Intent intent) {
  ...
  ComponentName clickedComponent = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

הוספת פעולות בהתאמה אישית לחלונית השיתוף

ב-Android 14 (רמת API 34) ואילך, אפליקציות יכולות להוסיף פעולות בהתאמה אישית לחלונית השיתוף של Android. יוצרים ChooserAction באמצעות ChooserAction.Builder. אפשר לציין את הערך PendingIntent כפעולה שתתבצע כשלוחצים על הסמל. יוצרים מערך שמכיל את כל הפעולות בהתאמה אישית ומציינים אותו בתור EXTRA_CHOOSER_CUSTOM_ACTIONS של השיתוף Intent.

Kotlin

val sendIntent = Intent(Intent.ACTION_SEND)
    .setType("text/plain")
    .putExtra(Intent.EXTRA_TEXT, text)
val shareIntent = Intent.createChooser(sendIntent, null)
val customActions = arrayOf(
    ChooserAction.Builder(
        Icon.createWithResource(context, R.drawable.ic_custom_action),
        "Custom",
        PendingIntent.getBroadcast(
            context,
            1,
            Intent(Intent.ACTION_VIEW),
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
        )
    ).build()
)
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
context.startActivity(shareIntent)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND)
        .setType("text.plain")
        .putExtra(Intent.EXTRA_TEXT, text);
Intent shareIntent = Intent.createChooser(sendIntent, null);
ChooserAction[] actions = new ChooserAction[]{
        new ChooserAction.Builder(
                Icon.createWithResource(context, R.drawable.ic_custom_action),
                "Custom",
                PendingIntent.getBroadcast(
                        context,
                        1,
                        new Intent(Intent.ACTION_VIEW),
                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT
                )
        ).build()
};
shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions);
context.startActivity(shareIntent);

שימוש בפותר הכוונות של Android

צילום מסך של ACTION_SEND intent resolver.

מומלץ להשתמש בפותר הכוונות של Android כששולחים נתונים לאפליקציה אחרת כחלק מתהליך עבודה מוגדר היטב.

כדי להשתמש בפותר הכוונות של Android, יוצרים כוונה ומוסיפים פריטים נוספים כמו שמוסיפים כדי לקרוא ל-Sharesheet של Android. עם זאת, אין להתקשר למספר Intent.createChooser().

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

דוגמה לשימוש בפתרון הכוונה של Android לשליחת טקסט:

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}
startActivity(sendIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

מידע נוסף

מידע נוסף על שליחת נתונים זמין במאמר כוונות ומסנני כוונות.