גישה למערכי נתונים משותפים

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

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

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

  • כדי להעניק גישה לקבוצה ספציפית של אפליקציות במכשיר, מעבירים את שמות החבילות של האפליקציות האלה אל allowPackageAccess().
  • כדי לאפשר רק לאפליקציות שהאישורים שלהן חתומים באמצעות אותו מפתח שבו נעשה שימוש באפליקציה שלכם – כמו חבילת אפליקציות שאתם מנהלים – צריך להתקשר אל allowSameSignatureAccess().
  • כדי להעניק גישה לכל האפליקציות במכשיר, קוראים ל-allowPublicAccess().

גישה ל-blob של נתונים משותפים

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

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

השלב הבא תלוי בשאלה אם הנתונים זמינים.

מערך נתונים זמין

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

Kotlin

val blobStoreManager =
        getSystemService(Context.BLOB_STORE_SERVICE) as BlobStoreManager
// The label "Sample photos" is visible to the user.
val blobHandle = BlobHandle.createWithSha256(sha256DigestBytes,
        "Sample photos",
        System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1),
        "photoTrainingDataset")
try {
    val input = ParcelFileDescriptor.AutoCloseInputStream(
            blobStoreManager.openBlob(blobHandle))
    useDataset(input)
}

Java

BlobStoreManager blobStoreManager =
        ((BlobStoreManager) getSystemService(Context.BLOB_STORE_SERVICE));
if (blobStoreManager != null) {
    // The label "Sample photos" is visible to the user.
    BlobHandle blobHandle = BlobHandle.createWithSha256(
            sha256DigestBytes,
            "Sample photos",
            System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1),
            "photoTrainingDataset");
    try (InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(
            blobStoreManager.openBlob(blobHandle))) {
        useDataset(input);
    }
}

מערך הנתונים לא זמין

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

Kotlin

val sessionId = blobStoreManager.createSession(blobHandle)
try {
    val session = blobStoreManager.openSession(sessionId)
    try {
        // For this example, write 200 MiB at the beginning of the file.
        val output = ParcelFileDescriptor.AutoCloseOutputStream(
                session.openWrite(0, 1024 * 1024 * 200))
        writeDataset(output)

        session.apply {
            allowSameSignatureAccess()
            allowPackageAccess(your-app-package,
                    app-certificate)
            allowPackageAccess(some-other-app-package,
                    app-certificate)
            commit(mainExecutor, callback)
        }
    }
}

Java

long sessionId = blobStoreManager.createSession(blobHandle);
try (BlobStoreManager.Session session =
        blobStoreManager.openSession(sessionId)) {
    // For this example, write 200 MiB at the beginning of the file.
    try (OutputStream output = new ParcelFileDescriptor.AutoCloseOutputStream(
            session.openWrite(0, 1024 * 1024 * 200)))
        writeDataset(output);
        session.allowSameSignatureAccess();
        session.allowPackageAccess(your-app-package,
                    app-certificate);
        session.allowPackageAccess(some-other-app-package,
                    app-certificate);
        session.commit(getMainExecutor(), callback);
    }
}