簡體   English   中英

如果當前版本 <> 市場版本,則提示 Android 應用用戶更新應用

[英]Prompt Android App User to Update App if current version <> market version

假設我的 Android 應用程序 0.1 版當前安裝在用戶的手機上。 每次他們啟動我的應用程序時,我都想檢查一下 Android Market 中是否有不同的可用版本,比如說這個版本是 0.2。 如果這兩個版本不匹配,我想顯示一個對話框,提示用戶升級應用程序。

我完全理解 Android Market 本身有一個通知程序給用戶,但就我的分析數據而言,它在提醒用戶升級到新版本的應用程序方面不是很有效。

任何見解都會非常有幫助。 感謝 StackOverflowers,你們搖滾!

截至 2019 年,更新應用的最佳方式是使用 Play 核心庫 (1.5.0+) 提供的應用內更新。 它適用於 Lollipop 和更新版本,但公平地說,Kit-Kat 截至今天還不到 7%,很快就會永遠消失。 您可以在 Kit-Kat 上安全地運行此代碼而無需進行版本檢查,它不會崩潰。

官方文檔: https : //developer.android.com/guide/app-bundle/in-app-updates

有兩種類型的應用內更新:靈活立即

靈活將在對話窗口中很好地詢問您: 在此處輸入圖片說明

Immediate將要求您更新應用程序以繼續使用它並顯示全屏消息(此頁面可以關閉):

在此處輸入圖片說明

重要提示:目前,您無法在 Developer Play Console 的“應用發布”部分中選擇要推出的更新類型。 但顯然,他們很快就會給我們這個選擇。 根據我的測試,目前,我們在onSuccessListener獲得了這兩種類型。

所以讓我們在我們的代碼中實現這兩種類型。

在模塊build.gradle添加以下依賴項:

dependencies {
    implementation 'com.google.android.play:core:1.6.1'//for new version updater
}

MainActivity.class

private static final int REQ_CODE_VERSION_UPDATE = 530;
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

   checkForAppUpdate();
}

@Override
protected void onResume() {
    super.onResume();
    checkNewAppVersionState();
}

@Override
public void onActivityResult(int requestCode, final int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);

    switch (requestCode) {

        case REQ_CODE_VERSION_UPDATE:
            if (resultCode != RESULT_OK) { //RESULT_OK / RESULT_CANCELED / RESULT_IN_APP_UPDATE_FAILED
                L.d("Update flow failed! Result code: " + resultCode);
                // If the update is cancelled or fails,
                // you can request to start the update again.
                unregisterInstallStateUpdListener();
            }

            break;
    }
}

@Override
protected void onDestroy() {
    unregisterInstallStateUpdListener();
    super.onDestroy();
}


private void checkForAppUpdate() {
    // Creates instance of the manager.
    appUpdateManager = AppUpdateManagerFactory.create(AppCustom.getAppContext());

    // Returns an intent object that you use to check for an update.
    Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();

    // Create a listener to track request state updates.
    installStateUpdatedListener = new InstallStateUpdatedListener() {
        @Override
        public void onStateUpdate(InstallState installState) {
            // Show module progress, log state, or install the update.
            if (installState.installStatus() == InstallStatus.DOWNLOADED)
                // After the update is downloaded, show a notification
                // and request user confirmation to restart the app.
                popupSnackbarForCompleteUpdateAndUnregister();
        }
    };

    // Checks that the platform will allow the specified type of update.
    appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
        if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
            // Request the update.
            if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {

                // Before starting an update, register a listener for updates.
                appUpdateManager.registerListener(installStateUpdatedListener);
                // Start an update.
                startAppUpdateFlexible(appUpdateInfo);
            } else if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ) {
                // Start an update.
                startAppUpdateImmediate(appUpdateInfo);
            }
        }
    });
}

private void startAppUpdateImmediate(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.IMMEDIATE,
                // The current activity making the update request.
                this,
                // Include a request code to later monitor this update request.
                MainActivity.REQ_CODE_VERSION_UPDATE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
    }
}

private void startAppUpdateFlexible(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.FLEXIBLE,
                // The current activity making the update request.
                this,
                // Include a request code to later monitor this update request.
                MainActivity.REQ_CODE_VERSION_UPDATE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
        unregisterInstallStateUpdListener();
    }
}

/**
 * Displays the snackbar notification and call to action.
 * Needed only for Flexible app update
 */
private void popupSnackbarForCompleteUpdateAndUnregister() {
    Snackbar snackbar =
            Snackbar.make(drawerLayout, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE);
    snackbar.setAction(R.string.restart, new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            appUpdateManager.completeUpdate();
        }
    });
    snackbar.setActionTextColor(getResources().getColor(R.color.action_color));
    snackbar.show();

    unregisterInstallStateUpdListener();
}

/**
 * Checks that the update is not stalled during 'onResume()'.
 * However, you should execute this check at all app entry points.
 */
private void checkNewAppVersionState() {
    appUpdateManager
            .getAppUpdateInfo()
            .addOnSuccessListener(
                    appUpdateInfo -> {
                        //FLEXIBLE:
                        // If the update is downloaded but not installed,
                        // notify the user to complete the update.
                        if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                            popupSnackbarForCompleteUpdateAndUnregister();
                        }

                        //IMMEDIATE:
                        if (appUpdateInfo.updateAvailability()
                                == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
                            // If an in-app update is already running, resume the update.
                            startAppUpdateImmediate(appUpdateInfo);
                        }
                    });

}

/**
 * Needed only for FLEXIBLE update
 */
private void unregisterInstallStateUpdListener() {
    if (appUpdateManager != null && installStateUpdatedListener != null)
        appUpdateManager.unregisterListener(installStateUpdatedListener);
}

我們完成了!

測試。 請閱讀 文檔,以便您了解如何使用 Google Play 上的測試軌道正確測試它。

長話短說:

  1. 使用發布證書對您的應用進行簽名,並將其上傳到 Developer Play Console 中 App Releases 下的發布軌道之一(alpha/beta/其他自定義封閉軌道)。

  2. 在“管理測試人員”部分的發布跟蹤頁面中,創建並添加測試人員列表,並確保選中了復選框 - 此步驟是可選的,因為您的開發者帳戶電子郵件也是測試人員帳戶,您可以將其用於測試。

  3. 在測試人員列表下,您會找到“選擇加入 URL” - 復制此 URL 並將其提供給您的測試人員或自己打開。 轉到該頁面並接受測試提議。 將有一個指向該應用程序的鏈接。 (您將無法在 Play 商店中搜索該應用,因此將其添加為書簽)

  4. 通過該鏈接在您的設備上安裝該應用程序。

  5. build.gradle增加defaultConfig { versionCode k+1 }並構建另一個簽名的 apk Build > Generate Signed Bundle / APK... 並將其上傳到您的發布軌道。

  6. 等……1小時? 2小時? 或更多之前它將在軌道上發布。

  7. 清除設備上 Play 商店應用的緩存 問題在於 Play 應用會緩存有關已安裝應用及其可用更新的詳細信息,因此您需要清除緩存。 為此,請執行以下兩個步驟:

7.1. 轉到設置 > 應用程序 > Google PLAy 商店 > 存儲 > 清除緩存。

7.2. 打開 Play 商店應用 > 打開主菜單 > 我的應用和游戲 > 您應該會看到您的應用有新的更新。

如果您沒有看到它,請確保您的新更新已經在軌道上發布(轉到您的書簽頁面並使用它打開您在 Play 商店中的應用列表,查看那里顯示的版本)。 此外,當您的更新上線時,您會在開發者 Play 管理中心的右上角看到一條通知(鍾形圖標帶有紅點)。

希望能幫助到你。

Android Market 是一個封閉的系統,只有一個非官方的 api,可能會在任何時候中斷。

您最好的選擇是在您的 Web 服務器上托管一個文件(xml、json 或簡單文本),您只需在將其發布到市場上時更新應用程序的當前版本即可。

然后,您的應用程序只需在啟動時獲取該文件,檢查當前安裝的應用程序是否具有較低的版本號,並顯示一個對話框以警告用戶他滯后了。

如果您想避免讓后端服務器像接受的答案中建議的那樣存儲當前的應用程序版本,則可以使用的另一個選項是使用Google 標簽管理器(GTM)。

如果您已經在使用 Google Analytics SDK,那么您也可以使用 GTM。

在 GTM 中,您可以在應用程序的容器中定義一個值,用於指定您最新發布的版本。 例如:

{
   "latestAppVersion": 14,
   ...
}

然后,您可以在應用啟動時查詢該值,並在有更新版本時顯示用戶更新對話框提醒。

Container container = TagManager.getInstance(context).openContainer(myContainerId);
long latestVersionCode = container.getLong("latestAppVersion");

// get currently running app version code
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
long versionCode = pInfo.versionCode;

// check if update is needed
if(versionCode < latestVersionCode) {
   // remind user to update his version
}

您可以使用此 Android 庫: https : //github.com/danielemaddaluno/Android-Update-Checker 它旨在提供一種可重用的工具,以異步檢查應用商店中是否存在任何較新發布的應用更新。 它基於使用 Jsoup ( http://jsoup.org/ ) 來測試是否真的存在新的更新解析 Google Play 商店中的應用程序頁面:

private boolean web_update(){
    try {       
        String curVersion = applicationContext.getPackageManager().getPackageInfo(package_name, 0).versionName; 
        String newVersion = curVersion;
        newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + package_name + "&hl=en")
                .timeout(30000)
                .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6")
                .referrer("http://www.google.com")
                .get()
                .select("div[itemprop=softwareVersion]")
                .first()
                .ownText();
        return (value(curVersion) < value(newVersion)) ? true : false;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

並且作為“值”函數如下(如果值介於 0-99 之間有效):

private long value(String string) {
    string = string.trim();
    if( string.contains( "." )){ 
        final int index = string.lastIndexOf( "." );
        return value( string.substring( 0, index ))* 100 + value( string.substring( index + 1 )); 
    }
    else {
        return Long.valueOf( string ); 
    }
}

如果您只想驗證版本之間的不匹配,您可以更改:

“value(curVersion) < value(newVersion)”與“value(curVersion) != value(newVersion)”

看看這個庫,你可以用它來查詢 Android Market API

http://code.google.com/p/android-market-api/

如果當前版本不等於市場版本,提示Android App用戶更新應用,您應該首先檢查市場上的應用版本,並將其與設備上的應用版本進行比較。 如果它們不同,則可能是可用更新。 在這篇文章中,我寫下了獲取當前市場版本和設備當前版本的代碼,並將它們放在一起進行比較。 我還展示了如何顯示更新對話框並將用戶重定向到更新頁面。 請訪問此鏈接: https : //stackoverflow.com/a/33925032/5475941

我用於強制應用程序更新的工作 Kotlin 代碼:

const val FLEXIABLE_UPADTE: Int = 101
const val FORCE_UPDATE: Int = 102
const val APP_UPDATE_CODE: Int = 500

override fun onCreate {
    // Get updateType from Webservice.
    updateApp(updateType)
}

private fun updateApp(statusCode: Int) {
    appUpdateManager = AppUpdateManagerFactory.create(this @MainActivity)

    val appUpdateInfoTask = appUpdateManager ? .appUpdateInfo

    appUpdateInfoTask ? .addOnSuccessListener {
        appUpdateInfo - >
            if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
                if ((statusCode == Constants.FORCE_UPDATE))
                    appUpdateManager ? .startUpdateFlowForResult(
                        appUpdateInfo, AppUpdateType.IMMEDIATE, this, Constants.APP_UPDATE_CODE
                    )
                else if (statusCode == Constants.FLEXIABLE_UPADTE)
                    appUpdateManager ? .startUpdateFlowForResult(
                        appUpdateInfo, AppUpdateType.FLEXIBLE, this, Constants.FLEXIABLE_UPADTE
                    )
            }
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent ? ) {

    try {
        if (requestCode == Constants.APP_UPDATE_CODE && resultCode == Activity.RESULT_OK) {
            if (resultCode != RESULT_OK) {
                appUpdateCompleted()
            }
        }
    } catch (e: java.lang.Exception) {

    }
}

private fun appUpdateCompleted() {
    Snackbar.make(
        findViewById(R.id.activity_main_layout),
        "An update has just been downloaded.",
        Snackbar.LENGTH_INDEFINITE
    ).apply {
        setAction("RESTART") {
            appUpdateManager.completeUpdate()
        }
        setActionTextColor(resources.getColor(R.color.snackbar_action_text_color))
        show()
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM