如果当前版本<>提示Android应用用户更新应用市场版

时间:2011-04-05 16:22:06

标签: java android google-play

假设我的Android App版本0.1目前已安装在用户的手机上。每次他们启动我的应用程序时,我想检查Android Market中是否有可用的其他版本,让我们说这个版本是0.2。如果这两个版本之间存在不匹配,我想显示一个对话框,提示用户升级应用程序。

我完全理解从Android电子市场本身到用户存在通知程序,但就我的Google Analytics数据而言,提醒用户升级到新版本的应用程序并不是非常有效。

任何见解都会非常有用。谢谢StackOverflowers,你们摇滚!

7 个答案:

答案 0 :(得分:15)

Android Market是一个封闭的系统,只有一个非官方的api,可能随时都会破解。

您最好的选择就是在您的网络服务器上托管文件(xml,json或简单文本),您只需在将其发布到市场时更新当前版本的应用程序。

您的应用程序将只需要在启动时获取该文件,检查当前安装的应用程序是否具有较低的版本号,并显示一个对话框以警告用户他是否滞后。

答案 1 :(得分:5)

您可以使用的另一个选项是,如果您想避免让后端服务器存储您接受的答案中建议的当前应用版本,则使用Google Tag Manager(GTM)。

如果您已经在使用Google AnalyticsSDK,那么您也可以使用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
}

答案 2 :(得分:4)

查看可用于查询Android Market API的此库

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

答案 3 :(得分:4)

您可以使用此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)&lt; value(newVersion)”with“value(curVersion)!= value(newVersion)”

答案 4 :(得分:2)

从2019年开始,更新应用程序的最佳方法是使用Play Core库(1.5.0+)提供的应用程序内更新。它适用于棒棒糖和更高版本,但公平地说,Kit-Kat到今天还不到7%,很快将永远消失。您可以在Kit-Kat上安全地运行此代码,而无需进行版本检查,它不会崩溃。

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

应用内更新有两种类型:灵活立即

灵活会在对话框窗口中很好地询问您: enter image description here

立即会要求您更新该应用,以便继续以全屏消息使用该应用(可以关闭此页面):

enter image description here

重要提示: ,目前,您无法在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);
}

我们完成了!

测试。 请阅读docs,以便您了解如何使用Google Play上的测试曲目对其进行正确测试。

长话短说:

  1. 使用发行证书对您的应用进行签名,然后将其上传到Developer Play Console中“应用发行”下的发布轨道之一(alpha / beta /其他自定义封闭轨道)。

  2. 在“发行测试”页面的“管理测试人员”部分中,创建并添加测试人员列表,并确保您选中了该复选框! -此步骤是可选步骤,因为您的开发者帐户电子邮件也是测试人员帐户,您可以将其用于测试。

  3. 在测试人员列表中,您会找到“选择使用的网址”-复制此网址并将其提供给您的测试人员或自行打开。转到该页面并接受命题进行测试。将会有一个指向该应用程序的链接。 (您将无法在Play商店中搜索该应用,因此请将其添加为书签)

  4. 通过该链接在您的设备上安装应用。

  5. build.gradle中增加defaultConfig { versionCode k+1 }的版本,并构建另一个已签名的apk。Build> Generate Signed Bundle / APK ...并将其上传到您的发布轨道。

  6. 等... 1小时? 2小时?或更多,然后才能在轨道上发布。

  7. 在设备上
  8. 清除Play商店应用的缓存。问题在于Play应用会缓存有关已安装应用及其可用更新的详细信息,因此您需要清除缓存。为此,请执行以下两个步骤:

7.1。转到设置>应用> Google PLay Store>存储>清除缓存。

7.2。打开Play商店应用>打开主菜单>我的应用和游戏>,在那里您应该看到您的应用有新更新。

如果您没有看到它,请确保新的更新已在轨道上发布(转到您的书签页面,并使用它来打开Play商店中列出的应用,以查看其中显示了哪个版本)。另外,当您的更新发布时,您会在Developer Play Console的右上角看到一个通知(响铃图标将带有一个红点)。

希望有帮助。

答案 5 :(得分:0)

如果当前版本不等于市场版本,提示Android App用户更新应用程序,则应首先检查市场上的应用程序版本,并将其与设备上的应用程序版本进行比较。如果它们不同,则可能是可用的更新。在这篇文章中,我写下了在设备上获取当前版本的市场和当前版本的代码,并将它们进行比较。我还展示了如何显示更新对话框并将用户重定向到更新页面。请访问此链接:https://stackoverflow.com/a/33925032/5475941

答案 6 :(得分:0)

    My working Kotlin code for force App update: 

    var appUpdateManager: AppUpdateManager? = null
    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()
}

    }