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

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

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

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

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

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

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

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

בנוסף, יש בקובץ לשיתוף ב-Android הרבה תכונות שימושיות למפתחים. לדוגמה, אתם יכולים:

שימוש בקובץ לשיתוף ב-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 של סרטונים, אודיו ותמונות. עם זאת, החל מ-Android 3.0 (רמת 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 שסופקו מפנים לנתונים שאפליקציה מקבלת יכולה לגשת אליהם.

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

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

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

הערה: ה-URI של תוכן התמונה מסופק מ-FileProvider, בדרך כלל מ-<cache-path> מוגדר. מידע נוסף זמין במאמר בנושא שיתוף קבצים. חשוב לוודא שהקובץ לשיתוף קיבל את ההרשאות המתאימות כדי לקרוא כל תמונה שרוצים להשתמש בה כתמונה ממוזערת. מידע נוסף זמין ב-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 אפשר לציין עד שני אובייקטים של 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);

מידע על שיתוף

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

קודם יוצרים 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_CHOOSER_RESULT:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
  ...
  val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra(
      intent,
      Intent.EXTRA_CHOOSER_RESULT,
      ChooserResult::class.java,
  )
  chooserResult?.let {
      Log.i(
          TAG,
          "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}",
      )
  } ?: Log.i(TAG, "chooserResult is null")
}

Java

@Override public void onReceive(Context context, Intent intent) {
  ...
  ChooserResult chooserResult = intent.getParcelableExtra(EXTRA_CHOOSER_RESULT); 
  Log.i(
      TAG,
      "Share callback: isShortcut: "
          + chooserResult.isShortcut()
          + ", type: "
          + chooserResult.getType()
          + ", componentName: "
          + chooserResult.getSelectedComponent()
  );
}
מידע נוסף זמין בקטע בנושא דוגמה לשיתוף בפלטפורמה:

הוספת פעולות מותאמות אישית לקובץ לשיתוף

ב-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.

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

כדי להשתמש במקודד הכוונות של Android, יוצרים כוונה עם תוספות כמו בהפעלה של קובץ לשיתוף ב-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);

מידע נוסף

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