是否可以检测Android应用程序是测试版本还是生产版本?

问题描述 投票:0回答:6

我们在 Google Play 商店中使用测试版。对于应用程序侧强制更新功能,我们希望检测我们的应用程序是来自 Google Play 商店的测试阶段还是生产阶段。这在 Android 应用程序中可能吗?

android google-play
6个回答
5
投票

目前无法检测该应用程序是从 Play 商店的 Beta 版还是 Production Track 安装的。

假设您的应用程序将连接到您拥有的 API - 您可以做的是让 API 确定该应用程序是 Beta 应用程序还是 Prod 应用程序。例如,在 API 上存储被视为 Prod 应用程序的应用程序版本号,当应用程序连接到 API 时,它将其版本号传递给 API,并且 API 返回一个响应,说明它是否是 Prod(版本匹配)已存储的应用程序)或 Beta 应用程序(与已存储的应用程序不匹配)。

但这有两个限制

  1. 您将需要更新 API 上的移动应用程序版本号 当应用程序准备好投入生产时。
  2. 移动应用程序将由版本号决定,而不是由版本号决定 跟踪它们在 Play 商店中的位置。

如果您对这 2 个限制感到满意,那么您将只有 1 个 APK 和一种确定您的应用是 Prod 还是 Beta 的方法。


2
投票

就像 @Jayen 所说,可以使用 Google AndroidPublisher Service API。请参阅以下示例代码(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));
    }
}


-2
投票

如果您的应用程序的版本名称 (

android:versionName
) 始终包含 beta 版本的字符串“beta”,您可以在运行时检索包名称并进行检查。

使用

getPackageInfo()
方法检索具有 versionName String 字段的
PackageInfo
对象。

另一种方法是使用

android:versionCode
。例如,您可以决定测试版本始终具有奇数版本代码,而生产版本始终具有偶数版本代码。您可以使用
getPackageInfo()
检索版本代码并据此做出决定。


-3
投票

应用程序版本名称中包含“beta”或“staging”,您可以使用

getPackageInfo()
获取它并使用正则表达式或
indexOf

进行检查
context.packageManager.getPackageInfo(context.packageName, 0).versionName.indexOf("beta") >= 0

-3
投票

假设相同的 apk 通常从 Beta 升级到 Production,Dizzy 的回答建议需要调用某些外部 API。

但是,您可以使用 android HttpURLConnnection 来检查 Google Play 商店详细信息页面以获取您自己的应用程序 ID,而不是设置并点击您自己的后端 API。

如果当前用户注册了 Beta,应用程序名称将显示为“应用程序名称(Beta)”。

页面再往下一点,它还会显示“您是此应用程序的 Beta 测试人员。太棒了!

该页面包含一个标有“安装”、“更新”或“已安装”的按钮,您可以从中确定用户是否拥有最新版本

在同一页面上,您的应用程序还可以查找上次生产更新日期和最新生产版本名称。

下面是有关如何实现此功能的示例 Java 代码:

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();
}
© www.soinside.com 2019 - 2024. All rights reserved.