首页 文章

google-services.json用于不同的productFlavors

提问于
浏览
366

更新:不推荐使用GCM,请使用FCM

我正在按照Google Developers页面的指南here实施新的Google Cloud Messaging

我已成功运行并测试它 . 但我现在的问题是我有不同的productFlavors具有不同的applicationId / packageName和不同的GCM项目ID . google-services.json 必须放在 /app/google-services.json 而不是flavors文件夹中 .

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

22 回答

  • 8

    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);
    
  • 45

    我正在使用从这里创建的google-services.json文件:https://developers.google.com/mobile/add?platform=android&cntapi=gcm&cnturl=https:%2F%2Fdevelopers.google.com%2Fcloud-messaging%2Fandroid%2Fclient&cntlbl=Continue%20Adding%20GCM%20Support&%3Fconfigured%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数据 . 我无法正确格式化...

  • 9

    谷歌在播放服务插件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

  • 4

    UPDATE: 以下说明适用于一个Android Studio项目,该项目中包含一个Firebase项目和不同的Firebase应用程序 . 如果目标是在同一个Android Studio项目中的不同Firebase项目中为不同的Firebase应用程序提供不同的JSON文件,(或者如果你不相同的话)look here. .

    每个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控制台更容易,因为它们提供了一个单独的文件,包含了所有配置所需的一切 .

  • 2

    在这个问题上写了Medium post .

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

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

    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
    }
    

    EDIT: 使用 processDebugFlavorGoogleServices / processReleaseFlavorGoogleServices 任务以每个风味级别修改它 .

  • 0

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

    我在做什么:

    我有两种口味,每一种我都把相应的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
    }
    

    Limitation: 每次想要运行不同的风格时,你必须在gradle中手动更改 myFlavor (因为它是硬编码的) .

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

    Update, Another solution: one google-services.json for all the flavors:

    您还可以为每种风格添加不同的软件包名称,然后在google developer console中,您不必为每种风格创建两个不同的应用程序,而只需在同一个应用程序中创建两个不同的客户端 . 然后,您将只有一个包含两个客户端的 google-services.json . 当然,这取决于你如何分离,然后这个解决方案对你没有帮助 .

  • 3

    根据ahmed_khan_89的回答,你可以在产品口味中加入"copy code" .

    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 '.'
            }
        }
    }
    

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

  • 1

    我们为调试版本(* .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 .

  • 0

    1.) What does google-services.json really do?

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

    2.) How does google-services.json file affects your android studio project?

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

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

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

    3.) What to do, to make it done?

    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.) Where to put google-service.json file in your structure.

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

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

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

  • 3

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

    This blog post详细描述了它 .

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

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

  • 2

    基于@ZakTaccardi 's answer, and assuming you don' t想要两个版本的单个项目,将其添加到 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 . 替换您使用的名称的风味名称 .

  • 11

    我发现 google-services 插件对于想要添加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指南逐字复制示例代码,您似乎只需要它 . 以下是示例行:

    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);
    

    For Product Flavors

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

  • 415

    无需任何额外的gradle脚本 .

    谷歌开始在'android_client_info'的名称中添加不同的包名称 . 它在google-services.json中如下所示

    "android_client_info": {
          "package_name": "com.android.app.companion.dev"
        }
    

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

    • 有两种口味

    • 将新的dev flavor包添加到google analystics配置页面并下载google-services.json .

    • 请注意,在新配置文件中,您的两个flavor的包ID都在那里

    • 准备你的任何风味 .

    这就对了!..

  • 1

    更新:

    有关构建变体的Firebase设置,请参阅this blog,其中包含详细说明 .

  • 7

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

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

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

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

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

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

  • 4

    简化@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"
            }
          ]
    
        }
    
  • 3

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

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

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

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

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

  • 0

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

  • 1

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

  • 4

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

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

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

  • 3

    灵感来自上面的@ 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
    }
    
  • 38

    将你的“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'
                        }
                    }
                }
            }
        }
    

相关问题