我们在 Google Play 商店使用 beta staging。针对应用端的强制更新功能,我们希望检测我们的应用程序是来自 Google Play 商店的 beta stage 还是 production stage。这在 Android 应用程序中是否可行?
我们在 Google Play 商店使用 beta staging。针对应用端的强制更新功能,我们希望检测我们的应用程序是来自 Google Play 商店的 beta stage 还是 production stage。这在 Android 应用程序中是否可行?
目前无法检测应用程序是从Beta还是Production Track在Play商店上安装的。
假设您的应用程序将连接到您拥有的API - 您可以让API确定应用程序是Beta还是生产App。例如,在API上存储被认为是Prod应用程序的应用程序版本号,当应用程序连接到API时,它会将其版本号传递给API,并且API返回一个响应,其中是否为Prod(版本与其存储的版本匹配)或Beta App(它不匹配其存储的版本)。
但这有两个限制:
如果您对这两个限制感到满意,则只需要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));
}
}
如果您的应用程序版本名称({{link1:android:versionName
}})始终包含“beta”字符串以进行测试版发布,则可以在运行时检索软件包名称并进行检查。
使用{{link2:getPackageInfo()
}}方法检索{{link3:PackageInfo
}}对象,该对象具有versionName String字段。
另一种方法是使用android:versionCode
。例如,您可以决定您的测试版发布始终具有奇数版本代码,而生产发布始终具有偶数版本代码。您可以使用getPackageInfo()
检索版本代码,并根据此进行确定。
假设相同的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();
}
如果您的应用版本名称中带有"beta"或"staging",则可以使用getPackageInfo()
获取该信息,并使用正则表达式或indexOf
进行检查
context.packageManager.getPackageInfo(context.packageName, 0).versionName.indexOf("beta") >= 0