如何从 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/… 这只是坏了。如果您使用正则表达式,则可以使用<div[^>]*?>Current Version</div><div><span[^>]*?>(.*?)</span></div>
对于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 的最新模式,即
<div class="BgcNfc">Current Version</div><span class="htlgb"><div><span class="htlgb">X.X.X</span></div>
我们首先必须匹配上面的节点序列,然后从上面的序列中获取版本值。下面是相同的代码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 导入 org.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 获取应用市场版本信息?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Rest Api 从 Microsoft Store 获取我的应用当前版本?
使用 android play store update 更新 android URI 方案