Android get Google Play Store app version
Asked Answered
S

9

7

I am using this code to get the Google Play Store app version but this is causing my app to hang. Please specify another way to get the app version or how I can use this code to make the app not hang and run successfully.

public class VersionChecker extends AsyncTask<String, String, String> {

    private String newVersion;

    @Override
    protected String doInBackground(String... params) {

        try {
            newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + "trai.gov.in.dnd" + "&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[itemprop=softwareVersion]")
                    .first()
                    .ownText();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return newVersion;
    }
}

This is my code to get the app version from asynctask

VersionChecker versionChecker = new VersionChecker();
try {
    String appVersionName = BuildConfig.VERSION_NAME;
    String mLatestVersionName = versionChecker.execute().get();
    if (versionChecker.compareVersionNames(appVersionName, mLatestVersionName) == -1) {
        showAppUpdateDialog();
    }
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
Sarong answered 22/2, 2018 at 12:4 Comment(9)
its for an specific app ?Cocainize
Yes for an specific appSarong
Could you paste the code of the function which is calling this async task ?Cinnamon
how did you fix the compareVersionNames error?Biquarterly
Hello bro, are you still using asyntask until this day or did you already find an alternative on this since asyntask was already deprecated.Biquarterly
As of May 26th, 2022, Google has changed their Play Store page and have hidden the latest "Version" behind a clickable button that displays a modal. Instead of just parsing/scraping the page, we had to use a headless browser to click that button, display the modal and then parse the modal for the Version. What a PITA. If someone knows a better method, please share!Fay
@JoshuaPinter if you have found any new or working methods could you please share them? if not, could you please share the method you mentioned?Indigestible
@AbdulrahmanHasanato We ended up doing it on our back-end and our mobile app just pings our API to retrieve the latest version number instead. Was much easier to maintain that way.Fay
@JoshuaPinter Hmm, I'm actually using Firebase to store the newest version and compare it with the current version in the app 🤷🏼‍♂️Indigestible
D
7

Just replace your code

.get()
.select("div[itemprop=softwareVersion]")
.first()
.ownText();

with below:

.get()
.select(".hAyfc .htlgb")
.get(3)
.ownText();

it will work..!

Dive answered 30/3, 2018 at 11:4 Comment(2)
You need to use .get(5) now instead of .get(3), but this is the only thing I have found that works.Nadene
how did you fix the compareVersionNames error?Biquarterly
T
2

The problem arises because the element div [itemprop = softwareVersion] is no longer found on the Google Play website (therefore it no longer returns the version number), it should only be changed to a new query with the changes made by google on your website.

Note: Take into account that if the structure is changed again, this code must be changed.

I hope it helps

Update: 12/09/2019

public class VersionChecker extends AsyncTask<String, String, String> {

    @Override
    protected String doInBackground(String... params) {

        private String newVersion;

        try {
        Document document = Jsoup.connect("https://play.google.com/store/apps/details?id=" + "com.example.package" + "&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();
        if (document != null) {
            Elements element = document.getElementsContainingOwnText("Current Version");
            for (Element ele : element) {
                if (ele.siblingElements() != null) {
                    Elements sibElemets = ele.siblingElements();
                    for (Element sibElemet : sibElemets) {
                        newVersion = sibElemet.text();
                    }
                }
            }
        }
        return newVersion;
    }
}

Codigo Java

VersionChecker versionChecker = new VersionChecker();
try {
    String latestVersion = versionChecker.execute().get();
    String versionName = BuildConfig.VERSION_NAME.replace("-DEBUG","");
    if (latestVersion != null && !latestVersion.isEmpty()) {
        if (!latestVersion.equals(versionName)) {
            showDialogToSendToPlayStore();
        }else{
            continueWithTheLogin();
        }
    }
    Log.d("update", "Current version " + Float.valueOf(versionName) + ", Playstore version " + Float.valueOf(latestVersion));

} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}
Taimi answered 17/4, 2018 at 16:21 Comment(2)
Nice ! Your solution is better than the top one.Statant
What is showDialogToSendToPlayStore()? Should I add a library?Greensboro
H
2
  1. It seems you use the "app-version" shown on the Google Play Store website to trigger an "update popup" to your users and notify when a new version is available. First of all, Google Play Store website is changing often, so that's not very reliable as your app might not be able to "parse/handle" those changes. If you want to keep that approach, some other answers already explained how to parse the right HTML tag and how to do in the background correctly. Keep in mind your app will be still responsible for the "parsing", eventually you would do the parsing remotely on a web-server, and expose to your app a stable API endpoint to retrieve the "latest-version" of your own app. If you do not want to bother with parsing HTML tags or host your own API, there are third-party APIs that can do that for you. We provide one such API here: https://42matters.com/docs/app-market-data/android/apps/lookup (it returns a JSON object with the latest "version name" of the app).

  2. You could also use https://github.com/danielemaddaluno/Android-Update-Checker to not implement your own code, under the hood it does more or less the same as you do.

  3. Personally I would use a remote service like Firebase Remote Config https://firebase.google.com/docs/remote-config or a simple JSON file hosted on your website specifying the latest published version of your app (just remember to change it once the update of your app is really published on Google Play, nowadays it might take a while). Also, I would rather use the "versionCode" as explained here: https://developer.android.com/studio/publish/versioning With this approach you could "trigger" the update when you want, more control on your side (especially in case you want to revert the "Please update" message, useful if you find a bug in the latest version you published)

Halfbound answered 13/8, 2020 at 14:9 Comment(0)
H
0

Change this two lines

{
 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")
....

you are using BuildConfig.APPLICATION_ID but you need package_name

BuildConfig is provided by Gradle. If you are not building using Gradle then you cannot access the package name using BuildConfig.

I would use Context.getPackageName() because the result is provided from the operating system, rather than a constant in build parameters.

Hacienda answered 22/2, 2018 at 12:12 Comment(6)
Okay let me do and check.Sarong
you are doing this inside an asynctask ?Cocainize
It is still talking time for app to load.Sarong
Yes inside an async taskSarong
do you have internet permisions in your manifest ? can you post your error log ? thanksCocainize
I have internet permissions in manifest and there is no error. Its just that app takes time to load the activity.Sarong
N
0

You need to put it into AysncTask

 //********* Check for Updated Version of APP
    private class GetVersionCode extends AsyncTask<Void, String, String> {
        String currentVersion = null;

        @Override
        protected String doInBackground(Void... voids) {

            String newVersion = null;

            try {
                currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
                newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + Activity.this.getPackageName() + "&hl=it")
                        .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[itemprop=softwareVersion]")
                        .first()
                        .ownText();
                return newVersion;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String onlineVersion) {
            super.onPostExecute(onlineVersion);
            if (onlineVersion != null && !onlineVersion.isEmpty()) {
                if (!currentVersion.equalsIgnoreCase(onlineVersion)) {
                    //Todo code here

                }
            }
            Log.d("update", "Current version " + currentVersion + "playstore version " + onlineVersion);
        }
    }
Norseman answered 22/2, 2018 at 12:42 Comment(3)
hi, OP says that he have an asynctask already, check the comments in my asnwerCocainize
Ohh I see... Probably it will clear it if he is doing anything wrong in that.Norseman
No problem dude :)Cocainize
M
0

Google change the API from 'softwareVersion' to 'currentVersion' and we can get the same version using ".hAyfc .htlgb"

Below code will not work i.e.

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[itemprop=softwareVersion]").first().ownText();

Instead of above code just add this code, it will work fine i.e.

Document document = 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();
    if(document != null) {
        if(document.select(".hAyfc .htlgb").get(5) != null) {
            latestVersion = document.select(".hAyfc .htlgb").get(5).ownText();
        } else {
            latestVersion = currentVersion;
        }
    }

// Note: There is no official API to get the current application version from Google Play. So use the above code to get the current version. Sometimes get(5).ownText() will change as google is updating the Google Play site. [Previously it was working with get(2).ownText()].
Medici answered 2/5, 2018 at 17:17 Comment(0)
T
0

just try this,

Replace the code ,

                .get()
                .select("div:containsOwn(Current Version)")
                .next()
                .text();
Tamper answered 8/5, 2018 at 9:48 Comment(0)
C
0

You can achieve this much easier using UpdateManager - https://developer.android.com/reference/com/google/android/things/update/UpdateManager

You can setup your Update Manager as such

// Creates instance of the manager.
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(this);

// Returns an intent object that you use to check for an update.
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();

//On Success Listener
appUpdateInfoTask.addOnSuccessListener(this);

In your On Success method, you can call

result.availableVersionCode()

Which returns 0 when the version is not different. Which if it is different you can just pull this value from your app directly.

Corri answered 1/8, 2020 at 15:26 Comment(0)
C
0

Refer to my answer here, but we made a CLI to use the proper APIs to retrieve this information, instead of trying to web-scrape: https://mcmap.net/q/1480209/-programatically-getting-the-version-code-of-the-app-that-is-in-play-store.

Essentially, using the CLI in the above-mentioned comment, to get the next available versionCode, it is as simple as:

JSON=$(cat ~/path/to/key.json) && google-app-version next -f "$JSON" --package com.company.app
# 15

Or, for the current/latest release versionCode:

JSON=$(cat ~/key.json) && google-app-version latest -f "$JSON" -p com.company.app
# 14

Edit: link to GH repo: https://github.com/inspire-labs-tms-tech/google-play-app-version-code-cli

Cede answered 14/6, 2024 at 0:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.