Uygulama içi güncellemeleri destekleme (Yerel)

Bu kılavuzda, yerel kod (C veya C++) kullanarak uygulamanızda uygulama güncellemelerini nasıl destekleyeceğiniz açıklanmaktadır. Uygulamanızda Kotlin programlama dili veya Java programlama dili kullanıldığı durumlar ve uygulamanızda Unity ya da Unreal Engine kullanıldığı durumlar için ayrı kılavuzlar vardır.

Yerel SDK'ya genel bakış

Play Core Yerel SDK'sı, Play Core SDK ailesinin bir parçasıdır. Yerel SDK, Java Play Uygulama İçi Güncelleme Kitaplığı'ndaki AppUpdateManager öğesini sarmalayan bir C üstbilgi dosyası (app_update.h) içerir. Bu üst dosya, uygulamanızın doğrudan yerel kodunuzdan uygulama güncellemeleri için API'yi çağırmasına olanak tanır.

Geliştirme ortamınızı ayarlama

İndir Play Core Native SDK

İndirmeden önce aşağıdaki hüküm ve koşulları kabul etmeniz gerekir.

Hükümler ve Koşullar

Last modified: September 24, 2020
  1. By using the Play Core Software Development Kit, you agree to these terms in addition to the Google APIs Terms of Service ("API ToS"). If these terms are ever in conflict, these terms will take precedence over the API ToS. Please read these terms and the API ToS carefully.
  2. For purposes of these terms, "APIs" means Google's APIs, other developer services, and associated software, including any Redistributable Code.
  3. “Redistributable Code” means Google-provided object code or header files that call the APIs.
  4. Subject to these terms and the terms of the API ToS, you may copy and distribute Redistributable Code solely for inclusion as part of your API Client. Google and its licensors own all right, title and interest, including any and all intellectual property and other proprietary rights, in and to Redistributable Code. You will not modify, translate, or create derivative works of Redistributable Code.
  5. Google may make changes to these terms at any time with notice and the opportunity to decline further use of the Play Core Software Development Kit. Google will post notice of modifications to the terms at https://developer.android.com/guide/playcore/license. Changes will not be retroactive.
Play Core Native SDK indirin

play-core-native-sdk-1.16.0.zip

  1. Aşağıdakilerden birini yapın:

    • Android Studio'nun 4.0 veya daha yeni bir sürümünü yükleyin. Android SDK Platformu 10.0 sürümünü (API düzeyi 29) yüklemek için SDK Manager kullanıcı arayüzünü kullanın.
    • Android SDK komut satırı araçlarını yükleyin ve Android SDK Platformu 10.0 sürümünü (API düzeyi 29) yüklemek için sdkmanager aracını kullanın.
  2. En yeni CMake ve Android Native Development Kit'i (NDK) yüklemek için SDK Manager'ı kullanarak Android Studio'yu yerel geliştirme için hazırlayın. Yerel projeler oluşturma veya içe aktarma hakkında daha fazla bilgi için NDK'yi Kullanmaya Başlama başlıklı makaleyi inceleyin.

  3. ZIP dosyasını indirin ve projenizle birlikte ayıklayın.

    İndirme Bağlantısı Boyut SHA-256 denetim toplamı
    54,8 MiB 008b8fedc6179a6dc6ccc21af75591afc7036f78f3d5559d844f1b923934fef0
  4. Uygulamanızın build.gradle dosyasını aşağıda gösterildiği gibi güncelleyin:

    Modern

        // App build.gradle
    
        plugins {
          id 'com.android.application'
        }
    
        // Define a path to the extracted Play Core SDK files.
        // If using a relative path, wrap it with file() since CMake requires absolute paths.
        def playcoreDir = file('../path/to/playcore-native-sdk')
    
        android {
            defaultConfig {
                ...
                externalNativeBuild {
                    cmake {
                        // Define the PLAYCORE_LOCATION directive.
                        arguments "-DANDROID_STL=c++_static",
                                  "-DPLAYCORE_LOCATION=$playcoreDir"
                    }
                }
                ndk {
                    // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                    abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                }
            }
            buildTypes {
                release {
                    // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                    proguardFile '$playcoreDir/proguard/common.pgcfg'
                    proguardFile '$playcoreDir/proguard/gms_task.pgcfg'
                    proguardFile '$playcoreDir/proguard/per-feature-proguard-files'
                    ...
                }
                debug {
                    ...
                }
            }
            externalNativeBuild {
                cmake {
                    path 'src/main/CMakeLists.txt'
                }
            }
        }
    
        dependencies {
            // Import these feature-specific AARs for each Google Play Core library.
            implementation 'com.google.android.play:app-update:2.1.0'
            implementation 'com.google.android.play:asset-delivery:2.3.0'
            implementation 'com.google.android.play:integrity:1.6.0'
            implementation 'com.google.android.play:review:2.0.2'
    
            // Import these common dependencies.
            implementation 'com.google.android.gms:play-services-tasks:18.0.2'
            implementation files("$playcoreDir/playcore-native-metadata.jar")
            ...
        }
        

    Kotlin

    // App build.gradle
    
    plugins {
        id("com.android.application")
    }
    
    // Define a path to the extracted Play Core SDK files.
    // If using a relative path, wrap it with file() since CMake requires absolute paths.
    val playcoreDir = file("../path/to/playcore-native-sdk")
    
    android {
        defaultConfig {
            ...
            externalNativeBuild {
                cmake {
                    // Define the PLAYCORE_LOCATION directive.
                    arguments += listOf("-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir")
                }
            }
            ndk {
                // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                abiFilters.clear()
                abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
            }
        }
        buildTypes {
            release {
                // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                proguardFile("$playcoreDir/proguard/common.pgcfg")
                proguardFile("$playcoreDir/proguard/gms_task.pgcfg")
                proguardFile("$playcoreDir/proguard/per-feature-proguard-files")
                ...
            }
            debug {
                ...
            }
        }
        externalNativeBuild {
            cmake {
                path = "src/main/CMakeLists.txt"
            }
        }
    }
    
    dependencies {
        // Import these feature-specific AARs for each Google Play Core library.
        implementation("com.google.android.play:app-update:2.1.0")
        implementation("com.google.android.play:asset-delivery:2.3.0")
        implementation("com.google.android.play:integrity:1.6.0")
        implementation("com.google.android.play:review:2.0.2")
    
        // Import these common dependencies.
        implementation("com.google.android.gms:play-services-tasks:18.0.2")
        implementation(files("$playcoreDir/playcore-native-metadata.jar"))
        ...
    }
  5. Uygulamanızın CMakeLists.txt dosyalarını aşağıda gösterildiği gibi güncelleyin:

    cmake_minimum_required(VERSION 3.6)
    
    ...
    
    # Add a static library called “playcore” built with the c++_static STL.
    include(${PLAYCORE_LOCATION}/playcore.cmake)
    add_playcore_static_library()
    
    // In this example “main” is your native code library, i.e. libmain.so.
    add_library(main SHARED
            ...)
    
    target_include_directories(main PRIVATE
            ${PLAYCORE_LOCATION}/include
            ...)
    
    target_link_libraries(main
            android
            playcore
            ...)
    

Veri Toplama

Play Core Native SDK, Google'ın ürünü iyileştirmesine olanak tanımak için sürümle ilgili verileri toplayabilir. Bu veriler arasında şunlar yer alır:

  • Uygulamanın paket adı
  • Uygulamanın paket sürümü
  • Play Core Yerel SDK'sının sürümü

Bu veriler, uygulama paketinizi Play Console'a yüklediğinizde toplanır. Bu veri toplama sürecinin kapsamı dışında kalmayı seçmek için build.gradle dosyasındaki $playcoreDir/playcore-native-metadata.jar içe aktarma işlemini kaldırın.

Play Core Native SDK'yı kullanımınızla ilgili bu veri toplama işleminin ve Google'ın toplanan verileri kullanımının, uygulama paketinizi Play Console'a yüklediğinizde Gradle'da beyan edilen kitaplık bağımlılıklarının Google tarafından toplanmasından ayrı ve bağımsız olduğunu unutmayın.

Play Core Yerel SDK'sını projenize entegre ettikten sonra API çağrıları içeren dosyalara aşağıdaki satırı ekleyin:

#include "play/app_update.h"

Uygulama içi güncelleme API'sini başlatma

Uygulama içi güncelleme API'sini her kullandığınızda, android_native_app_glue.h ile oluşturulan aşağıdaki örnekte gösterildiği gibi AppUpdateManager_init() işlevini çağırarak API'yi başlatın:

void android_main(android_app* app) {
  app->onInputEvent = HandleInputEvent;

  AppUpdateErrorCode error_code =
    AppUpdateManager_init(app->activity->vm, app->activity->clazz);
  if (error_code == APP_UPDATE_NO_ERROR) {
    // You can use the API.
  }
}

Güncelleme olup olmadığını kontrol etme

Güncelleme isteğinde bulunmadan önce uygulamanız için güncelleme olup olmadığını kontrol edin. AppUpdateManager_requestInfo(), daha sonra uygulama içi güncelleme akışını başlatmak için gereken bilgileri toplayan asenkron bir istek başlatır. İstek başarıyla başlatılırsa işlev APP_UPDATE_NO_ERROR değerini döndürür.

AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()

if (error_code == APP_UPDATE_NO_ERROR) {
    // The request has successfully started, check the result using
    // AppUpdateManager_getInfo.
}

AppUpdateManager_getInfo() aracını kullanarak devam eden süreci ve isteğin sonucunu takip edebilirsiniz. Bu işlev, hata koduna ek olarak güncelleme isteğiyle ilgili bilgi almak için kullanabileceğiniz opak bir AppUpdateInfo yapısı döndürür. Örneğin, info için boş olmayan bir sonuç döndürene kadar bu işlevi her oyun döngüsünde çağırmak isteyebilirsiniz:

AppUpdateInfo* info;
GameUpdate() {

   // Keep calling this in every game loop until info != nullptr
   AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);

   if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
       // Successfully started, check the result in the following functions
   }
...
}

Güncellemenin güncelliğini kontrol etme

Güncelleme olup olmadığını kontrol etmenin yanı sıra, kullanıcının Play Store üzerinden bir güncelleme hakkında en son ne zaman bilgilendirildiğini de kontrol etmek isteyebilirsiniz. Bu sayede, esnek güncelleme mi yoksa hemen güncelleme mi başlatmanız gerektiğine karar verebilirsiniz. Örneğin, kullanıcıya esnek bir güncelleme bildirimi göndermeden önce birkaç gün, hemen güncelleme yapmasını istemeden önce de birkaç gün bekleyebilirsiniz.

Güncellemenin Google Play Store'da kullanıma sunulmasından bu yana geçen gün sayısını kontrol etmek için AppUpdateInfo_getClientVersionStalenessDays() komutunu kullanın:

int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);

Güncelleme önceliğini kontrol etme

Google Play Developer API, her güncellemenin önceliğini ayarlamanıza olanak tanır. Bu sayede uygulamanız, kullanıcıya bir güncellemeyi ne kadar güçlü bir şekilde önereceğine karar verebilir. Örneğin, güncelleme önceliğini ayarlamak için aşağıdaki stratejiyi göz önünde bulundurun:

  • Kullanıcı arayüzüyle ilgili küçük iyileştirmeler: Düşük öncelikli güncelleme; esnek güncelleme veya hemen güncelleme istemeyin. Yalnızca kullanıcı uygulamanızla etkileşimde bulunmadığında güncelleyin.
  • Performans iyileştirmeleri: Orta öncelikli güncelleme; esnek güncelleme isteyin.
  • Kritik güvenlik güncellemesi: Yüksek öncelikli güncelleme; hemen güncelleme isteyin.

Google Play, önceliği belirlemek için 0 ile 5 arasında bir tam sayı değeri kullanır. 0 varsayılan değer, 5 ise en yüksek önceliktir. Bir güncellemenin önceliğini ayarlamak için Google Play Developer API'de Edits.tracks.releases altındaki inAppUpdatePriority alanını kullanın. Sürüme yeni eklenen tüm sürümler, sürümle aynı önceliğe sahip olarak kabul edilir. Öncelik yalnızca yeni bir sürüm yayınlanırken ayarlanabilir ve daha sonra değiştirilemez.

Play Developer API belgelerinde açıklandığı şekilde Google Play Developer API'yi kullanarak önceliği ayarlayın. Edit.tracks: update yönteminde iletilen Edit.tracks kaynağında uygulama güncellemesi önceliğini belirtin. Aşağıdaki örnekte, sürüm kodu 88 ve 5 olan bir uygulamanın yayınlanması gösterilmektedir: inAppUpdatePriority

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

Uygulamanızın kodunda, AppUpdateInfo_getPriority() kullanarak belirli bir güncellemenin öncelik düzeyini kontrol edebilirsiniz:

int32_t priority = AppUpdateInfo_getPriority(info);

Güncelleme başlatma

Güncelleme olduğunu onayladıktan sonra AppUpdateManager_requestStartUpdate() kullanarak güncelleme isteğinde bulunabilirsiniz. Güncelleme isteğinde bulunmadan önce güncel bir AppUpdateInfo nesnesi alın ve güncelleme akışını yapılandırmak için bir AppUpdateOptions nesnesi oluşturun. AppUpdateOptions nesnesi, güncellemenin esnek mi yoksa hemen mi olması gerektiği de dahil olmak üzere uygulama içi uygulama güncellemesi akışının seçeneklerini tanımlar.

Aşağıdaki örnekte, esnek güncelleme akışı için bir AppUpdateOptions nesnesi oluşturulmaktadır:

// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);

Aşağıdaki örnekte, anında güncelleme akışı için bir AppUpdateOptions nesnesi oluşturulmaktadır:

// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);

AppUpdateOptions nesnesi, sınırlı cihaz depolama alanı olması durumunda güncellemenin öğe paketlerini temizlemesine izin verilip verilmediğini tanımlayan bir AllowAssetPackDeletion alanı da içerir. Bu alan varsayılan olarak false değerine ayarlanır ancak AppUpdateOptions_setAssetPackDeletionAllowed() yöntemini kullanarak true değerine ayarlayabilirsiniz:

bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);

Güncel bir AppUpdateInfo nesnesi ve doğru şekilde yapılandırılmış bir AppUpdateOptions nesnesi oluşturduktan sonra, asenkron olarak güncelleme akışı istemek için AppUpdateManager_requestStartUpdate() yöntemini çağırın ve son parametre olarak bir Android etkinliği jobject iletin.

AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);

Kaynakları serbest bırakmak için artık ihtiyacınız olmayan AppUpdateInfo ve AppUpdateOptions örneklerini sırasıyla AppUpdateInfo_destroy() ve AppUpdateOptions_destroy() yöntemlerini çağırarak serbest bırakın.

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

Anında güncelleme akışı için Google Play bir kullanıcı onay sayfası gösterir. Kullanıcı isteği kabul ettiğinde Google Play, güncellemeyi otomatik olarak ön planda indirip yükler, ardından yükleme başarılı olursa uygulamayı güncellenmiş sürümle yeniden başlatır.

Esnek güncelleme akışında, kullanıcı uygulamayla etkileşimde bulunmaya devam ederken mevcut güncelleme durumunu takip etmek için güncel AppUpdateInfo nesneleri istemeye devam edebilirsiniz. İndirme işlemi başarıyla tamamlandıktan sonra aşağıdaki örnekte gösterildiği gibi AppUpdateManager_requestCompleteUpdate() yöntemini çağırarak güncellemenin tamamlanmasını tetiklemeniz gerekir:

AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
    AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
    if (error_code != APP_UPDATE_NO_ERROR)
    {
      // There was an error while completing the update flow.
    }
}

Uygulamanız API'yi kullanmayı tamamladıktan sonra AppUpdateManager_destroy() işlevini çağırarak kaynakları serbest bırakın.

Hata işleme

Bu bölümde, belirli AppUpdateErrorCode değerleriyle belirtilen yaygın hataların çözümleri açıklanmaktadır:

  • -110, APP_UPDATE_INITIALIZATION_NEEDED hata kodu, API'nin başarıyla başlatılmadığını gösterir. API'yi ilk kullanıma hazırlamak için AppUpdateManager_init() yöntemini çağırın.
  • -4, APP_UPDATE_INVALID_REQUEST hata kodu, güncelleme akışı isteğinin bazı parametrelerinin hatalı biçimlendirildiğini gösterir. AppUpdateInfo ve AppUpdateOptions nesnelerinin boş olmadığından ve doğru biçimlendirildiğinden emin olun.
  • -5, APP_UPDATE_UNAVAILABLE hata kodu, geçerli bir güncelleme olmadığını gösterir. Hedef sürümün aynı paket adına, uygulama kimliğine ve imzalama anahtarına sahip olduğundan emin olun. Güncelleme varsa uygulamanın önbelleğini temizleyin ve AppUpdateInfo'i yenilemek için AppUpdateManager_requestAppUpdateInfo() numarasını tekrar arayın.
  • -6, APP_UPDATE_NOT_ALLOWED hata kodu, AppUpdateOption nesnesi tarafından belirtilen güncelleme türüne izin verilmediğini gösterir. Güncelleme akışını başlatmadan önce AppUpdateInfo nesnesinin güncelleme türüne izin verildiğini gösterip göstermediğini kontrol edin.

Sonraki adımlar

Entegrasyonunuzun doğru şekilde çalıştığını doğrulamak için uygulamanızın uygulama içi güncellemelerini test edin.