it-swarm.dev

google-services.json用于不同的productFlavors

更新: _ gcm _ 不推荐使用 _ fcm _

我正在按照Google开发者网页上的指南实施新的Google云消息传递 此处

我已成功运行并测试它。但我现在的问题是我有不同的产品风格,不同的applicationId/packageName和不同的Google Cloud Messaging Project Id。 google-services.json必须放在/app/google-services.json而不是flavors文件夹中。

是否有任何方法可以使google-services.json配置与许多风格不同?

400
gentra

谷歌在播放服务插件2.0版本中包含了对风味的支持。从这个版本的gradle plugin com.google.gms:google-services:2.0.0-alpha3

你可以这样做

app/src/
    flavor1/google-services.json
    flavor2/google-services.json

插件3.0.0版在这些位置搜索json文件(考虑到你有一个flavor flavor1和一个构建类型debug):

/app/src/flavor1/google-services.json
/app/src/flavor1/debug/google-services.json
/app/src/debug/google-services.json
/app/src/debug/flavor1/google-services.json
/app/google-services.json

即使使用flavorDimensions,这对我也有用。我在一个方面有免费和付费,在另一个方面有Mock&Prod。我还有3个buildTypes:debug,release和staging。这就是我在FreeProd风格的项目中的样子:

enter image description here

Google-services.json文件的数量取决于项目的特征,但每个Google项目至少需要一个json文件。

如果你想了解这个插件对这些json文件的作用的更多细节,请点击: https://github.com/googlesamples/google-services/issues/54#issuecomment-165824720

链接到官方文档: https://developers.google.com/Android/guides/google-services-plugin

包含最新信息的博客文章: https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-Android-app-builds.html

并转到此处查看此插件的最新版本: https://bintray.com/Android/android-tools/com.google.gms.google-services/view

451
Yair Kukielka

更新: 以下说明适用于一个Android Studio项目,该项目中包含一个Firebase项目和不同的Firebase应用程序。如果目标是在同一Android Studio项目中的不同Firebase项目中为不同的Firebase应用程序提供不同的JSON文件,(或者如果您不知道有什么区别) 请查看此处。

每个Android应用程序ID(通常是程序包名称)需要一个Firebase应用程序。每个Gradle构建变体有一个应用程序ID是常见的(如果您使用Gradle构建类型和Gradle构建样式,这将很可能)


截至 Google Services 3.0 并使用 Firebase 没有必要为不同的风格创建不同的文件。如果您拥有相互组合的productFlavours和Build类型,那么为不同的风格创建不同的文件可能不明确或不直接。

在同一个文件中,您将拥有所有构建类型和风格所需的所有配置。

在Firebase控制台中,您需要为每个程序包名称添加一个应用程序。想象一下,你有2种风格(开发和实时)和2种构建类型(调试和发布)。根据您的配置,但您可能有4个不同的包名称,如:

  • com.stackoverflow.example(live - release)
  • com.stackoverflow.example.dev(live - dev)
  • com.stackoverflow.example.debug(debug - release)
  • com.stackoverflow.example.dev.debug(debug - dev)

您需要在Firebase控制台中使用4种不同的Android应用。 (在每一个上你需要为你正在使用的每台计算机添加SHA-1进行调试和实时)

当您下载google-services.json文件时,实际上它与您下载的应用程序无关,它们都包含与您的所有应用相关的相同信息。

现在,您需要在应用程序级别(app /)中找到此文件。

enter image description here

如果您打开该文件,您将看到如果包含所有包名称的所有信息。

痛点用作插件。为了使其正常工作,您需要在文件底部找到插件。所以这一行..

apply plugin: 'com.google.gms.google-services'

...需要位于app build.gradle文件的底部。

对于这里所述的大部分内容,它也适用于以前的版本。我从来没有为不同的配置提供不同的文件,但现在使用Firebase控制台更容易,因为它们提供了一个单独的文件,包含了所有配置所需的一切。

54
Sotti

在这个问题上写了 中等帖子

有一个类似的问题(使用BuildTypes而不是Flavors),并修复它就像这样。

利用Gradle的依赖管理系统。我创建了两个任务,switchToDebugswitchToRelease。要求运行assembleReleaseswitchToRelease也会运行。调试相同。

def appModuleRootFolder = '.'
def srcDir = 'src'
def googleServicesJson = 'google-services.json'

task switchToDebug(type: Copy) {
    def buildType = 'debug'
    description = 'Switches to DEBUG google-services.json'
    from "${srcDir}/${buildType}"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

task switchToRelease(type: Copy) {
    def buildType = 'release'
    description = 'Switches to RELEASE google-services.json'
    from "${srcDir}/${buildType}/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

afterEvaluate {
    processDebugGoogleServices.dependsOn switchToDebug
    processReleaseGoogleServices.dependsOn switchToRelease
}

编辑: 使用processDebugFlavorGoogleServices/processReleaseFlavorGoogleServices任务以在每个风味级别修改它。

38
ZakTaccardi

根据 ahmed_khan_89 的回答,你可以在产品口味中加入“复制代码”。

productFlavors {
    staging {
        applicationId = "com.demo.staging"

        println "Using Staging google-service.json"
        copy {
            from 'src/staging/'
            include '*.json'
            into '.'
        }
    }
    production {
        applicationId = "com.demo.production"

        println "Using Production google-service.json"
        copy {
            from 'src/production/'
            include '*.json'
            into '.'
        }
    }
}

然后您不必手动切换设置。

12
Kros C.S. Huang

好吧,我遇到了同样的问题,无法得到任何完美的解决方案。这只是一种解决方法。我想知道谷歌如何不考虑口味......?我希望他们能尽快提出更好的解决方案。

我在做什么:

我有两种口味,每一种我都放了相应的google-services.json:src/flavor1/google-services.jsonsrc/flavor2/google-services.json

然后在构建gradle中,根据flavor调整文件到app/目录:

Android {

// set build flavor here to get the right gcm configuration.
//def myFlavor = "flavor1"
def myFlavor = "flavor2"

if (myFlavor.equals("flavor1")) {
    println "--> flavor1 copy!"
    copy {
        from 'src/flavor1/'
        include '*.json'
        into '.'
    }
} else {
    println "--> flavor2 copy!"
    copy {
        from 'src/flavor2/'
        include '*.json'
        into '.'
    }
}

// other stuff
}

限制: 每次你想要运行不同的味道时,你必须在gradle中更改myFlavor手动(因为它是硬编码的)。

我尝试了很多方法来获得当前的构建风格,例如afterEvaluate close ...直到现在才能得到更好的解决方案。

更新,另一个解决方案:一个google-services.json用于所有口味:

您还可以为每种风格设置不同的软件包名称,然后在 google开发人员控制台 中,您不必为每种风格创建两个不同的应用程序,而只需在同一个应用程序中创建两个不同的客户端。那么你将只有一个google-services.json包含你的两个客户端。当然,这取决于你如何实现你的口味的后端。如果他们没有分开,那么这个解决方案对你没有帮助。

12
ahmed_khan_89

我正在使用从此处创建的google-services.json文件: https://developers.google.com/mobile/add?platform=Android&cntapi=gcm&cnturl=https:%2F%2Fdevelopers.google.com%2Fcloud -messaging%2Fandroid%2Fclient&cntlbl =继续%20添加%20GCM%20Support&%3F配置%3Dtrue

在JSON结构中有一个名为clients的JSON数组。如果您有多种口味,只需在此处添加不同的属性即可。

{
  "project_info": {
    "project_id": "PRODJECT-ID",
    "project_number": "PROJECT-NUMBER",
    "name": "APPLICATION-NAME"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:PROJECT-NUMBER:Android:HASH-FOR-FLAVOR1",
        "client_id": "Android:PACKAGE-NAME-1",
        "client_type": 1,
        "Android_client_info": {
          "package_name": "PACKAGE-NAME-1"
        }
      },
      "oauth_client": [],
      "api_key": [],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "cloud_messaging_service": {
          "status": 2,
          "apns_config": []
        },
        "appinvite_service": {
          "status": 1,
          "other_platform_oauth_client": []
        },
        "google_signin_service": {
          "status": 1
        },
        "ads_service": {
          "status": 1
        }
      }
    },
    {
      "client_info": {
        "mobilesdk_app_id": "1:PROJECT-NUMBER:Android:HASH-FOR-FLAVOR2",
        "client_id": "Android:PACKAGE-NAME-2",
        "client_type": 1,
        "Android_client_info": {
          "package_name": "PACKAGE-NAME-2"
        }
      },
      "oauth_client": [],
      "api_key": [],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "cloud_messaging_service": {
          "status": 2,
          "apns_config": []
        },
        "appinvite_service": {
          "status": 1,
          "other_platform_oauth_client": []
        },
        "google_signin_service": {
          "status": 1
        },
        "ads_service": {
          "status": 1
        }
      }
    }
  ],
  "client_info": [],
  "ARTIFACT_VERSION": "1"
}

在我的项目中,我使用相同的project-id,当我在上面的url中添加第二个包名时,谷歌为我提供了一个包含json-data中多个客户端的文件。

对不起,紧凑的JSON数据。我无法正确格式化...

8
Mark Martinsson

google-services.json文件不需要接收通知。只需为build.gradle文件中的每个flavor添加一个变量:

buildConfigField "String", "GCM_SENDER_ID", "\"111111111111\""

注册时使用此变量BuildConfig.GCM_SENDER_ID而不是getString(R.string.gcm_defaultSenderId):

instanceID.getToken(BuildConfig.GCM_SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
8
divonas

1.) google-services.json真的有用吗?

请关注此: https://stackoverflow.com/a/31598587/2382964

2.) google-services.json文件如何影响您的Android工作室项目?

请关注: https://stackoverflow.com/a/33083898/2382964

简而言之,如果您在项目中添加google-services.json,则必须在此路径中为debug变体添加一个自动生成的google-services文件夹

app/build/generated/res/google-services/debug/values/values.xml

3.) 怎么做才能完成?

project_level build.gradle中添加google-services依赖项,如果使用app_compact库,也可以使用version 3.0.0

// Top-level build.gradle file
classpath 'com.google.gms:google-services:2.1.2'

现在在app_level build.gradle中你必须在底部添加。

// app-level build.gradle file
apply plugin: 'com.google.gms.google-services'

4.) 在你的结构中放置google-service.json文件的位置。

情况1.)如果你没有build_flavor只是把它放在/app/google-service.json文件夹里面。

情况2.)如果您有多个build_flavor,并且您在app/src/build_flavor/google-service.json中放置了不同的google_services.json文件。

情况3.)如果您有多个build_flavor并且您在app/google-service.json中放置了单个google_services.json文件。

5
Tushar Pandey

我们为调试版本(* .debug)提供了不同的软件包名称,所以我想要一些基于flavor和buildType的东西,而不必在processDebugFlavorGoogleServices的模式中编写任何与风格相关的东西。

我在每种风格中创建了一个名为“google-services”的文件夹,其中包含调试版本和json文件的发行版本:

enter image description here

在gradle文件的buildTypes部分中,添加以下内容:

    applicationVariants.all { variant ->
            def buildTypeName = variant.buildType.name
            def flavorName = variant.productFlavors[0].name;

            def googleServicesJson = 'google-services.json'
            def originalPath = "src/$flavorName/google-services/$buildTypeName/$googleServicesJson"
            def destPath = "."

            copy {
                if (flavorName.equals(getCurrentFlavor()) && buildTypeName.equals(getCurrentBuildType())) {
                    println originalPath
                    from originalPath
                    println destPath
                    into destPath
                }
            }
    }

当您切换构建变体时,它会自动在您的应用程序模块的根目录下复制正确的json文件。

添加两个调用的方法,以获取build.gradle根目录下的当前flavor和当前构建类型

def getCurrentFlavor() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()

    Pattern pattern;

    if( tskReqStr.contains( "assemble" ) )
        pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
    else
        pattern = Pattern.compile("generate(\\w+)(Release|Debug)")

    Matcher matcher = pattern.matcher( tskReqStr )

    if( matcher.find() ) {
        println matcher.group(1).toLowerCase()
        return matcher.group(1).toLowerCase()
    }
    else
    {
        println "NO MATCH FOUND"
        return "";
    }
}

def getCurrentBuildType() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()

        if (tskReqStr.contains("Release")) {
            println "getCurrentBuildType release"
            return "release"
        }
        else if (tskReqStr.contains("Debug")) {
            println "getCurrentBuildType debug"
            return "debug"
        }

    println "NO MATCH FOUND"
    return "";
}

就是这样,您不必担心从gradle文件中删除/添加/修改flavor,它会自动获得调试或发布google-services.json。

4
FallasB

Firebase现在支持使用一个google-services.json文件的多个应用程序ID。

这篇博客文章 详细描述了它。

您将在Firebase中创建一个您将用于所有变体的父项目。然后,您可以在该项目的Firebase中为您拥有的每个应用程序ID创建单独的Android应用程序。

当您创建所有变体时,可以下载支持所有应用程序ID的google-services.json。如果单独查看数据(即崩溃报告)是相关的,您可以使用下拉列表切换。

4
bMcNees

更新:

有关构建变体的Firebase设置,请参阅 此博客 其中包含详细说明。

3
KayAnn

基于@ ZakTaccardi的答案,并假设您不希望两个版本都有一个项目,请将其添加到build.gradle文件的末尾:

def appModuleRootFolder = '.'
def srcDir = 'src'
def googleServicesJson = 'google-services.json'

task switchToStaging(type: Copy) {
    outputs.upToDateWhen { false }
    def flavor = 'staging'
    description = "Switches to $flavor $googleServicesJson"
    delete "$appModuleRootFolder/$googleServicesJson"
    from "${srcDir}/$flavor/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

task switchToProduction(type: Copy) {
    outputs.upToDateWhen { false }
    def flavor = 'production'
    description = "Switches to $flavor $googleServicesJson"
    from "${srcDir}/$flavor/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

afterEvaluate {
    processStagingDebugGoogleServices.dependsOn switchToStaging
    processStagingReleaseGoogleServices.dependsOn switchToStaging
    processProductionDebugGoogleServices.dependsOn switchToProduction
    processProductionReleaseGoogleServices.dependsOn switchToProduction
}

您需要拥有src/staging/google-services.jsonsrc/production/google-services.json文件。替换您使用的名称的风味名称。

3
bryant1410

无需任何额外的gradle脚本。

Google开始在“Android_client_info”名称中添加不同的软件包名称。它在google-services.json中如下所示

"Android_client_info": {
      "package_name": "com.Android.app.companion.dev"
    }

所以,以下步骤足以让不同的google-services.json选择。

  1. 有2种口味
  2. 将新的dev flavor包添加到google analystics配置页面并下载google-services.json。
  3. 请注意,在新配置文件中,您的两个flavor的包ID都在那里
  4. 准备你的任何风味。

这就对了!..

3
Rames Palanisamy

我发现 google-services plugin对于想要添加GCM的项目来说毫无用处。它只生成以下文件,只是将您的项目ID添加为字符串资源:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Your API key would be on the following line -->
    <string name="gcm_defaultSenderId">111111111111</string>
</resources>

如果您直接从 Cloud Messaging for Android guide逐字复制示例代码,您似乎只需要它。以下是示例行:

String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),              GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

如果您希望能够为不同的构建类型或产品风格切换API项目,您可以定义自己的常量,并在调用getToken() API时选择合适的常量。

private static final String SENDER_ID = "111111111111";
private static final String SANDBOX_SENDER_ID = "222222222222";

String token = instanceID.getToken(
        BuildConfig.DEBUG ? SENDER_ID : SANDBOX_SENDER_ID,
        GoogleCloudMessaging.INSTANCE_ID_SCOPE,
        null);

对于产品口味

上面的代码适用于在调试和发布版本之间切换。对于产品风格,您可以在Java源文件中定义不同的API密钥,并将文件放在相应的产品风格目录中。供参考: Gradle Build Variants

3
kjones

谷歌服务插件的目的是简化谷歌功能的集成。

因为它只从google-services.json文件中生成Android资源,所以过度复杂的gradle-logic否定了这一点。

因此,如果Google-docs没有说明特定Google功能需要哪些资源,我建议为每个相关的构建类型/风格生成JSON文件,查看插件生成的资源,然后手动放置这些资源进入各自的src/buildtypeORflavor/res目录。

之后删除对google-services插件和JSON文件的引用,您就完成了。

有关google-services gradle-plugin内部工作方式的详细信息,请参阅我的其他答案:

https://stackoverflow.com/a/33083898/433421

2
arne.jans

简化@Scotti的说法。您需要根据产品风格为特定项目创建具有不同包名称的Multiples应用程序。

假设您的项目是ABC,具有不同的产品风格X,Y,其中X的包名称为com.x,Y具有包名称com.y,然后在firebase控制台中,您需要创建项目ABC,您需要在其中创建2个应用程序包名称为com.x和com.y.然后你需要下载google-services.json文件,其中将有2个包含那些pacakges的客户端信息对象,你将会很高兴。

Json的片段就是这样的

{
  "client": [
    {
      "client_info": {
        "Android_client_info": {
          "package_name": "com.x"
        }

    {
      "client_info": {
        "Android_client_info": {
          "package_name": "com.y"
        }
      ]

    }
2
Sagar Devanga

嘿朋友也只寻找名称使用小写,然后你不会得到这个错误

1
Divyesh Jani

事实上,MyApp/app/目录中的一个google-services.json是好的,不需要带com.google.gms:google-services:3.0.0的aditional脚本。但要小心从应用程序目录google-services.json中删除文件MyApp/app/src/flavor1/res/以避免错误类型Execution failed for task ':app:processDebugGoogleServices'. > No matching client found for package

1
gigeos

你有很多味道,所以这意味着你会有很多不同的包ID,对吗?因此,只需转到设置/生成json文件的页面并为每个包名配置。所有这些都将添加到json文件中。

我现在懒得发布图片,但基本上:

配置文件时,您可以看到谷歌显示服务器API密钥+发件人ID。所有包装(口味)都一样

最后,您只需要一个json文件用于所有风格。

还有一个问题,你必须在注册获得注册令牌时进行测试,检查每种口味是否有区别。我不接触它,但它认为它应该是不同的。现在太晚了,我好困啊:)希望它有所帮助!

1
Lạng Hoàng

我目前在同一个应用程序包中使用两个GCM Project Id。我把我的第一个GCM项目的google-service.json但我从第一个切换到第二个只改变了SENDER_ID:

    String token = instanceID.getToken(SENDER_ID,GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

(此时我认为google-services.json不是强制性的)

0
ariostoi

将你的“google-services.json”文件分别放在app/src/flavors下,然后放在app的build.gradle中,在Android下添加以下代码

gradle.taskGraph.beforeTask { Task task ->
        if (task.name ==~ /process.*GoogleServices/) {
            Android.applicationVariants.all { variant ->
                if (task.name ==~ /(?i)process${variant.name}GoogleServices/) {
                    copy {
                        from "/src/${variant.flavorName}"
                        into '.'
                        include 'google-services.json'
                    }
                }
            }
        }
    }
0
Sameer Khader

灵感来自上面的@ ahmed_khan_89答案。我们可以直接在gradle文件中保存。

Android{

// set build flavor here to get the right Google-services configuration(Google Analytics).
    def currentFlavor = "free" //This should match with Build Variant selection. free/paidFull/paidBasic

    println "--> $currentFlavor copy!"
    copy {
        from "src/$currentFlavor/"
        include 'google-services.json'
        into '.'
    }
//other stuff
}
0
Noundla Sandeep