繁体   English   中英

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

[英]Is it possible to detect that an android app is either a beta version or production version?

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

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

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

但这有 2 个限制

  1. 当应用准备投入生产时,您需要更新 API 上的移动应用版本号。
  2. 移动应用程序将取决于它们的版本号,而不是它们在 Play 商店中的轨道。

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

就像@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));
    }
}

如果您的应用程序的版本名称 ( android:versionName ) 始终包含用于测试版本的字符串“beta”,您可以在运行时检索包名称,并进行检查。

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

另一种方法是使用android:versionCode 例如,您可以决定您的 Beta 版本始终具有奇数版本代码,而生产版本始终具有偶数版本代码。 您可以使用getPackageInfo()来检索版本代码并基于此做出决定。

在您的应用程序版本名称中使用“beta”或“staging”,您可以使用getPackageInfo()获取它并使用 Regex 或indexOf检查

context.packageManager.getPackageInfo(context.packageName, 0).versionName.indexOf("beta") >= 0

假设相同的 apk 通常从 Beta 升级到生产,Dizzy 的答案表明需要调用某些外部 API 是要走的路。

但是,您无需设置并访问您自己的后端 API,您只需使用 android HttpURLConnnection来检查 Google Play 商店详细信息页面以获取您自己的应用程序 ID。

如果当前用户已注册 Beta,则应用名称将显示为“ App Name (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();
}

我们在Google Play商店中使用Beta登台。 对于应用程序方面的强制更新功能,我们要检测我们的应用程序是否来自Google Play商店的Beta阶段或生产阶段。 这在Android应用程序中可能吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM