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

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

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

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

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

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

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

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

ל-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);

מידע נוסף

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