Is it possible to detect that an android app is either a beta version or production version?
Asked Answered
T

6

42

We use beta staging in google play store. For app side force update functionality we want to detect if our app is either coming from the beta stage or the production stage of the google play store. Is this possible in android apps?

Taveras answered 18/7, 2014 at 7:32 Comment(7)
your question is unclear, but I still answered whatever I could make from itLast
Hm I really don't want to start a discussion, but what is unclear about "we want to detect if our app is either coming from the beta stage or the production stage of the google play store" exactly?Taveras
Did you ever find a good solution? @longliveenduroLocalism
@HadasKaminsky unfortunately notTaveras
I also need to determine this. We use the app version code to tell the user if they have the latest version. But we don't want it telling all our production users their app is out of date just because we launched a new beta.Boatsman
Anyone find a solution on this?Pinpoint
Is there still no solution for this?Barely
C
4

It's currently not possible to detect if the app was installed from either the Beta or Production Track on the Play Store.

Assuming your app will be connecting to an API that you own - What you can do is let the API determine if the App is a Beta or Prod App. For example store the app version number(s) that are considered a Prod app on the API, when the app connects to the API it passes it's version number to the API and the API returns a response with whether it is Prod (The version matches one it has stored) or Beta App (it's does not match one it has stored).

There are 2 Limitations to this though:

  1. You will need to update the mobile app version number(s) on your API when the app is ready to go to production.
  2. Mobile apps will be determined by their version number not what Track they are on in Play Store.

If you're happy with these 2 limitations then you will only have 1 APK and a means to determine if your app is Prod or Beta.

Cockpit answered 17/10, 2019 at 14:39 Comment(0)
S
2

Like @Jayen said, it is possible using the Google AndroidPublisher Service API. See the following sample code (in Java):

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.SecurityUtils;
import com.google.api.services.androidpublisher.AndroidPublisher;
import com.google.api.services.androidpublisher.AndroidPublisherScopes;
import com.google.api.services.androidpublisher.model.AppEdit;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Objects;
import java.util.Set;

public class AndroidPublisherService {

    private final AndroidPublisher service;

    /**
     * Constructs a GooglePlayService instance with the specified credentials.
     *
     * @param accountId
     * @param keyStoreInputStream
     * @param keyStorePassword
     * @param keyAlias
     * @param keyPassword
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public AndroidPublisherService(
            String accountId,
            InputStream keyStoreInputStream,
            String keyStorePassword,
            String keyAlias,
            String keyPassword
    ) throws GeneralSecurityException, IOException {
        // Specify info for your application 'CompanyName-ApplicationName/ApplicationVersion'
        // This is not part of the authentication, but sample code from Google specifies this.
        final String applicationName = "SomeCompany-SomeApplication/1.0";
        final JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        final HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        final var keyInputStream = Objects.requireNonNull(keyStoreInputStream);
        final var key = Objects.requireNonNull(SecurityUtils.loadPrivateKeyFromKeyStore(
                SecurityUtils.getPkcs12KeyStore(),
                keyInputStream,
                keyStorePassword,
                keyAlias,
                keyPassword
        ));
        var credentials = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(jsonFactory)
                .setServiceAccountId(accountId)
                .setServiceAccountScopes(Set.of(AndroidPublisherScopes.ANDROIDPUBLISHER))
                .setServiceAccountPrivateKey(key)
                .build();
        this.service = new AndroidPublisher.Builder(
                httpTransport, jsonFactory, credentials
        ).setApplicationName(applicationName).build();
    }

    /**
     * Checks whether the application with the specified packageName/versionCode is in the production lane or not.
     *
     * @param packageName The package name of the application
     * @param versionCode The version code of the application
     * @return true if the application is a test version (not in production lane), false otherwise.
     * @throws IOException
     */
    public boolean isTestVersion(String packageName, long versionCode) throws IOException {
        // Create the API service.
        final AndroidPublisher.Edits edits = service.edits();

        // Create a new edit to make changes.
        AndroidPublisher.Edits.Insert editRequest = edits
                .insert(packageName, null);
        AppEdit appEdit = editRequest.execute();

        // Get a list of apks.
        var tracksListResponse = edits
                .tracks()
                .list(packageName, appEdit.getId()).execute();
        return tracksListResponse.getTracks().stream()
                .filter(it -> !it.getTrack().equalsIgnoreCase("production"))
                .flatMap(it -> it.getReleases().stream())
                .anyMatch(it -> it.getVersionCodes().contains(versionCode));
    }
}
Scapula answered 27/5, 2021 at 8:36 Comment(0)
N
-2

If your application's version name (android:versionName) always contains the string "beta" for beta releases, you can retrieve the package name at runtime, and check that.

Use the getPackageInfo() method to retrieve a PackageInfo object which has a versionName String field.

Another approach would be to use the android:versionCode. For example, you could decide that your beta releases always have an odd version code, and production releases always have an even one. You could use getPackageInfo() to retrieve the version code and make your determination based on that.

Needlepoint answered 18/7, 2014 at 7:50 Comment(3)
as in the comments of the answers above, you misunderstood our intents, we don't want to have different apks for betas and prodTaveras
That's a terrible reason to downvote an answer (both mine, and harvey_slash's), especially when you don't spell that out in your original request (and still have not done so).Needlepoint
i think it's pretty clear to anyone who has used the beta distribution channel of google play.Blown
A
-3

With "beta" or "staging" in your app version name, you can get it with getPackageInfo() and check with a Regex or indexOf

context.packageManager.getPackageInfo(context.packageName, 0).versionName.indexOf("beta") >= 0
Ard answered 31/1, 2020 at 18:10 Comment(0)
R
-3

Assuming the same apk is typically promoted from Beta to Production, the answer by Dizzy suggesting that a call out to some external API is required is the way to go.

However, rather than setting up and hitting your own back-end API, you can just use an android HttpURLConnnection to check the Google Play store details page for your own app id.

If the current user is enrolled in Beta, the app name is presented as "App Name (Beta)".

A little further down the page it will also say "You're a beta tester for this app. Awesome!"

The page contains a single button labelled either "Install", "Update" or "Installed", from which you can determine whether or not the user has the latest version

On the same page your app can also look up the last production Updated date, and latest production version name.

Sample Java code for how you might implement this below:

boolean isBeta = false;
URL url = new URL("https://play.google.com/sore/apps/details?id=com.example.app");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
  InputStream in = new BufferedInputStream(urlConnection.getInputStream());
  Scanner scanner = new Scanner(in);
  isBeta = (scanner.findWithinHorizon("\\s\\(Beta\\)", 650000) != null);
} finally {
  urlConnection.disconnect();
}
Ricciardi answered 28/4, 2020 at 6:4 Comment(1)
First of all this piece of code contains a typo in url "sore"->"store". Then if you send a simple Get request like shown in this answer, then you will receive the content of the usual page from your production, without any beta text and so on and so for. So this is the wrong answer.Shimmery

© 2022 - 2024 — McMap. All rights reserved.