41

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

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

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

4

15 回答 15

51

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

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;
}
  1. 在您的活动中:

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

就这些

于 2016-04-08T21:35:39.010 回答
9

旧版本(不再工作)

如果其他人需要,这里是 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 后端。这已经工作了一年。谷歌似乎并没有那么频繁地改变他们的 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;
                }
            }
        }
    }
}
于 2016-09-30T11:17:59.500 回答
8

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

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

}
于 2018-05-25T09:20:22.567 回答
7

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

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

于 2017-08-18T06:47:18.423 回答
7

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

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

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

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

// 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
}
于 2019-08-08T08:37:26.397 回答
4

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

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

    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 中所做的最新更改。希望有帮助。

于 2018-05-23T03:01:21.277 回答
3

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

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

或者您可以使用推送通知,这很容易做到......还有

于 2015-12-21T19:13:07.210 回答
3

此解决方案的完整源代码:https ://stackoverflow.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();
于 2018-09-24T15:20:22.227 回答
1

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

$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]);
于 2020-06-02T16:18:57.907 回答
1

服务器端的用户版本 API:

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

使用 Jsoup 库:

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

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

    实施 'org.jsoup:jsoup:1.11.1'

  2. 为版本检查创建一个类:

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

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

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
} }
  1. 现在按如下方式使用该类:

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

于 2020-05-12T09:32:54.187 回答
0

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

于 2017-10-17T23:06:04.233 回答
0

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

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

    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()
    }
    
于 2019-04-17T06:21:58.467 回答
0

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

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' ]

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

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

于 2020-03-02T02:06:37.540 回答
0

您可以调用以下 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
                    }
        });
于 2016-09-01T16:26:15.980 回答
0

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

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

以防万一您错过了某些内容 - 之前对您的主题的讨论会 在 google play store 中查询应用程序的版本?

于 2015-12-19T03:48:34.280 回答