Mengunduh dan menginstal pembaruan paket dari Store

Mulai dari Windows 10, versi 1607, Anda dapat menggunakan metode kelas StoreContext di namespace Windows.Services.Store untuk secara terprogram memeriksa pembaruan paket untuk aplikasi saat ini dari Microsoft Store, dan mengunduh dan menginstal paket yang diperbarui. Anda juga dapat mengkueri paket yang telah Anda tandai sebagai wajib di Pusat Mitra dan menonaktifkan fungsionalitas di aplikasi Anda hingga pembaruan wajib diinstal.

Metode StoreContext tambahan yang diperkenalkan di Windows 10, versi 1803 memungkinkan Anda mengunduh dan menginstal pembaruan paket secara diam-diam (tanpa menampilkan antarmuka pengguna pemberitahuan kepada pengguna), menghapus instalan paket opsional, dan mendapatkan info tentang paket dalam unduhan dan instal antrean untuk aplikasi Anda.

Fitur-fitur ini membantu Anda terus memperbarui basis pengguna secara otomatis dengan versi terbaru aplikasi Anda, paket opsional, dan layanan terkait di Store.

Mengunduh dan menginstal pembaruan paket dengan izin pengguna

Contoh kode ini menunjukkan cara menggunakan metode GetAppAndOptionalStorePackageUpdatesAsync untuk menemukan semua pembaruan paket yang tersedia dari Store lalu memanggil metode RequestDownloadAndInstallStorePackageUpdatesAsync untuk mengunduh dan menginstal pembaruan. Saat menggunakan metode ini untuk mengunduh dan menginstal pembaruan, OS menampilkan dialog yang meminta izin pengguna sebelum mengunduh pembaruan.

Catatan

Metode ini mendukung paket yang diperlukan dan opsional untuk aplikasi Anda. Paket opsional berguna untuk add-on konten yang dapat diunduh (DLC), membandingkan aplikasi besar Anda untuk batasan ukuran, atau untuk mengirim konten tambahan yang terpisah dari aplikasi inti Anda. Untuk mendapatkan izin untuk mengirimkan aplikasi yang menggunakan paket opsional (termasuk add-on DLC) ke Store, lihat Dukungan pengembang Windows.

Contoh kode ini mengasumsikan:

  • Kode berjalan dalam konteks Halaman.
  • Halaman berisi Bilah Kemajuan bernama downloadProgressBar untuk memberikan status untuk operasi pengunduhan.
  • File kode memiliki pernyataan penggunaan untuk namespace layanan Windows.Services.Store, Windows.Threading.Tasks, dan Windows.UI.Popups .
  • Aplikasi ini adalah aplikasi pengguna tunggal yang hanya berjalan dalam konteks pengguna yang meluncurkan aplikasi. Untuk aplikasi multi-pengguna, gunakan metode GetForUser untuk mendapatkan objek StoreContext alih-alih metode GetDefault.
private StoreContext context = null;

public async Task DownloadAndInstallAllUpdatesAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> updates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (updates.Count > 0)
    {
        // Alert the user that updates are available and ask for their consent
        // to start the updates.
        MessageDialog dialog = new MessageDialog(
            "Download and install updates now? This may cause the application to exit.", "Download and Install?");
        dialog.Commands.Add(new UICommand("Yes"));
        dialog.Commands.Add(new UICommand("No"));
        IUICommand command = await dialog.ShowAsync();

        if (command.Label.Equals("Yes", StringComparison.CurrentCultureIgnoreCase))
        {
            // Download and install the updates.
            IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> downloadOperation =
                context.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);

            // The Progress async method is called one time for each step in the download
            // and installation process for each package in this request.
            downloadOperation.Progress = async (asyncInfo, progress) =>
            {
                await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                () =>
                {
                    downloadProgressBar.Value = progress.PackageDownloadProgress;
                });
            };

            StorePackageUpdateResult result = await downloadOperation.AsTask();
        }
    }
}

Catatan

Untuk hanya mengunduh (tetapi tidak menginstal) pembaruan paket yang tersedia, gunakan metode RequestDownloadStorePackageUpdatesAsync .

Menampilkan info kemajuan pengunduhan dan penginstalan

Saat Anda memanggil metode RequestDownloadStorePackageUpdatesAsync atau RequestDownloadAndInstallStorePackageUpdatesAsync , Anda dapat menetapkan handler Kemajuan yang dipanggil satu kali untuk setiap langkah dalam proses unduhan (atau unduh dan instal) untuk setiap paket dalam permintaan ini. Handler menerima objek StorePackageUpdateStatus yang menyediakan info tentang paket pembaruan yang menaikkan pemberitahuan kemajuan. Contoh sebelumnya menggunakan bidang PackageDownloadProgress dari objek StorePackageUpdateStatus untuk menampilkan kemajuan proses pengunduhan dan penginstalan.

Ketahuilah bahwa ketika Anda memanggil RequestDownloadAndInstallStorePackageUpdatesAsync untuk mengunduh dan menginstal pembaruan paket dalam satu operasi, bidang PackageDownloadProgress meningkat dari 0,0 menjadi 0,8 selama proses pengunduhan untuk paket, dan kemudian meningkat dari 0,8 menjadi 1,0 selama penginstalan. Oleh karena itu, jika Anda memetakan persentase yang ditampilkan di UI kemajuan kustom Anda langsung ke nilai bidang PackageDownloadProgress , UI Anda akan menunjukkan 80% ketika paket selesai diunduh dan OS menampilkan dialog penginstalan. Jika Anda ingin UI kemajuan kustom Anda menampilkan 100% saat paket diunduh dan siap diinstal, Anda dapat memodifikasi kode Anda untuk menetapkan 100% ke antarmuka pengguna kemajuan Anda ketika bidang PackageDownloadProgress mencapai 0,8.

Mengunduh dan menginstal pembaruan paket secara diam-diam

Mulai dari Windows 10, versi 1803, Anda dapat menggunakan metode TrySilentDownloadStorePackageUpdatesAsync dan TrySilentDownloadAndInstallStorePackageUpdatesAsync untuk mengunduh dan menginstal pembaruan paket secara diam-diam, tanpa menampilkan UI pemberitahuan kepada pengguna. Operasi ini akan berhasil hanya jika pengguna telah mengaktifkan pengaturan Perbarui aplikasi secara otomatis di Bursa dan pengguna tidak berada di jaringan terukur. Sebelum memanggil metode ini, Anda dapat terlebih dahulu memeriksa properti CanSilentlyDownloadStorePackageUpdates untuk menentukan apakah kondisi ini saat ini terpenuhi.

Contoh kode ini menunjukkan cara menggunakan metode GetAppAndOptionalStorePackageUpdatesAsync untuk menemukan semua pembaruan paket yang tersedia lalu memanggil metode TrySilentDownloadStorePackageUpdatesAsync dan TrySilentDownloadAndInstallStorePackageUpdatesAsync untuk mengunduh dan menginstal pembaruan secara diam-diam.

Contoh kode ini mengasumsikan:

  • File kode memiliki pernyataan penggunaan untuk namespace Windows.Services.Store dan System.Threading.Tasks .
  • Aplikasi ini adalah aplikasi pengguna tunggal yang hanya berjalan dalam konteks pengguna yang meluncurkan aplikasi. Untuk aplikasi multi-pengguna, gunakan metode GetForUser untuk mendapatkan objek StoreContext alih-alih metode GetDefault.

Catatan

Metode IsNowAGoodTimeToRestartApp, RetryDownloadAndInstallLater, dan RetryInstallLater yang disebut oleh kode dalam contoh ini adalah metode tempat penampung yang dimaksudkan untuk diimplementasikan sesuai kebutuhan sesuai dengan desain aplikasi Anda sendiri.

private StoreContext context = null;

public async Task DownloadAndInstallAllUpdatesInBackgroundAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> storePackageUpdates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (storePackageUpdates.Count > 0)
    {

        if (!context.CanSilentlyDownloadStorePackageUpdates)
        {
            return;
        }

        // Start the silent downloads and wait for the downloads to complete.
        StorePackageUpdateResult downloadResult =
            await context.TrySilentDownloadStorePackageUpdatesAsync(storePackageUpdates);

        switch (downloadResult.OverallState)
        {
            case StorePackageUpdateState.Completed:
                // The download has completed successfully. At this point, confirm whether your app
                // can restart now and then install the updates (for example, you might only install
                // packages silently if your app has been idle for a certain period of time). The
                // IsNowAGoodTimeToRestartApp method is not implemented in this example, you should
                // implement it as needed for your own app.
                if (IsNowAGoodTimeToRestartApp())
                {
                    await InstallUpdate(storePackageUpdates);
                }
                else
                {
                    // Retry/reschedule the installation later. The RetryInstallLater method is not  
                    // implemented in this example, you should implement it as needed for your own app.
                    RetryInstallLater();
                    return;
                }
                break;
            // If the user cancelled the download or you can't perform the download for some other
            // reason (for example, Wi-Fi might have been turned off and the device is now on
            // a metered network) try again later. The RetryDownloadAndInstallLater method is not  
            // implemented in this example, you should implement it as needed for your own app.
            case StorePackageUpdateState.Canceled:
            case StorePackageUpdateState.ErrorLowBattery:
            case StorePackageUpdateState.ErrorWiFiRecommended:
            case StorePackageUpdateState.ErrorWiFiRequired:
            case StorePackageUpdateState.OtherError:
                RetryDownloadAndInstallLater();
                return;
            default:
                break;
        }
    }
}

private async Task InstallUpdate(IReadOnlyList<StorePackageUpdate> storePackageUpdates)
{
    // Start the silent installation of the packages. Because the packages have already
    // been downloaded in the previous method, the following line of code just installs
    // the downloaded packages.
    StorePackageUpdateResult downloadResult =
        await context.TrySilentDownloadAndInstallStorePackageUpdatesAsync(storePackageUpdates);

    switch (downloadResult.OverallState)
    {
        // If the user cancelled the installation or you can't perform the installation  
        // for some other reason, try again later. The RetryInstallLater method is not  
        // implemented in this example, you should implement it as needed for your own app.
        case StorePackageUpdateState.Canceled:
        case StorePackageUpdateState.ErrorLowBattery:
        case StorePackageUpdateState.OtherError:
            RetryInstallLater();
            return;
        default:
            break;
    }
}

Pembaruan paket wajib

Saat Anda membuat pengiriman paket di Pusat Mitra untuk aplikasi yang menargetkan Windows 10, versi 1607 atau yang lebih baru, Anda dapat menandai paket sebagai wajib dan tanggal dan waktu di mana paket tersebut menjadi wajib. Saat properti ini diatur dan aplikasi Anda menemukan bahwa pembaruan paket tersedia, aplikasi Anda dapat menentukan apakah paket pembaruan wajib dan mengubah perilakunya hingga pembaruan diinstal (misalnya, aplikasi Anda dapat menonaktifkan fitur).

Catatan

Status wajib pembaruan paket tidak diberlakukan oleh Microsoft, dan OS tidak menyediakan UI untuk menunjukkan kepada pengguna bahwa pembaruan aplikasi wajib harus diinstal. Pengembang dimaksudkan untuk menggunakan pengaturan wajib untuk memberlakukan pembaruan aplikasi wajib dalam kode mereka sendiri.

Untuk menandai pengiriman paket sebagai wajib:

  1. Masuk ke Pusat Mitra dan buka halaman gambaran umum untuk aplikasi Anda.
  2. Klik nama pengiriman yang berisi pembaruan paket yang ingin Anda jadikan wajib.
  3. Navigasi ke halaman Paket untuk pengiriman. Di dekat bagian bawah halaman ini, pilih Jadikan pembaruan ini wajib lalu pilih hari dan waktu di mana pembaruan paket menjadi wajib. Opsi ini berlaku untuk semua paket UWP dalam pengiriman.

Untuk informasi selengkapnya, lihat Mengunggah paket aplikasi.

Catatan

Jika Anda membuat penerbangan paket, Anda dapat menandai paket sebagai wajib menggunakan UI serupa di halaman Paket untuk penerbangan. Dalam hal ini, pembaruan paket wajib hanya berlaku untuk pelanggan yang merupakan bagian dari grup penerbangan.

Contoh kode untuk paket wajib

Contoh kode berikut menunjukkan cara menentukan apakah ada paket pembaruan yang wajib. Biasanya, Anda harus menurunkan tingkat pengalaman aplikasi Anda dengan baik untuk pengguna jika pembaruan paket wajib tidak berhasil diunduh atau diinstal.

private StoreContext context = null;

// Downloads and installs package updates in separate steps.
public async Task DownloadAndInstallAllUpdatesAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }  

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> updates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (updates.Count != 0)
    {
        // Download the packages.
        bool downloaded = await DownloadPackageUpdatesAsync(updates);

        if (downloaded)
        {
            // Install the packages.
            await InstallPackageUpdatesAsync(updates);
        }
    }
}

// Helper method for downloading package updates.
private async Task<bool> DownloadPackageUpdatesAsync(IEnumerable<StorePackageUpdate> updates)
{
    bool downloadedSuccessfully = false;

    IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> downloadOperation =
        this.context.RequestDownloadStorePackageUpdatesAsync(updates);

    // The Progress async method is called one time for each step in the download process for each
    // package in this request.
    downloadOperation.Progress = async (asyncInfo, progress) =>
    {
        await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () =>
        {
            downloadProgressBar.Value = progress.PackageDownloadProgress;
        });
    };

    StorePackageUpdateResult result = await downloadOperation.AsTask();

    switch (result.OverallState)
    {
        case StorePackageUpdateState.Completed:
            downloadedSuccessfully = true;
            break;
        default:
            // Get the failed updates.
            var failedUpdates = result.StorePackageUpdateStatuses.Where(
                status => status.PackageUpdateState != StorePackageUpdateState.Completed);

            // See if any failed updates were mandatory
            if (updates.Any(u => u.Mandatory && failedUpdates.Any(
                failed => failed.PackageFamilyName == u.Package.Id.FamilyName)))
            {
                // At least one of the updates is mandatory. Perform whatever actions you
                // want to take for your app: for example, notify the user and disable
                // features in your app.
                HandleMandatoryPackageError();
            }
            break;
    }

    return downloadedSuccessfully;
}

// Helper method for installing package updates.
private async Task InstallPackageUpdatesAsync(IEnumerable<StorePackageUpdate> updates)
{
    IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> installOperation =
        this.context.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);

    // The package updates were already downloaded separately, so this method skips the download
    // operatation and only installs the updates; no download progress notifications are provided.
    StorePackageUpdateResult result = await installOperation.AsTask();

    switch (result.OverallState)
    {
        case StorePackageUpdateState.Completed:
            break;
        default:
            // Get the failed updates.
            var failedUpdates = result.StorePackageUpdateStatuses.Where(
                status => status.PackageUpdateState != StorePackageUpdateState.Completed);

            // See if any failed updates were mandatory
            if (updates.Any(u => u.Mandatory && failedUpdates.Any(failed => failed.PackageFamilyName == u.Package.Id.FamilyName)))
            {
                // At least one of the updates is mandatory, so tell the user.
                HandleMandatoryPackageError();
            }
            break;
    }
}

// Helper method for handling the scenario where a mandatory package update fails to
// download or install. Add code to this method to perform whatever actions you want
// to take, such as notifying the user and disabling features in your app.
private void HandleMandatoryPackageError()
{
}

Menghapus instalan paket opsional

Mulai dari Windows 10, versi 1803, Anda dapat menggunakan metode RequestUninstallStorePackageAsync atau RequestUninstallStorePackageByStoreIdAsync untuk menghapus instalan paket opsional (termasuk paket DLC) untuk aplikasi saat ini. Misalnya, jika Anda memiliki aplikasi dengan konten yang diinstal melalui paket opsional, Anda mungkin ingin menyediakan UI yang memungkinkan pengguna menghapus instalan paket opsional untuk mengosongkan ruang disk.

Contoh kode berikut menunjukkan cara memanggil RequestUninstallStorePackageAsync. Contoh ini mengasumsikan:

  • File kode memiliki pernyataan penggunaan untuk namespace Windows.Services.Store dan System.Threading.Tasks .
  • Aplikasi ini adalah aplikasi pengguna tunggal yang hanya berjalan dalam konteks pengguna yang meluncurkan aplikasi. Untuk aplikasi multi-pengguna, gunakan metode GetForUser untuk mendapatkan objek StoreContext alih-alih metode GetDefault.
public async Task UninstallPackage(Windows.ApplicationModel.Package package)
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    var storeContext = StoreContext.GetDefault();
    IAsyncOperation<StoreUninstallStorePackageResult> uninstallOperation =
        storeContext.RequestUninstallStorePackageAsync(package);

    // At this point, you can update your app UI to show that the package
    // is installing.

    uninstallOperation.Completed += (asyncInfo, status) =>
    {
        StoreUninstallStorePackageResult result = uninstallOperation.GetResults();
        switch (result.Status)
        {
            case StoreUninstallStorePackageStatus.Succeeded:
                {
                    // Update your app UI to show the package as uninstalled.
                    break;
                }
            default:
                {
                    // Update your app UI to show that the package uninstall failed.
                    break;
                }
        }
    };
}

Dapatkan info antrean unduhan

Mulai windows 10, versi 1803, Anda dapat menggunakan metode GetAssociatedStoreQueueItemsAsync dan GetStoreQueueItemsAsync untuk mendapatkan info tentang paket yang ada dalam antrean pengunduhan dan penginstalan saat ini dari Store. Metode ini berguna jika aplikasi atau game Anda mendukung paket opsional besar (termasuk DLC) yang dapat memakan waktu berjam-jam atau berjam-hari untuk diunduh dan diinstal, dan Anda ingin menangani kasus di mana pelanggan menutup aplikasi atau game Anda sebelum proses pengunduhan dan penginstalan selesai. Ketika pelanggan memulai aplikasi atau game Anda lagi, kode Anda dapat menggunakan metode ini untuk mendapatkan info tentang status paket yang masih dalam antrean pengunduhan dan penginstalan sehingga Anda dapat menampilkan status setiap paket kepada pelanggan.

Contoh kode berikut menunjukkan cara memanggil GetAssociatedStoreQueueItemsAsync untuk mendapatkan daftar pembaruan paket yang sedang berlangsung untuk aplikasi saat ini dan mengambil info status untuk setiap paket. Contoh ini mengasumsikan:

  • File kode memiliki pernyataan penggunaan untuk namespace Windows.Services.Store dan System.Threading.Tasks .
  • Aplikasi ini adalah aplikasi pengguna tunggal yang hanya berjalan dalam konteks pengguna yang meluncurkan aplikasi. Untuk aplikasi multi-pengguna, gunakan metode GetForUser untuk mendapatkan objek StoreContext alih-alih metode GetDefault.

Catatan

Metode MarkUpdateInProgressInUI, RemoveItemFromUI, MarkInstallCompleteInUI, MarkInstallErrorInUI, dan MarkInstallPausedInUI yang dipanggil oleh kode dalam contoh ini adalah metode tempat penampung yang dimaksudkan untuk diimplementasikan sesuai kebutuhan sesuai dengan desain aplikasi Anda sendiri.

private StoreContext context = null;

private async Task GetQueuedInstallItemsAndBuildInitialStoreUI()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the Store packages in the install queue.
    IReadOnlyList<StoreQueueItem> storeUpdateItems = await context.GetAssociatedStoreQueueItemsAsync();

    foreach (StoreQueueItem storeItem in storeUpdateItems)
    {
        // In this example we only care about package updates.
        if (storeItem.InstallKind != StoreQueueItemKind.Update)
            continue;

        StoreQueueItemStatus currentStatus = storeItem.GetCurrentStatus();
        StoreQueueItemState installState = currentStatus.PackageInstallState;
        StoreQueueItemExtendedState extendedInstallState =
            currentStatus.PackageInstallExtendedState;

        // Handle the StatusChanged event to display current status to the customer.
        storeItem.StatusChanged += StoreItem_StatusChanged;

        switch (installState)
        {
            // Download and install are still in progress, so update the status for this  
            // item and provide the extended state info. The following methods are not
            // implemented in this example; you should implement them as needed for your
            // app's UI.
            case StoreQueueItemState.Active:
                MarkUpdateInProgressInUI(storeItem, extendedInstallState);
                break;
            case StoreQueueItemState.Canceled:
                RemoveItemFromUI(storeItem);
                break;
            case StoreQueueItemState.Completed:
                MarkInstallCompleteInUI(storeItem);
                break;
            case StoreQueueItemState.Error:
                MarkInstallErrorInUI(storeItem);
                break;
            case StoreQueueItemState.Paused:
                MarkInstallPausedInUI(storeItem, installState, extendedInstallState);
                break;
        }
    }
}

private void StoreItem_StatusChanged(StoreQueueItem sender, object args)
{
    StoreQueueItemStatus currentStatus = sender.GetCurrentStatus();
    StoreQueueItemState installState = currentStatus.PackageInstallState;
    StoreQueueItemExtendedState extendedInstallState = currentStatus.PackageInstallExtendedState;

    switch (installState)
    {
        // Download and install are still in progress, so update the status for this  
        // item and provide the extended state info. The following methods are not
        // implemented in this example; you should implement them as needed for your
        // app's UI.
        case StoreQueueItemState.Active:
            MarkUpdateInProgressInUI(sender, extendedInstallState);
            break;
        case StoreQueueItemState.Canceled:
            RemoveItemFromUI(sender);
            break;
        case StoreQueueItemState.Completed:
            MarkInstallCompleteInUI(sender);
            break;
        case StoreQueueItemState.Error:
            MarkInstallErrorInUI(sender);
            break;
        case StoreQueueItemState.Paused:
            MarkInstallPausedInUI(sender, installState, extendedInstallState);
            break;
    }
}