簡體   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