我发现以下两个替代方法:
- 使用服务器API存储版本信息
- 使用Google标签并在应用程序中访问它,这不是首选方法。
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();
这就是全部。
<div[^>]*?>Current Version</div><div><span[^>]*?>(.*?)</span></div>
。 - vincent虽然这种方法非常hacky,但是这是我能够快速想出来的最好的解决方法。在我尝试的所有应用程序中都似乎可以使用。这是一种PHP解决方案,但你可以为任何其他语言选择preg_match()正则表达式部分。
public function getAndroidVersion(string $storeUrl): string
{
$html = file_get_contents($storeUrl);
$matches = [];
preg_match('/\[\[\[\"\d+\.\d+\.\d+/', $html, $matches);
if (empty($matches) || count($matches) > 1) {
throw new Exception('Could not fetch Android app version info!');
}
return substr(current($matches), 4);
}
使用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;
}
}
}
}
}
这里是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());
});
softwareVersion
。它可能已经改变了。 - Gi0rgi0s我怀疑请求应用程序版本的主要原因是提示用户进行更新。我不赞成抓取响应,因为这可能会在未来版本中破坏功能。
如果应用程序的最低版本为5.0,则可以按照文档https://developer.android.com/guide/app-bundle/in-app-updates实现应用内更新。
如果请求应用程序版本的原因不同,仍然可以使用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
}
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())));
}
}
JS示例(可移植到任何其他语言):
import { JSDOM } from 'jsdom';
import axios from 'axios';
const res = await axios('https://play.google.com/store/apps/details?id=com.yourapp');
const dom = new JSDOM(res.data);
const scripts = Array.from(dom.window.document.querySelectorAll('script'));
const script = scripts.find(s => s.textContent && s.textContent.includes('/store/apps/developer'));
const versionStringRegex = /"[0-9]+\.[0-9]+\.[0-9.]+"/g;
const matches = script.textContent.match(versionStringRegex);
const match = matches[0];
const version = match.replace(/"/g, '');
console.log(version); // '1.2.345'
不幸的是,应用商店最近改变了它们的DOM布局,以至于版本号只有在您打开模态框时才可见。
然而,在其中一个脚本标签中嵌入的元数据中,终将呈现到该模态框中的数据确实存在。它没有以任何方式键入,而是仅嵌入在一个数组中,因此此解决方案依赖于同一附近的一些数据,这些数据不太可能改变。
<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中最新的更改。希望能有所帮助。
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();
2022年我的Xamarin应用将采用C#解决方案。
var url = $"https://play.google.com/store/apps/details?id={_packageName}";
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
using (var handler = new HttpClientHandler())
{
using (var client = new HttpClient(handler))
{
using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead))
{
try
{
if (response.IsSuccessStatusCode)
{
var content = response.Content == null ? null : await response.Content.ReadAsStringAsync();
var versionMatch = Regex.Match(content, @"\[\[""\d+.\d+.\d+""\]\]"); //look for pattern [["X.Y.Z"]]
if (versionMatch.Groups.Count == 1)
{
var versionMatchGroup = versionMatch.Groups.FirstOrDefault();
if (versionMatchGroup.Success)
return versionMatch.Value.Replace("[", "").Replace("]", "").Replace("\"", "");
}
}
}
catch
{ }
}
}
}
}
return null;
使用服务器API存储版本信息
就像你所说的那样。这是一种检测更新的简单方法。在每个API调用中传递您的版本信息。当Playstore更新时,在服务器上更改版本。一旦服务器版本高于已安装应用程序版本,您可以在API响应中返回状态代码/消息,该代码/消息可以被处理并显示更新消息。 如果您使用此方法,还可以像WhatsApp一样阻止用户使用非常旧的应用程序。
或者,您可以使用推送通知,这很容易做...另外