You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Jsoup的Version Checker版本检测功能失效问题求助

Hey there! Let's break down your version update check setup and fix up those rough edges. I’ve worked with plenty of apps that started with similar web-scraping logic, so I know exactly where the pain points are.

Optimizing Your Play Store App Version Update Logic

First, let’s call out the critical issues in your current code snippet:

  • Using execute().get() on your VersionChecker is a synchronous blocking call—this will freeze your main thread, which almost guarantees ANRs (App Not Responding) in production. Terrible for user experience!
  • Scraping the Play Store details page is extremely fragile. Google tweaks that page’s HTML structure regularly, and you might even get blocked by their anti-scraping measures, leaving users stuck without update prompts.

Here are two solid solutions to fix this:

Solution 1: Refactor to Async, Non-Blocking Version Check

If you want to stick with a web-scraping approach (though I don’t recommend it long-term), at least fix the blocking issue with async callbacks. Let’s adjust your code:

private void checkVersionNumber() {
    VersionChecker versionChecker = new VersionChecker();
    versionChecker.setListener(new VersionCheckListener() {
        @Override
        public void onLatestVersionFound(String latestVersion) {
            try {
                PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
                String currentVersion = pInfo.versionName;
                
                // Pro tip: Use versionCode (integer) for simpler, more reliable comparison
                // int currentCode = pInfo.versionCode;
                // int latestCode = Integer.parseInt(latestVersion); // Adjust if you scrape versionCode instead
                
                if (!currentVersion.equals(latestVersion)) {
                    showUpdatePromptDialog();
                }
            } catch (PackageManager.NameNotFoundException e) {
                DebugLog.e(TAG, "Failed to fetch current app version", e);
            }
        }

        @Override
        public void onCheckFailed(Exception e) {
            DebugLog.e(TAG, "Version check failed", e);
        }
    });
    versionChecker.execute();
}

// Add a callback interface to your VersionChecker
public interface VersionCheckListener {
    void onLatestVersionFound(String latestVersion);
    void onCheckFailed(Exception e);
}

// Update your VersionChecker to use async callbacks
public class VersionChecker extends AsyncTask<Void, Void, String> {
    private VersionCheckListener listener;

    public void setListener(VersionCheckListener listener) {
        this.listener = listener;
    }

    @Override
    protected String doInBackground(Void... voids) {
        try {
            String playStoreUrl = "https://play.google.com/store/apps/details?id=" + YourApp.getContext().getPackageName();
            URL url = new URL(playStoreUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();
            connection.disconnect();
            
            // Parse the HTML to extract version (note: this can break anytime!)
            Pattern versionPattern = Pattern.compile("\\[(\\d+\\.\\d+\\.\\d+)\\]");
            Matcher matcher = versionPattern.matcher(response.toString());
            return matcher.find() ? matcher.group(1) : null;
        } catch (Exception e) {
            if (listener != null) listener.onCheckFailed(e);
            return null;
        }
    }

    @Override
    protected void onPostExecute(String latestVersion) {
        if (listener != null && latestVersion != null) {
            listener.onLatestVersionFound(latestVersion);
        }
    }
}

This is the gold standard for Play Store app updates. It’s reliable, maintained by Google, and supports flexible update flows (like allowing users to update later or forcing immediate updates).

Step 1: Add Dependency

Add this to your module-level build.gradle file:

dependencies {
    implementation 'com.google.android.play:app-update:2.1.0'
}

Step 2: Implement Update Logic

private AppUpdateManager appUpdateManager;
private static final int UPDATE_REQUEST_CODE = 100;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    appUpdateManager = AppUpdateManagerFactory.create(this);
    checkForAvailableUpdates();
}

private void checkForAvailableUpdates() {
    Task<AppUpdateInfo> updateInfoTask = appUpdateManager.getAppUpdateInfo();
    
    updateInfoTask.addOnSuccessListener(appUpdateInfo -> {
        // Check for flexible update (user can choose to update later)
        if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
            startFlexibleUpdate(appUpdateInfo);
        }
        // Check for immediate update (user must update to continue using the app)
        else if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
            startImmediateUpdate(appUpdateInfo);
        }
    });
}

private void startFlexibleUpdate(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.FLEXIBLE,
                this,
                UPDATE_REQUEST_CODE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
    }
}

private void startImmediateUpdate(AppUpdateInfo appUpdateInfo) {
    try {
        appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.IMMEDIATE,
                this,
                UPDATE_REQUEST_CODE);
    } catch (IntentSender.SendIntentException e) {
        e.printStackTrace();
    }
}

// Handle update result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == UPDATE_REQUEST_CODE) {
        if (resultCode != RESULT_OK) {
            DebugLog.d(TAG, "Update failed with result code: " + resultCode);
            // Optionally retry the update here
        }
    }
}

// Resume flexible update if it was interrupted
@Override
protected void onResume() {
    super.onResume();
    appUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
        if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
            try {
                appUpdateManager.startUpdateFlowForResult(
                        appUpdateInfo,
                        AppUpdateType.FLEXIBLE,
                        this,
                        UPDATE_REQUEST_CODE);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        }
    });
}

Why the official API is better:

  • No fragile web scraping—Google handles all version checks
  • Supports multiple update strategies (flexible/immediate)
  • Automatically manages download, installation, and post-update flows
  • Avoids anti-scraping blocks from Google

内容的提问来源于stack exchange,提问作者Nir Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:39:48