ייבוא וייצוא של נתונים במסך הבית

נתוני מסך הבית של Android מסופקים על ידי המחלקה LauncherProvider, שהיא הרחבה של ContentProvider, ומאפשרת ייבוא וייצוא של נתוני סביבת העבודה של מפעיל האפליקציות באמצעות XML.

איך יוצרים קשר עם ספק התוכן

כדי לקיים אינטראקציה עם המחלקה LaunchProvider, שהיא הרחבה של ContentProvider, משתמשים בשיטה call:

class LauncherProvider : ContentProvider {
    public Bundle call(String method, String arg, Bundle extras);
}

הפעלת המחלקה LaunchProvider

כדי להפעיל את המחלקה LauncherProvider מהאפליקציה, משתמשים בקוד הבא:

class YourClass {

    /**
     * This method imports Launcher workspace data as a XML string. Calling this method clears the old
     * data model within Launcher and replaces it with the imported data. It should be noted
     * that it doesn't need to clear all the Launcher's data, just what is similar to what is being imported.
     */
    fun importLauncherData(xmlRepresentation: String, ctx: Context): Boolean {
        val uri = try {
            getLauncherProviderUri(ctx)
        } catch (e: IllegalStateException) {
            Log.e(TAG, "Failed to get launcher provider URI", e)
            return false
        }
        val bundle = ctx.contentResolver.call(
            uri,
            LauncherProviderConstants.METHOD_IMPORT_LAYOUT_XML,
            xmlRepresentation,
            null,
        )
        return LauncherProviderConstants.SUCCESS
            .equals(bundle.getBoolean(LauncherProviderConstants.KEY_RESULT))
    }

    /**
     * Use this function to retrieve an XML string representation of the Launcher's Workspace.
     * This method doesn't return what the user sees on their home screen,
     * but rather what is in their data model at the moment it's called.
     */
    fun exportLauncherData(xmlRepresentation: String, ctx: Context): String {
        val uri = try {
            getLauncherProviderUri(ctx)
        } catch (e: IllegalStateException) {
            Log.e(TAG, "Failed to get launcher provider URI", e)
            return ""
        }
        val bundle = ctx.contentResolver.call(
            uri,
            LauncherProviderConstants.METHOD_EXPORT_LAYOUT_XML,
            null,
            null,
        )
        if (LauncherProviderConstants.FAILURE
            .equals(bundle.getBoolean(LauncherProviderConstants.KEY_RESULT))) {
            Log.e(TAG, "failed to export launcher data; review previous logs for the cause.")
        }
        return bundle.getString(LauncherProviderConstants.KEY_LAYOUT, "")
    }

    /**
     * Returns a Uri for interacting with Launcher's ContentProvider.
     *
     * Not all Launchers implement this api. This method throws an IllegalStateException
     * if the Launcher doesn't support it.
     */
    private fun getLauncherProviderUri(ctx: Context): Uri {
        val homeIntent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
        val launcherPackage: String =
            ctx.packageManager
                .resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY)
                ?.activityInfo
                ?.packageName ?: throw IllegalStateException("No launcher package found")
        val authority = "${launcherPackage}.settings"
        ctx.packageManager.resolveContentProvider(authority, 0)
            ?: throw IllegalStateException(
                "Launcher package '$launcherPackage' does not support LauncherProvider",
            )
        return "content://$authority".toUri()
    }
}

פרמטרים

הקבועים האלה נמצאים בשימוש בשיטת הקריאה:

object LauncherProviderConstants {

    // Valid arg parameters for export and import operations
    private static final String METHOD_EXPORT_LAYOUT_XML = "EXPORT_LAYOUT_XML";
    private static final String METHOD_IMPORT_LAYOUT_XML = "IMPORT_LAYOUT_XML";

    // Bundle key and value set for determining if operation completed successfully or not
    private static final String KEY_RESULT = "KEY_RESULT";
    private static final String SUCCESS = "success";
    private static final String FAILURE = "failure";

    // Bundle key used to store exported XML-string representation of Launcher's workspace layout
    // and item metadata
    private static final String KEY_LAYOUT = "KEY_LAYOUT";
}

משתמשים בקבועי LauncherProvider עם ההגבלות הבאות:

  • משתמשים ב-contentResolver.call method עם EXPORT_LAYOUT_XML כפרמטר של השיטה כדי לייצא ייצוג XML של סביבת העבודה של מרכז האפליקציות.
  • במהלך הייצוא, אפשר לגשת לייצוג ה-XML בחבילה שמוחזרת באמצעות המפתח KEY_LAYOUT.
  • משתמשים ב-contentResolver.call method עם IMPORT_LAYOUT_XML כפרמטר של השיטה כדי לייבא ייצוג XML של סביבת העבודה של מרכז האפליקציות.
  • במהלך הייבוא, ייצוג ה-XML מסופק כפרמטר arg של שיטת הקריאה.
  • גם בקריאות ל-API של ייצוא וגם בקריאות ל-API של ייבוא, אם הפעולה שנבחרה הושלמה בהצלחה מוחזרת התוצאה success, ואם הפעולה הופסקה או נכשלה מוחזרת התוצאה failure.
  • אפשר לאחזר את הערך success או failure בחבילה שמוחזרת באמצעות המפתח KEY_RESULT.

דוגמה מופיעה במאמר בנושא הפעלת המחלקה LaunchProvider.

ייצוג ב-XML

המדריכים הבאים מתייחסים למבנה XML במהלך ייבוא וייצוא.

  • אפליקציית Workspace:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace rows="4" columns="5">
      <autoinstall container="desktop" x="1" y="1" screen="0" className="com.android.launcher3.tests.Activity2" packageName="com.google.android.apps.nexuslauncher" />
    </workspace>
    
  • אפליקציית Hotseat:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace>
      <autoinstall container="hotseat" rank="0" className="com.android.launcher3.tests.Activity2" packageName="com.google.android.apps.nexuslauncher" />
    </workspace>
    
  • ווידג'ט:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace>
      <appwidget container="desktop" spanX="2" spanY="2" x="0" y="1" screen="0" className="PlaceholderWidget" packageName="com.test.pending" />
    </workspace>
    
  • תיקייה:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace>
      <folder container="desktop" x="1" y="1" screen="1" titleText="CustomFolder">
        <autoinstall className="com.android.launcher3.tests.Activity1" packageName="com.google.android.apps.nexuslauncher" />
        <autoinstall className="com.android.launcher3.tests.Activity2" packageName="com.google.android.apps.nexuslauncher" />
        <autoinstall className="com.android.launcher3.tests.Activity3" packageName="com.google.android.apps.nexuslauncher" />
      </folder>
    </workspace>
    
  • קיצור דרך עמוק:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace>
      <shortcut shortcutId="shortcut2" packageName="com.google.android.apps.nexuslauncher.tests" />
    </workspace>
    
  • צמד אפליקציות:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <workspace>
      <apppair container="desktop" x="1" y="1" screen="1" titleText="CustomFolder">
        <autoinstall className="com.android.launcher3.tests.Activity1" packageName="com.google.android.apps.nexuslauncher" />
        <autoinstall className="com.android.launcher3.tests.Activity2" packageName="com.google.android.apps.nexuslauncher" />
      </apppair>
    </workspace>
    

הנחות התנהגותיות

אלה ההנחות ההתנהגותיות לגבי המחלקה LaunchProvider.

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