我如何从Google Play商店获取应用程序版本信息,以便在更新Play商店应用程序时(即在用户使用旧版本应用程序的情况下)提示用户强制/建议对应用程序进行更新。 我已经通过了andorid-market-api,这不是官方方法,还需要Google的oauth登录身份验证。 我也经历了android查询
它提供了应用内版本检查功能,但在我的情况下不起作用。
我发现以下两种选择:

  • 使用服务器API来存储版本信息
  • 使用google标记并在应用内访问它,这不是首选方式。

还有其他简便的方法吗?

  • 我喜欢你的第一种方式
  • @CapDroid还有其他方法吗? 特别是在独立应用程序的情况下。
  • 我不知道:(大多数情况下,我是按照你的第一种方式:)
  • 如果有其他选择,那么采用第一种方法也是第一种方法,尽管学习起来很有趣。 好问题!
  • 在Android Market中以编程方式检查我的应用程序版本的可能重复项
  • 我已经尝试过目前无法使用的市场API! 您提到的问题有提及吨市场API的答案。 所以没有重复的问题
  • 试试这个:github.com/googlesamples/android-play-publisher-api/tree/mas ter /

我建议不要使用库只是创建一个新类

1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class VersionChecker extends AsyncTask<String, String, String>{

String newVersion;

@Override
protected String doInBackground(String... params) {

    try {
        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.hAyfc:nth-child(4) > span:nth-child(2) > div:nth-child(1) > span:nth-child(1)")
                .first()
                .ownText();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return newVersion;
}
  • 在您的活动中:

    1
    2
        VersionChecker versionChecker = new VersionChecker();
        String latestVersion = versionChecker.execute().get();
  • 就这些

    • 这将是什么输出?我没有得到这个!是否输出版本信息?如果是,则采用什么格式?
    • 您将获得versionName的字符串,可以在文件" build.gradle"中找到此版本名称。
    • 这是一个hack。但这确实是一个不错的技巧,不需要太多的努力,尤其是考虑到Google使得使用它们的api变得困难。 +1。 :)
    • 不错的骇客,但自此不再需要了:github.com/googlesamples/android-play-publisher-api/tree/mas ter /
    • 谢谢。。。但是很漂亮。
    • @SandroWiggers哪个官方API可以检查应用程序版本?
    • 是的,它可能由于多种原因而失败。例如,1. Google更改您在select(" div [itemprop = softwareVersion]")中使用的密钥。最好的办法是在自己的服务器上维护一个API,该API可为您提供应用程序的当前市场版本,然后您可以将其与用户设备上安装的API进行比较。
    • 这刚刚坏了。如果您使用正则表达式,则可以使用]*?>Current Version]*?>(.*?)
    • 诚然,这种方式被打破了。您提供的表达式也不起作用@vincent
    • @bkm他们似乎正在更改它的atm。让我们看看最终结果是"稳定"的。
    • 在当前版本之间使用" \ s"修复模式后,我可以使用此功能:] *?> Current \ sVersion ] *?>(。*?)
    • .select("] *?> Current \\ sVersion ] *?>(。*?)")产生此错误方法抛出org.jsoup.select.Selector $ SelectorParseException异常@Cesar
    • 对于android用户,将此依赖项添加到gradle文件中,编译org.jsoup:jsoup:1.11.3
    • 认真的人..我只是想尝试n从早上开始就终于尝试了,这个工作了...非常感谢...
    • 那么,有没有人尝试过android-play-publisher-api获取当前版本号?我浏览了一下代码,但没有发现任何提示可用于此目的。
    • 没有官方的方法可以做到这一点。我的意思是您刚刚阅读了html网站。不是最漂亮的方法。
    • 这还通过用户移动数据连接下载了大量的HTML数据(到今天为止为780 Kb)。并非每个人都在加利福尼亚州并且有无限的数据计划。该代码不仅不够健壮,而且对用户也造成了很大的麻烦。

    使用此代码可以完美地工作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    public void forceUpdate(){
        PackageManager packageManager = this.getPackageManager();
        PackageInfo packageInfo = null;
        try {
            packageInfo =packageManager.getPackageInfo(getPackageName(),0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        String currentVersion = packageInfo.versionName;
        new ForceUpdateAsync(currentVersion,TodayWork.this).execute();
    }

    public class ForceUpdateAsync extends AsyncTask<String, String, JSONObject> {

        private String latestVersion;
        private String currentVersion;
        private Context context;
        public ForceUpdateAsync(String currentVersion, Context context){
            this.currentVersion = currentVersion;
            this.context = context;
        }

        @Override
        protected JSONObject doInBackground(String... params) {

            try {
                latestVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + context.getPackageName()+"&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.hAyfc:nth-child(3) > span:nth-child(2) > div:nth-child(1) > span:nth-child(1)")
                        .first()
                        .ownText();
                Log.e("latestversion","---"+latestVersion);

            } catch (IOException e) {
                e.printStackTrace();
            }
            return new JSONObject();
        }

        @Override
        protected void onPostExecute(JSONObject jsonObject) {
            if(latestVersion!=null){
                if(!currentVersion.equalsIgnoreCase(latestVersion)){
                    // Toast.makeText(context,"update is available.",Toast.LENGTH_LONG).show();
                    if(!(context instanceof SplashActivity)) {
                        if(!((Activity)context).isFinishing()){
                            showForceUpdateDialog();
                        }
                    }
                }
            }
            super.onPostExecute(jsonObject);
        }

        public void showForceUpdateDialog(){

            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName())));
        }

    }

    如果有人需要,这里是jQuery版本,以获取版本号。

    1
    2
    3
        $.get("https://play.google.com/store/apps/details?id=" + packageName +"&hl=en", function(data){
            console.log($('').html(data).contents().find('div[itemprop="softwareVersion"]').text().trim());
        });
    • 我需要离子性的,但是当我使用它时,会出现一些问题,
    • 这太脆了。我怎么知道?我继承的一个应用程序执行此操作,并且今天开始严重崩溃。

    Firebase Remote Config在这里可以提供最佳帮助,

    请参考这个答案
    https://stackoverflow.com/a/45750132/2049384


    除了使用JSoup,我们还可以进行模式匹配,以从playStore获取应用程序版本。

    要匹配来自Google Playstore的最新模式,即
    Current VersionX.X.X
    我们首先必须匹配上面的节点序列,然后从上面的序列中获取版本值。以下是相同的代码段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
        private String getAppVersion(String patternString, String inputString) {
            try{
                //Create a pattern
                Pattern pattern = Pattern.compile(patternString);
                if (null == pattern) {
                    return null;
                }

                //Match the pattern string in provided string
                Matcher matcher = pattern.matcher(inputString);
                if (null != matcher && matcher.find()) {
                    return matcher.group(1);
                }

            }catch (PatternSyntaxException ex) {

                ex.printStackTrace();
            }

            return null;
        }


        private String getPlayStoreAppVersion(String appUrlString) {
            final String currentVersion_PatternSeq ="]*?>Current\\\\sVersion<span[^>]*?>(.*?)>]*?>(.*?)><span[^>]*?>(.*?)</span>";
            final String appVersion_PatternSeq ="htlgb\">([^<]*)</s";
            String playStoreAppVersion = null;

            BufferedReader inReader = null;
            URLConnection uc = null;
            StringBuilder urlData = new StringBuilder();

            final URL url = new URL(appUrlString);
            uc = url.openConnection();
            if(uc == null) {
               return null;
            }
            uc.setRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
            inReader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
            if (null != inReader) {
                String str ="";
                while ((str = inReader.readLine()) != null) {
                               urlData.append(str);
                }
            }

            // Get the current version pattern sequence
            String versionString = getAppVersion (currentVersion_PatternSeq, urlData.toString());
            if(null == versionString){
                return null;
            }else{
                // get version from"htlgb">X.X.X</span>
                playStoreAppVersion = getAppVersion (appVersion_PatternSeq, versionString);
            }

            return playStoreAppVersion;
        }

    我通过这个解决了这个问题。这也解决了Google在PlayStore中所做的最新更改。希望能有所帮助。

    • 在您的允许下,我将使用AsynsTask发布完整代码
    • 由于用户可能有不同的地点偏爱,因此不中继"当前版本"一词更为可靠

    我怀疑请求应用程序版本的主要原因是提示用户进行更新。我不赞成取消响应,因为这可能会破坏将来版本的功能。

    如果应用的最低版本为5.0,则可以根据文档https://developer.android.com/guide/app-bundle/in-app-updates实施应用内更新

    如果请求应用程序版本的原因不同,您仍然可以使用appUpdateManager来检索版本并执行所需的任何操作(例如,将其存储在首选项中)。

    例如,我们可以将文档的片段修改为如下形式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Creates instance of the manager.
    val appUpdateManager = AppUpdateManagerFactory.create(context)

    // Returns an intent object that you use to check for an update.
    val appUpdateInfoTask = appUpdateManager.appUpdateInfo

    // Checks that the platform will allow the specified type of update.
    appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
        val version = appUpdateInfo.availableVersionCode()
        //do something with version. If there is not a newer version it returns an arbitary int
    }

    此解决方案的完整源代码:https://stackoverflow.com/a/50479184/5740468

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    import android.os.AsyncTask;
    import android.support.annotation.Nullable;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.regex.PatternSyntaxException;

    public class GooglePlayAppVersion extends AsyncTask<String, Void, String> {

        private final String packageName;
        private final Listener listener;
        public interface Listener {
            void result(String version);
        }

        public GooglePlayAppVersion(String packageName, Listener listener) {
            this.packageName = packageName;
            this.listener = listener;
        }

        @Override
        protected String doInBackground(String... params) {
            return getPlayStoreAppVersion(String.format("https://play.google.com/store/apps/details?id=%s", packageName));
        }

        @Override
        protected void onPostExecute(String version) {
            listener.result(version);
        }

        @Nullable
        private static String getPlayStoreAppVersion(String appUrlString) {
            String
                  currentVersion_PatternSeq ="]*?>Current\\\\sVersion<span[^>]*?>(.*?)>]*?>(.*?)><span[^>]*?>(.*?)</span>",
                  appVersion_PatternSeq ="htlgb\">([^<]*)</s";
            try {
                URLConnection connection = new URL(appUrlString).openConnection();
                connection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
                try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                    StringBuilder sourceCode = new StringBuilder();
                    String line;
                    while ((line = br.readLine()) != null) sourceCode.append(line);

                    // Get the current version pattern sequence
                    String versionString = getAppVersion(currentVersion_PatternSeq, sourceCode.toString());
                    if (versionString == null) return null;

                    // get version from"htlgb">X.X.X</span>
                    return getAppVersion(appVersion_PatternSeq, versionString);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Nullable
        private static String getAppVersion(String patternString, String input) {
            try {
                Pattern pattern = Pattern.compile(patternString);
                if (pattern == null) return null;
                Matcher matcher = pattern.matcher(input);
                if (matcher.find()) return matcher.group(1);
            } catch (PatternSyntaxException e) {
                e.printStackTrace();
            }
            return null;
        }

    }

    用法:

    1
    2
    3
    new GooglePlayAppVersion(getPackageName(), version ->
        Log.d("TAG", String.format("App version: %s", version)
    ).execute();

    使用服务器API来存储版本信息

    如您所说,这是检测更新的简便方法。在每次API调用时传递您的版本信息。 Playstore更新后,请更改服务器中的版本。服务器版本高于已安装的应用程序版本后,您可以在API响应中返回状态代码/消息,可以对其进行处理并显示更新消息。如果您使用此方法,您还可以阻止用户使用像WhatsApp这样的非常老的应用程序。

    或者您可以使用推式通知,这很容易做到...也

    • 我正在寻找服务器API以外的解决方案。谢谢回复!
    • 试试这个Google官方api:github.com/googlesamples/android-play-publisher-api/tree/mas ter /
    • 如何在Cakephp 2.0中使用
    • 对我来说,每个API调用似乎都太过分了。
    • 不要添加新的api调用。在api中添加版本信息。参考github.com/mindhaq/restapi-versioning-spring
    • 但是,如果您使用此方法,则Google团队需要审查更新,并且您如何知道何时更改API中的版本?

    对于PHP

    1
    2
    3
    4
    $package='com.whatsapp';
            $html = file_get_contents('https://play.google.com/store/apps/details?id='.$package.'&hl=en');
            preg_match_all('/<span class="htlgb"><span class="htlgb">(.*?)<\\/span><\\/div><\\/span>/s', $html, $output);
    print_r($output[1][3]);
    • 尽管这段代码可以解决问题,包括解释如何以及为什么解决问题的方法,特别是当问题有多个好的答案时,这实际上将有助于提高您的帖子质量,并可能导致更多的投票。 请记住,您将来会为读者回答问题,而不仅仅是现在问的人。 请编辑您的答案以添加说明,并指出适用的限制和假设。 来自评论

    服务器端的用户版本Api:

    这是目前仍获得市场版本的最佳方法。当您上传新的APK时,请更新api中的版本。因此,您将在您的应用程序中获得最新版本。
    -这是最好的,因为没有google api可以获取应用程序版本。

    使用Jsoup库:

    这基本上是网页抓取。这不是一种方便的方法,因为如果Google更改了他们的代码,则此过程将无法进行。虽然可能性较小。无论如何,要使用Jsop库获取版本。

  • 将此库添加到您的build.gradle中

    实现'org.jsoup:jsoup:1.11.1'

  • 创建一个用于版本检查的类:

  • import android.os.AsyncTask import org.jsoup.Jsoup import
    java.io.IOException

    class PlayStoreVersionChecker(private val packageName: String) :
    AsyncTask() {

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    private var playStoreVersion: String =""

    override fun doInBackground(vararg params: String?): String {
        try {
            playStoreVersion =
                    Jsoup.connect("https://play.google.com/store/apps/details?id=$packageName&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.hAyfc:nth-child(4) > span:nth-child(2) > div:nth-child(1) > span:nth-child(1)")
                        .first()
                        .ownText()
        } catch (e: IOException) {
        }
        return playStoreVersion
    } }
  • 现在,使用以下类:

    val playStoreVersion = PlayStoreVersionChecker(" com.example")。execute()。get()


  • 我的解决方法是解析Google Play网站并提取版本号。
    如果您遇到CORS问题或想节省用户设备上的带宽,请考虑从Web服务器上运行它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    let ss = [html];

    for (let p of ['div', 'span', '>', '<']) {
      let acc = [];
      ss.forEach(s => s.split(p).forEach(s => acc.push(s)));
      ss = acc;
    }

    ss = ss
      .map(s => s.trim())
      .filter(s => {
        return parseFloat(s) == +s;
      });

    console.log(ss); // print something like [ '1.10' ]

    您可以通过获取https://play.google.com/store/apps/details?id=your.package.name来获取html文本。为了实现可比性,您可以使用https://www.npmjs.com/package/cross-fetch(可在浏览器和node.js上使用)。

    其他人提到使用某些CSS类或模式(例如"当前版本")从Google Play网站解析html,但是这些方法可能不那么可靠。因为Google可以随时更改班级名称。它也可能根据用户的语言环境偏好返回不同语言的文本,因此您可能不会得到"当前版本"一词。


    • 更好的方法是使用Firebase远程配置。
    • 其他方法是使用您自己的API。

    这样的好处是,您将可以检查版本号而不是名称,这应该更加方便:)另一方面-您应该注意每次发布后在api / firebase中更新版本。

    • 从Google Play网页上获取版本。我已经实现了这种方式,并且可以工作超过1年,但是在此期间,我不得不将"匹配器"更改3-4次,因为网页上的内容已更改。另外,不时检查它有些头痛,因为您不知道可以在哪里更改。
      但是,如果您仍然想使用这种方式,这是基于okHttp的我的kotlin代码:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      private fun getVersion(onChecked: OnChecked, packageName: String) {

      Thread {
          try {
              val httpGet = HttpGet("https://play.google.com/store/apps/details?id="
                      + packageName +"&hl=it")

              val response: HttpResponse
              val httpParameters = BasicHttpParams()
              HttpConnectionParams.setConnectionTimeout(httpParameters, 10000)
              HttpConnectionParams.setSoTimeout(httpParameters, 10000)
              val httpclient = DefaultHttpClient(httpParameters)
              response = httpclient.execute(httpGet)

              val entity = response.entity
              val `is`: InputStream
              `is` = entity.content
              val reader: BufferedReader
              reader = BufferedReader(InputStreamReader(`is`,"iso-8859-1"), 8)
              val sb = StringBuilder()
              var line: String? = null
              while ({ line = reader.readLine(); line }() != null) {
                  sb.append(line).append("\
      ")
              }

              val resString = sb.toString()
              var index = resString.indexOf(MATCHER)
              index += MATCHER.length
              val ver = resString.substring(index, index + 6) //6 is version length
              `is`.close()
              onChecked.versionUpdated(ver)
              return@Thread
          } catch (ignore: Error) {
          } catch (ignore: Exception) {
          }

          onChecked.versionUpdated(null)
      }.start()
      }


    您可以调用以下WebService:
    http://carreto.pt/tools/android-store-version/?package=[YOUR_APP_PACKAGE_NAME]

    使用Volley的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    String packageName ="com.google.android.apps.plus";
    String url ="http://carreto.pt/tools/android-store-version/?package=";
    JsonObjectRequest jsObjRequest = new JsonObjectRequest
        (Request.Method.GET, url+packageName, null, new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            /*
                                    here you have access to:

                                    package_name, - the app package name
                                    status - success (true) of the request or not (false)
                                    author - the app author
                                    app_name - the app name on the store
                                    locale - the locale defined by default for the app
                                    publish_date - the date when the update was published
                                    version - the version on the store
                                    last_version_description - the update text description
                                 */
                            try{
                                if(response != null && response.has("status") && response.getBoolean("status") && response.has("version")){
                                    Toast.makeText(getApplicationContext(), response.getString("version").toString(), Toast.LENGTH_LONG).show();
                                }
                                else{
                                    //TODO handling error
                                }
                            }
                            catch (Exception e){
                                //TODO handling error
                            }

                        }
                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            //TODO handling error
                        }
            });
    • 应该更容易:github.com/googlesamples/android-play-publisher-api/tree/mas ter /
    • 如何在Cakephp 2.0中使用

    我建议使用ex。推送通知以通知您的应用程序有新更新,或者使用您自己的服务器从那里启用您的应用程序读取版本。

    是的,每次您更新应用程序时,它的其他工作都是可行的,但是在这种情况下,您并不依赖于某些"非正式"或第三方的服务,这些服务可能会失效。

    以防万一您错过了什么-之前对您的主题的讨论
    向Google Play商店查询应用程序的版本?

    • 我试过了android-market-api,现在无法正常工作。我也尝试了android-query,它不再起作用。
    • 是的,android-market-api对我来说似乎也不再起作用。
    • 您可以使用以下代码:github.com/googlesamples/android-play-publisher-api/tree/mas ter /