如何从 google play store 获取应用市场版本信息?

Posted

技术标签:

【中文标题】如何从 google play store 获取应用市场版本信息?【英文标题】:How to get app market version information from google play store? 【发布时间】:2016-03-22 10:39:44 【问题描述】:

如何从谷歌游戏商店获取应用程序版本信息,以便在更新 Play 商店应用程序时提示用户强制/推荐应用程序更新,即如果用户使用旧版本应用程序。我已经通过andorid-market-api 这不是官方的方式,还需要来自google 的oauth login 身份验证。我也经历过android query 它提供应用内版本检查,但在我的情况下不起作用。 我找到了以下两种选择:

使用将存储版本信息的服务器 API 使用谷歌标签并在应用内访问它,这不是首选方式。

还有其他方法可以轻松做到吗?

【问题讨论】:

我更喜欢你的第一种方式... @CapDroid 还有其他方法吗?尤其是在独立应用的情况下。 我不知道 :( 主要是我按照你的第一种方式 :) 采取第一种方法,虽然学习会很有趣,如果有其他选择的话。好问题! Checking my app version programmatically in Android market的可能重复 【参考方案1】:

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

1.

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;

    在你的活动中:

        VersionChecker versionChecker = new VersionChecker();
        String latestVersion = versionChecker.execute().get();
    

就是这样

【讨论】:

这是一个黑客。但这是一个非常好的 hack,不需要太多努力,特别是考虑到 Google 很难使用他们的 api。 +1。 :) 不错的 hack,但不再需要了:github.com/googlesamples/android-play-publisher-api/tree/master/… 这只是坏了。如果您使用正则表达式,则可以使用 &lt;div[^&gt;]*?&gt;Current Version&lt;/div&gt;&lt;div&gt;&lt;span[^&gt;]*?&gt;(.*?)&lt;/span&gt;&lt;/div&gt; 对于android用户在gradle文件中添加这个依赖,编译'org.jsoup:jsoup:1.11.3' 这也是通过用户的移动数据连接下载大量 html 数据(截至目前为 780 KB)。并非每个人都在加利福尼亚并且拥有无限数据计划。这段代码不仅不健壮,而且对用户来说也是一个巨大的麻烦。【参考方案2】:

旧版本(不再工作)

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

    $.get("https://play.google.com/store/apps/details?id=" + packageName + "&hl=en", function(data)
        console.log($('<div/>').html(data).contents().find('div[itemprop="softwareVersion"]').text().trim());
    );

当前解决方案

使用 php 后端。这已经工作了一年。似乎 Google 不会经常更改他们的 DOM。

public function getAndroidVersion(string $storeUrl): string

    $dom = new DOMDocument();
    $dom->loadHTML(file_get_contents($storeUrl));
    libxml_use_internal_errors(false);
    $elements = $dom->getElementsByTagName('span');

    $depth = 0;
    foreach ($elements as $element) 
        foreach ($element->attributes as $attr) 
            if ($attr->nodeName === 'class' && $attr->nodeValue === 'htlgb') 
                $depth++;
                if ($depth === 7) 
                    return preg_replace('/[^0-9.]/', '', $element->nodeValue);
                    break 2;
                
            
        
    

【讨论】:

我需要离子,但是当我使用它时会出现一些 cors 问题, 这是超级易碎的。我怎么知道?我继承的一个应用程序就是这样做的,今天已经开始hard崩溃了。 我在这个命令的输出中没有看到softwareVersion。应该是变了 @Gi0rgi0s 这已经很久没有工作了。你的 DOM 已经很稳定了。我一直在解析DOM。目前正在寻找课程:htlgb【参考方案3】:

使用此代码可以正常工作。

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())));
    


【讨论】:

【参考方案4】:

Firebase 远程配置可以在这里提供最佳帮助,

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

【讨论】:

【参考方案5】:

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

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

如果请求应用版本的原因不同,您仍然可以使用 appUpdateManager 来检索版本并做任何您想做的事情(例如将其存储在首选项中)。

例如我们可以将文档的 sn-p 修改成这样的:

// 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

【讨论】:

最佳解决方案,这是获取应用更新信息的官方方式【参考方案6】:

除了使用 JSoup,我们还可以通过模式匹配从 playStore 获取应用版本。

要匹配来自 google playstore 的最新模式,即 &lt;div class="BgcNfc"&gt;Current Version&lt;/div&gt;&lt;span class="htlgb"&gt;&lt;div&gt;&lt;span class="htlgb"&gt;X.X.X&lt;/span&gt;&lt;/div&gt; 我们首先必须匹配上面的节点序列,然后从上面的序列中获取版本值。下面是相同的代码sn-p:

    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 = "<div[^>]*?>Current\\sVersion</div><span[^>]*?>(.*?)><div[^>]*?>(.*?)><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 发布完整代码 不中继“当前版本”这个词更健壮,因为用户可能有不同的区域偏好【参考方案7】:

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

如您所说。这是检测更新的简单方法。在每个 API 调用中传递您的版本信息。当 playstore 更新时,更改服务器中的版本。一旦服务器版本高于安装的应用程序版本,您可以在 API 响应中返回一个状态代码/消息,可以处理并显示更新消息。 如果您使用此方法,您还可以阻止用户使用 WhatsApp 等非常旧的应用程序。

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

【讨论】:

我正在寻找服务器 API 以外的解决方案。感谢您的回复! 试试这个google官方api:github.com/googlesamples/android-play-publisher-api/tree/master/… 如何在 Cakephp 2.0 中使用 每个 API 调用对我来说似乎都是多余的。 不要添加新的 api 调用。在 api 中添加版本信息。参考github.com/mindhaq/restapi-versioning-spring【参考方案8】:

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

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 = "<div[^>]*?>Current\\sVersion</div><span[^>]*?>(.*?)><div[^>]*?>(.*?)><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;
    


用法:

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

【讨论】:

【参考方案9】:

服务器端用户版本 API:

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

使用 Jsoup 库:

这基本上是网络抓取。这不是一种方便的方法,因为如果谷歌更改了他们的代码,这个过程将不起作用。虽然可能性很小。无论如何,要获得带有 Jsop 库的版本。

    在你的 build.gradle 中添加这个库

    实现'org.jsoup:jsoup:1.11.1'

    为版本检查创建一个类:

导入 android.os.AsyncTask 导入 o​​rg.jsoup.Jsoup 导入 java.io.IOException

类 PlayStoreVersionChecker(private val packageName: String) : 异步任务()

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()

【讨论】:

【参考方案10】:

对于 PHP 它有助于 php 开发人员获取特定 play store 应用服务器端的版本代码

$package='com.whatsapp';
        $html = file_get_contents('https://play.google.com/store/apps/details?id='.$package.'&hl=en');
        preg_match_all('/<span class="htlgb"><div class="IQ1z0d"><span class="htlgb">(.*?)<\/span><\/div><\/span>/s', $html, $output);
print_r($output[1][3]);

【讨论】:

虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因,特别是当问题有多个好的答案时,确实有助于提高帖子的质量,并且可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案以添加解释并说明适用的限制和假设。 From Review【参考方案11】:

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

是的,每次更新您的应用程序时都会有额外的工作,但在这种情况下,您不依赖于可能会停止服务的某些“非官方”或第三方的东西。

以防万一您遗漏了什么 - 之前对您的主题的讨论 query the google play store for the version of an app?

【讨论】:

我试过android-market-api,现在不行了。我也试过android-query,但它不再工作了。 是的,android-market-api 似乎对我也不起作用了。 你可以使用这个:github.com/googlesamples/android-play-publisher-api/tree/master/…【参考方案12】:

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

使用 Volley 的示例:

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/master/… 如何在 Cakephp 2.0 中使用【参考方案13】:

最简单的方法是使用来自 google 的 firebase 包并使用远程通知或实时配置新版本并将 id 发送给版本号以下的用户 查看更多https://firebase.google.com/

【讨论】:

【参考方案14】: 更好的方法是使用Firebase Remote Config。 其他方式是使用您自己的 API。

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

从 google play 网页获取版本。我已经实现了这种方式,它的工作时间超过 1 年,但在此期间我必须更改 'matcher' 3-4 次,因为网页上的内容已更改。时不时检查一下也很头疼,因为你不知道在哪里可以更改。 但是如果你还想用这种方式,这里是我基于okHttp的kotlin代码:

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("\n")
        

        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()

【讨论】:

【参考方案15】:

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

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 play store 获取应用市场版本信息?的主要内容,如果未能解决你的问题,请参考以下文章

代表另一家公司在 Google Play Store 上发布应用

我想用css和js做一个像google play store这样的侧边栏

如何使用 AndroidPublisher api 在 google play store 中检索任何 google 应用程序的评论?

从 google play-store 安装后应用程序立即关闭 - Android

在 facebook 上显示从 google play store 弹出的即时安装

从 App Store 和 google Play Store 禁用 iOS 和 Android 应用程序,并向用户发送自定义消息