בורר התמונות

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

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

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

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

שימוש בחוזים של Jetpack Activity

כדי לפשט את השילוב של כלי בחירת התמונות, צריך לכלול את גרסה 1.7.0 ואילך של ספריית androidx.activity.

כדי להפעיל את כלי בחירת התמונות, משתמשים בחוזים הבאים של תוצאות הפעילות:

אם כלי לבחירת תמונות לא זמין במכשיר, הספרייה מפעילה אוטומטית את פעולת Intent ACTION_OPEN_DOCUMENT במקום זאת. ה-Intent הזה נתמך במכשירים עם Android מגרסה 4.4 (רמת API‏ 19) ואילך. כדי לבדוק אם כלי לבחירת תמונות זמין במכשיר מסוים, צריך להפעיל את isPhotoPickerAvailable().

בחירת קובץ מדיה אחד

כדי לבחור קובץ מדיה יחיד, משתמשים בחוזה PickVisualMedia activity result, כמו שמוצג בקטע הקוד הבא:

צפיות

// Registers a photo picker activity launcher in single-select mode.
val pickMedia = registerForActivityResult(PickVisualMedia()) { uri ->
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: $uri")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

// Launch the photo picker and let the user choose only images.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
val mimeType = "image/gif"
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))

צפיות

// Registers a photo picker activity launcher in single-select mode.
ActivityResultLauncher<PickVisualMediaRequest> pickMedia =
        registerForActivityResult(new PickVisualMedia(), uri -> {
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: " + uri);
    } else {
        Log.d("PhotoPicker", "No media selected");
    }
});

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only images.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageOnly.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.VideoOnly.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
String mimeType = "image/gif";
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(new PickVisualMedia.SingleMimeType(mimeType))
        .build());

כתיבה

// Registers a photo picker activity launcher in single-select mode.
val pickMedia = rememberLauncherForActivityResult(PickVisualMedia()) { uri ->
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: $uri")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

// Launch the photo picker and let the user choose only images.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
val mimeType = "image/gif"
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))

בחירה של כמה פריטי מדיה

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

צפיות

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
val pickMultipleMedia =
        registerForActivityResult(PickMultipleVisualMedia(5)) { uris ->
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (uris.isNotEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: ${uris.size}")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

צפיות

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
ActivityResultLauncher<PickVisualMediaRequest> pickMultipleMedia =
        registerForActivityResult(new PickMultipleVisualMedia(5), uris -> {
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (!uris.isEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: " + uris.size());
    } else {
        Log.d("PhotoPicker", "No media selected");
    }
});

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE)
        .build());

כתיבה

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
val pickMultipleMedia =
        rememberLauncherForActivityResult(PickMultipleVisualMedia(5)) { uris ->
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (uris.isNotEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: ${uris.size}")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

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

זמינות למכשירים

כלי בחירת התמונות זמין במכשירים שעומדים בקריטריונים הבאים:

במכשירים ישנים יותר עם Android בגרסה 4.4 (רמת API‏ 19) עד Android בגרסה 10 (רמת API‏ 29), ובמכשירי Android Go עם Android בגרסה 11 או 12 שתומכים ב-Google Play Services, אפשר להתקין גרסה של כלי לבחירת תמונות שמותאמת לגרסאות קודמות. כדי להפעיל את ההתקנה האוטומטית של מודול כלי לבחירת תמונות שעבר התאמה לאחור דרך Google Play Services, מוסיפים את הרשומה הבאה לתג <application> בקובץ המניפסט של האפליקציה:

<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
         android:enabled="false"
         android:exported="false"
         tools:ignore="MissingClass">
    <intent-filter>
        <action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
    </intent-filter>
    <meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>

שמירת הגישה לקובצי מדיה

כברירת מחדל, המערכת מעניקה לאפליקציה שלכם גישה לקובצי מדיה עד שהמכשיר מופעל מחדש או עד שהאפליקציה מפסיקה לפעול. אם האפליקציה מבצעת עבודה ארוכת טווח, כמו העלאה של קובץ גדול ברקע, יכול להיות שתצטרכו שהגישה הזו תישמר למשך תקופה ארוכה יותר. כדי לעשות את זה, מבצעים קריאה ל-method‏ takePersistableUriPermission():

Kotlin

val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flag)

Java

int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION;
context.contentResolver.takePersistableUriPermission(uri, flag);

טיפול בסרטוני HDR באמצעות המרת קידוד

ב-Android 13 ‏ (API 33) נוספה האפשרות לצלם סרטונים בטווח דינמי גבוה (HDR). טכנולוגיית HDR מציעה חוויה ויזואלית עשירה יותר, אבל יכול להיות שבחלק מהאפליקציות הישנות יותר לא תהיה תמיכה בפורמטים החדשים האלה, ולכן עלולות להיווצר בעיות כמו הצגת צבעים לא טבעית במהלך ההפעלה (למשל, פנים עם גוון ירוק). כדי לגשר על פער התאימות הזה, בכלי לבחירת תמונות יש תכונה של המרת קידוד שיכולה להמיר אוטומטית סרטוני HDR לפורמט של טווח דינמי סטנדרטי (SDR) לפני שהם מועברים לאפליקציה ששלחה את הבקשה.

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

איך פועל תהליך הטרנסקוד של תמונות בכלי לבחירת תמונות

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

האפליקציה מספקת את היכולות שלה לעיבוד מדיה לכלי לבחירת תמונות. הפעולה הזו מתבצעת כשמפעילים את כלי לבחירת תמונות באמצעות ספריית הפעילות של AndroidX על ידי הוספת mediaCapabilities אל PickVisualMediaRequest.Builder. כדי לעשות את זה, הוספנו ל-PickVisualMediaRequest.Builder ממשק API חדש, ‏ setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?).

אפשר לשלוט בהתנהגות של המרת קידוד HDR באמצעות המחלקה MediaCapabilities. מספקים אובייקט MediaCapabilities שמציין בדיוק אילו סוגי HDR האפליקציה תומכת בהם (למשל, ‫TYPE_HLG10, ‏TYPE_HDR10, ‏TYPE_HDR10_PLUS, TYPE_DOLBY_VISION).

כדי להשבית לגמרי את המרת הקידוד, מעבירים את הערך null לפרמטר MediaCapabilities. כל סוג HDR שלא מופיע במפורש ביכולות שציינתם ייחשב כלא נתמך. ה-API הזה נתמך ב-Android 13 (רמת API‏ 33) ומעלה ומסומן ב-@RequiresApi(Build.VERSION_CODES.TIRAMISU).

import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.annotation.RequiresApi
import android.os.Build
import android.util.Log
import android.provider.MediaStore

// Registers a photo picker activity launcher.
val pickMedia = registerForActivityResult(PickVisualMedia()) { uri ->
    // Callback invoked after media selected or picker activity closed.
    if (uri != null) {
        Log.d("photo picker", "Selected URI: $uri")
    } else {
        Log.d("photo picker", "No media selected")
    }
}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun launchPhotoPickerWithTranscodingSupport() {
    val mediaCapabilities = MediaCapabilities.Builder()
        .addSupportedHdrType(MediaCapabilities.HdrType.TYPE_HLG10)
        .build()

    // Launch the photo picker and let the user choose only videos with
    // transcoding enabled.
    pickMedia.launch(PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.VideoOnly)
        .setMediaCapabilitiesForTranscoding(mediaCapabilities)
        .build())
}

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

שיקולים חשובים לגבי המרת קידוד של HDR

  • ביצועים ואחסון: המרת קידוד דורשת זמן עיבוד ויוצרת קובץ חדש, שתופס נפח אחסון.
  • מגבלת אורך הסרטון: כדי לאזן בין חוויית המשתמש לבין מגבלות האחסון, אורך הסרטון מוגבל לדקה אחת.
  • ניהול קבצים במטמון: קבצים שעברו המרה ונשמרו במטמון מפונים באופן תקופתי במהלך תחזוקה במצב לא פעיל, כדי למנוע שימוש מוגזם בנפח אחסון נדרש.
  • זמינות במכשירים: המרת קידוד של תמונות בכלי לבחירת תמונות נתמכת ב-Android 13 (רמת API‏ 33) ואילך.
  • שילוב של פעילות AndroidX: חשוב לוודא שאתם משתמשים בגרסה 1.11.0-alpha01 או בגרסה מאוחרת יותר של אלפא/בטא/RC/יציבה של ספריית הפעילות של AndroidX, כי היא כוללת את setMediaCapabilitiesForTranscoding API הנדרש.