如何在应用中同时使用Google Mobile Services和华为移动服务?
考虑到华为已丧失了GMS的许可,似乎我们需要用华为提供的服务来替换应用中使用的所有GMS服务。一个最佳实践是什么?使用flavors并以某种方式单独处理每个类别,还是复制粘贴项目并开始替换?或者更好的方法是,是否有一种方式可以同时拥有这两种服务,并让应用根据设备决定使用哪个服务?显然,后者将导致APK文件大小的增加。
有什么想法?
如何在应用中同时使用Google Mobile Services和华为移动服务?
考虑到华为已丧失了GMS的许可,似乎我们需要用华为提供的服务来替换应用中使用的所有GMS服务。一个最佳实践是什么?使用flavors并以某种方式单独处理每个类别,还是复制粘贴项目并开始替换?或者更好的方法是,是否有一种方式可以同时拥有这两种服务,并让应用根据设备决定使用哪个服务?显然,后者将导致APK文件大小的增加。
有什么想法?
所以,我是这样做的:
定义了两个风味
gms {
dimension "services"
buildConfigField "String", "SERVICE_USED", '"g"'
}
hms {
dimension "services"
buildConfigField "String", "SERVICE_USED", '"h"'
}
每当我需要决定执行某些操作时,我会在代码中使用"g"和"h",例如API需要deviceType
是"android"或"iOS",而且随着华为构建的加入,我们定义了另一个常量"huawei"。我使用SERVICE_USED
来确定要发送哪个常量。
接着我在build.gradle文件的顶部添加了以下内容:
apply plugin: 'com.android.application'
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Hms")) {
//*meh*
} else {
apply plugin: 'io.fabric'
}
由于我使用的是fabric(而fabric / firebase ...实际上无法与HMS一起使用),并且我也将其放在了build.gradle的最底部
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Hms")) {
apply plugin: 'com.huawei.agconnect'
} else {
apply plugin: 'com.google.gms.google-services'
}
只包括适当的插件。
然后,我开始处理使用(地图、位置、推送通知、分析)的每个内容,通过创建一个包装器并在每个flavour中分离代码。例如,对于推送通知,我创建了,它有一个方法。我在两个flavour中定义相同的类和方法,但根据服务类型(gms或hms)实现它们。
在项目中包含依赖项时,我使用这种类型的注释:
//GMS stuff
gmsImplementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
gmsImplementation 'com.google.firebase:firebase-core:16.0.9'
gmsImplementation 'com.google.firebase:firebase-messaging:18.0.0'
gmsImplementation 'com.google.firebase:firebase-crash:16.2.1'
gmsImplementation 'com.google.android.gms:play-services-maps:16.1.0'
gmsImplementation 'com.google.android.gms:play-services-location:16.0.0'
gmsImplementation 'com.google.android.gms:play-services-tagmanager:16.0.8'
//HMS stuff
hmsImplementation 'com.huawei.agconnect:agconnect-core:1.0.0.300'
hmsImplementation 'com.huawei.hms:push:4.0.3.301'
hmsImplementation 'com.huawei.hms:maps:4.0.1.301'
hmsImplementation 'com.huawei.hms:location:4.0.3.303'
Implementation
前的 gms
和 hms
是指味道的名称。只有在选择适当的 BuildVariant(即正在构建适当的 flavor )时,才会加载这些依赖项。
基本上,我为地图、分析、位置和推送通知两种情况下都封装了逻辑。以下是结构。没有什么特别的。
就是这样。他们创建 HMS 时基本上是逐个复制 GMS 的类和方法。你会看到确切的方法名称完全匹配,甚至包括调用参数和返回值。它们的相似度达到了99.99%。这使得事情更容易。基本上,你只需要将代码复制到两个类中,并导入正确的东西(在类的顶部)。你很少需要更改已经为 GMS 编写的代码。
希望对某些人有所帮助。
com.google.android.gms.common.api.ApiException
和com.google.android.gms.common.api.ResolvableApiException
的方法,这些方法是实现对话框所需的,该对话框已知来自谷歌地图,以在应用程序中打开GPS(无需重定向到设置)https://www.google.com/search?q=google+play+services+request+turn+on+gps&source=lnms&tbm=isch 当我检查华为“Petal Maps”时,只有警告显示GPS未启用,没有对话框可以在应用程序中打开它。因此,我不认为99.99%的相似性是正确的;) - mikep在回答您的问题之前,这里简单解释一下什么是HMS和GMS:
您可以将使用Google库的应用程序发布到华为的应用商店(名为AppGallery),但这个应用程序只适用于包含HMS+GMS(所有设备直到2020年都有HMS和GMS)的华为设备,其他设备无法看到。
然而,新款手机如Mate 30系列、P40等只安装了HMS。因此,如果您想使您的应用对所有华为设备可见(HMS+GMS和HMS),则必须在您的应用程序中实现检测用户设备上的哪种服务的功能。它将决定调用哪个正确的函数(例如初始化华为地图或谷歌地图的实例)。
对于华为移动服务,我们使用:
HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context);
我们使用以下 Google 移动服务:
https://developer.huawei.com/consumer/zh-cn/doc/development/HMS-References/huaweiapiavailability
GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
https://developers.google.com/android/reference/com/google/android/gms/common/GoogleApiAvailability
public static boolean isHmsAvailable(Context context) {
boolean isAvailable = false;
if (null != context) {
int result = HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context);
isAvailable = (com.huawei.hms.api.ConnectionResult.SUCCESS == result);
}
Log.i(TAG, "isHmsAvailable: " + isAvailable);
return isAvailable;
}
public static boolean isGmsAvailable(Context context) {
boolean isAvailable = false;
if (null != context) {
int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
isAvailable = (com.google.android.gms.common.ConnectionResult.SUCCESS == result);
}
Log.i(TAG, "isGmsAvailable: " + isAvailable);
return isAvailable;
}
据我所知,如果你实现了华为的开发工具包或谷歌的库,这些类(HuaweiApiAvailability/GoogleApiAvailability)将会可用。
HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context)
,只需要在项目中添加 implementation 'com.huawei.hms:base:4.0.2.300'
并将 maven {url 'http://developer.huawei.com/repo/'}
加入到仓库中即可。 - cosicreturn HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context) == ConnectionResult.SUCCESS
。 - Jorn Rigter尽管这取决于您的应用程序架构,但到目前为止有两个合理的替代方案:
需要将google
和huawei
设置为productFlavors
,然后作为sourceSets
进行设置。
build.gradle
根项目:
buildscript {
repositories {
google()
mavenCentral()
maven { url "https://developer.huawei.com/repo/" }
}
dependencies {
classpath "com.android.tools.build:gradle:7.2.2"
classpath "com.google.gms:google-services:4.3.13"
classpath "com.huawei.agconnect:agcp:1.7.0.300"
}
}
模块build.gradle
:
plugins {
id "com.android.application"
id "androidx.navigation.safeargs"
}
def json_huawei_release = "src/huaweiRelease/agconnect-services.json"
def json_huawei_debug = "src/huaweiDebug/agconnect-services.json"
def json_google = "src/google/google-services.json"
if (getGradle().getStartParameter().getTaskRequests().toString().contains('Huawei')) {
if (project.file(json_huawei_debug).exists() || project.file(json_huawei_release).exists()) {
apply plugin: "com.huawei.agconnect"
}
}
if (getGradle().getStartParameter().getTaskRequests().toString().contains('Google')) {
if (project.file(json_google).exists()) {
println "found: ${project.file(json_google)}"
apply plugin: "com.google.gms.google-services"
apply plugin: "com.google.firebase.crashlytics"
} else {
println "missing: ${project.file(json_google)}"
}
}
android {
...
flavorDimensions "vendor"
productFlavors {
google {
dimension "vendor"
versionNameSuffix "-google"
}
huawei {
dimension "vendor"
versionNameSuffix "-huawei"
}
}
sourceSets {
google {
java.srcDirs = ['src/main/java', 'src/google/java']
}
huawei {
java.srcDirs = ['src/main/java', 'src/huawei/java']
}
}
}
dependencies {
/** Google Play Services */
googleImplementation "com.google.android.gms:play-services-base:18.0.1"
googleImplementation "com.google.android.gms:play-services-basement:18.0.0"
googleImplementation "com.google.android.gms:play-services-auth:20.0.0"
googleImplementation "com.google.android.gms:play-services-identity:18.0.0"
googleImplementation "com.google.android.gms:play-services-oss-licenses:17.0.0"
/** Google Firebase */
googleImplementation "com.google.firebase:firebase-auth:21.0.1"
googleImplementation "com.google.firebase:firebase-database:20.0.3"
googleImplementation "com.google.firebase:firebase-messaging:23.0.0"
googleImplementation "com.google.firebase:firebase-functions:20.0.1"
googleImplementation "com.google.firebase:firebase-crashlytics:18.2.6"
googleImplementation "com.google.firebase:firebase-analytics:20.0.2"
googleImplementation "com.google.firebase:firebase-perf:20.0.4"
// googleImplementation "com.firebaseui:firebase-ui-auth:8.0.0"
/** Huawei Mobile Services */
huaweiImplementation "com.huawei.hms:base:6.1.0.302"
huaweiImplementation "com.huawei.hms:push:6.1.0.300"
huaweiImplementation "com.huawei.hms:hianalytics:6.3.0.300"
/** Huawei AppGallery Connect */
huaweiImplementation "com.huawei.agconnect:agconnect-core:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-auth:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-remoteconfig:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-function:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-cloud-database:1.5.2.300"
huaweiImplementation "com.huawei.agconnect:agconnect-applinking:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-crash:1.6.5.300"
huaweiImplementation "com.huawei.agconnect:agconnect-apms:1.5.2.309"
huaweiImplementation "com.huawei.agconnect:agconnect-storage:1.5.0.100"
huaweiImplementation "com.huawei.agconnect:agconnect-appmessaging:1.6.5.300"
}
这允许为所有内容提供自定义实现;它将构建两个不同的构件。
在测试时需要考虑切换构建变体和测试设备 - 但可以在IDE运行配置中传递任务名称和设备序列号(以便在正确的测试设备上运行正确的构建变体)。
安德烈博格丹(@AndreiBogdan)和deadfish(@deadfish)的回答都是正确的。我想再补充一下:
首先,您需要根据应用程序场景和开发/测试成本选择适当的解决方案(G+H或G2H)。
如果您选择G2H解决方案,则兼容性测试的工作量较小。您只需要在华为手机上测试新的APK即可。使用不同的包在HUAWEI AppGallery和Google Play上发布您的应用程序。在AppGallery上发布的应用程序仅包含华为的逻辑代码。您可以参考AndreiBogdan(@AndreiBogdan)的答案,或查看文档支持多个渠道。
正如captaink(@captaink)所说,您可以使用HMS Toolkit Convertor。它支持G+H和G2H转换。目前,HMS Toolkit支持Java和Kotlin。支持的Android Studio版本:3.3.2~4.1。