有没有可能检测出安卓应用是测试版还是正式版?

40

我们在 Google Play 商店使用 beta staging。针对应用端的强制更新功能,我们希望检测我们的应用程序是来自 Google Play 商店的 beta stage 还是 production stage。这在 Android 应用程序中是否可行?


12
嗯,我真的不想开始讨论,但是“我们想检测我们的应用程序是来自谷歌Play商店的测试版阶段还是正式发布阶段”有什么不清楚的地方呢? - Chris W.
你有没有找到好的解决方案?@longliveenduro - Hadas Kaminsky
1
很抱歉,@HadasKaminsky不行。 - Chris W.
有人找到了这个问题的解决方案吗? - j_d
这个问题还没有解决方案吗? - Just The Highlights
显示剩余2条评论
6个回答

5

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

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

但这有两个限制

  1. 当应用准备投入生产时,您需要更新API上的移动应用程序版本号。
  2. 移动应用程序将由其版本号而不是在Play商店上的Track来确定。

如果您对这两个限制感到满意,则只需要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

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

使用{{link2:getPackageInfo()}}方法检索{{link3:PackageInfo}}对象,该对象具有versionName String字段。

另一种方法是使用android:versionCode。例如,您可以决定您的测试版发布始终具有奇数版本代码,而生产发布始终具有偶数版本代码。您可以使用getPackageInfo()检索版本代码,并根据此进行确定。


9
如上面答案评论所述,你误解了我们的意图,我们不想为测试版和正式版分别建立不同的APK文件。 - Chris W.
2
这是一个非常糟糕的理由来对一个回答进行负评(无论是我的还是harvey_slash的),特别是当你在最初的请求中没有明确说明(而且现在仍然没有)。 - Nik
15
我认为对于任何使用过 Google Play beta 发布渠道的人来说,这一点非常清晰明了。 - Jayen

-3

假设相同的apk通常会从Beta推广到Production,Dizzy提出的建议需要调用一些外部API。

但是,你可以使用android HttpURLConnnection来检查Google Play商店中你自己的应用程序ID的详细信息,而不是设置和命中自己的后端API。

如果当前用户已经注册了Beta版,那么应用程序名称将显示为“App名称(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();
}

首先,这段代码中的URL存在一个拼写错误,“sore”应该改为“store”。 然后,如果您像本答案中所示发送一个简单的Get请求,那么您将收到来自您的生产环境的通常页面内容,没有任何测试文本等等。因此,这是错误的答案。 - Alexandro

-3

如果您的应用版本名称中带有"beta"或"staging",则可以使用getPackageInfo()获取该信息,并使用正则表达式或indexOf进行检查

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接