2

I have just converted my app into an instant app, the thing is that it has a setup that is a little complex, since I have 3 dimensions:

  1. experience

      - instant
      - installed
    
  2. type

      - demo
      - controlled
      - user
    
  3. adjustment

      - normal
      - perf
    

so the conversion process to instant app was not straight forwards, had to add some gradle code to ignore some permutations of flavors, to setup source and manifest location for build variants, deal with deep links in activities in different manifests and a series of issues I've managed to tackle down. Everything seems to work fine, except firebase.

I'm trying to understand how firebase routes the google-services.json file, how to set a different location or how to make it work repeating the file or something.

When I add firebase and add the google-services.json file to the installed directory I get the following error:

File google-services.json is missing. The Google Services Plugin cannot

function without it. 
 Searched Location: 
myapp_project/base/src/feature/instant/user/normal/release/google-services.json
... and so on with other flavors and combinations

This doesn't make too much sense to me since the directory tree structure is not well formed. My directory tree is as follows:

- myapp_project
   - base
      - src
          - controlled
          - demo
          - main
          - user
          - userNormal
          - userPerf
   - installed
   - instant 

I have tried creating the directories asked for, and adding the file in all of them. It then compiles perfectly, but it doesn't connect to firebase. Update on this matter, I realized that gradle searched for the file in many directories but among them was my "base" directory so just added the google-services.json file there and now compiles without the need of creating a file per directory. I'm also changing the package string inside the file to .base so that it doesn't throw the package not found error. But, it still compiles well but silently fails to connect to firebase server.

base gradle file

apply plugin: 'com.android.feature'
apply plugin: 'kotlin-android'

import org.apache.tools.ant.taskdefs.condition.Os

android {

    baseFeature true

    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
        testInstrumentationRunner 
        "android.support.test.runner.AndroidJUnitRunner"
    }

    def keystoreProperties = Os.isFamily(Os.FAMILY_WINDOWS) ?
        "KeyStoreWin.properties" : "KeyStore.properties"
    Properties props = new Properties()
    props.load(new FileInputStream(file(project.property(keystoreProperties))))

    signingConfigs {
        storeSignature {
            storeFile file(props['KEYSTORE'])
            storePassword props['KEYSTORE_PASSWD']
            keyAlias props['KEYSTORE1']
            keyPassword props['KEYSTORE_PASSWD1']
        }
    }

    buildTypes {
        debug {
            debuggable true
        }
        release {
            signingConfig signingConfigs.storeSignature
            debuggable false
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            renderscriptDebuggable false
        }
     }

     flavorDimensions "experience", "type", "adjustment"
     productFlavors {
         instant {
             dimension "experience"
             versionCode 1
         }
         installed {
             dimension "experience"
             versionCode 2
         }
         user {
             dimension "type"
         }
         demo {
             dimension "type"
         }
         controlled {
             dimension "type"
         }
         normal {
             dimension "adjustment"
         }
         perf {
             dimension "adjustment"
         }
     }

     variantFilter { variant -> def names = variant.flavors*.name
         if (names.contains("controlled") && names.contains("perf")) {
             setIgnore(true)
         }
         if (names.contains("demo") && names.contains("perf")) {           
             setIgnore(true)
         }
         if (names.contains("user") && names.contains("perf") &&
            variant.buildType.name == 'debug') {       
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("perf")) {
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("demo")) {           
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("controlled")) {
             setIgnore(true)
         }
    }

    sourceSets {
        instantUserNormal {
            java.srcDirs = ['src/userNormal/java', 'src/userNormal/java/']
            res.srcDirs = ['src/userNormal/res', 'src/userNormal/res/']
            manifest.srcFile 'src/userNormal/AndroidManifest.xml'
        }
        installedUserNormal {
            java.srcDirs = ['src/userNormal/java', 'src/userNormal/java/']
            res.srcDirs = ['src/userNormal/res', 'src/userNormal/res/']
            manifest.srcFile 'src/userNormal/AndroidManifest.xml'
        }
        installedUserPerf {
            java.srcDirs = ['src/userPerf/java', 'src/userPerf/java/']
            res.srcDirs = ['src/userPerf/res', 'src/userPerf/res/']
            manifest.srcFile 'src/userPerf/AndroidManifest.xml'
        }
    }
    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    packagingOptions {
        exclude 'META-INF/proguard/androidx-annotations.pro'
    }
}

repositories {
    google()
    maven { url "https://jitpack.io" }
    mavenCentral()
}


dependencies {
   implementation fileTree(include: ['*.jar'], dir: 'libs')
   ... all dependencies here
}

apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.gms.google-services'

installed gradle:

import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'

    defaultConfig {
         applicationId "com.domain.myapp"
         minSdkVersion 21
         targetSdkVersion 28
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    def keystoreProperties = Os.isFamily(Os.FAMILY_WINDOWS) ?
        "KeyStoreWin.properties" : "KeyStore.properties"
    Properties props = new Properties()
    props.load(new 
    FileInputStream(file(project.property(keystoreProperties))))

    signingConfigs {
        storeSignature {
            storeFile file(props['KEYSTORE'])
            storePassword props['KEYSTORE_PASSWD']
            keyAlias props['KEYSTORE_UPS']
            keyPassword props['KEYSTORE_UPS_PASSWD']
        }
    }

    buildTypes {
        debug {
            debuggable true
            versionNameSuffix "v1d"
        }
        release {
            signingConfig signingConfigs.storeSignature
            debuggable false
            versionNameSuffix "v1r"
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            renderscriptDebuggable false
        }
    }

    flavorDimensions "experience", "type", "adjustment"
    productFlavors {
        instant {
           dimension "experience"
        }
        installed {
           dimension "experience"
        }
        user {
           dimension "type"
        }
        demo {
           dimension "type"
           applicationIdSuffix ".demo"
        }
        controlled {
           dimension "type"
           applicationIdSuffix ".controlled"
        }
        normal {
           dimension "adjustment"
        }
        perf {
           dimension "adjustment"
        }
    }

    variantFilter { variant -> def names = variant.flavors*.name
         if (names.contains("controlled") && names.contains("perf") {
             setIgnore(true)
         }
         if (names.contains("demo") && names.contains("perf")) {            
             setIgnore(true)
         }
         if (names.contains("user") && names.contains("perf") && variant.buildType.name == 'debug') {
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("perf")) {
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("demo")) {         
             setIgnore(true)
         }
         if (names.contains("instant") && names.contains("controlled")) {
             setIgnore(true)
         }
    }

    packagingOptions {
            exclude 'META-INF/proguard/androidx-annotations.pro'
    }
}

repositories {
    google()
    maven { url "https://jitpack.io" }
    mavenCentral()
}

dependencies {
     implementation project(':base')
}

Update2 my logs show the following errors:

E/FA: GoogleService failed to initialize, status: 10, Missing google app id value from from string resources with name google_app_id.
E/FA: Missing google_app_id. Firebase Analytics disabled. See https....

However the google_app_id is present at the build directory auto-generated values.xml file for every build variant

How can I resolve this issue?

UPDATE3 SOLVED I had to apply the firebase pluggin twice in the base and installed gradle files. As shown in the post shared in one of the comments.

apply plugin: 'com.google.gms.google-services'
alexm
  • 1,285
  • 18
  • 36
  • 1
    Have you seen https://stackoverflow.com/a/47639585/6668797 ? – TWL Nov 26 '18 at 19:20
  • that was it, I tried so many gradle setups, I don't know why I did not try that specific apply pluggin repeated. That solved my problem. add it as an answer if you wish so I select your answer – alexm Nov 26 '18 at 20:02

1 Answers1

1

The plugin is telling you where it is searching for the google-services.json files. Are you able to place the correct files in the locations that are specified? It is okay to have the same or different google-services.json file in different variants.

dazza5000
  • 7,075
  • 9
  • 44
  • 89
  • Yes, I have done that, I've placed the google-services.json file in the directories it asks me, as well as in the base one. Proof of that is that I'm able to assemble a release without the file not found error. The problem is that any ways it won't connect to the cloud. – alexm Nov 26 '18 at 12:33
  • I'm trying to understand more to the bone how the firebase integration works, I'm thinking the problem is related to the complex flavor/dimension setup together with the instant app feature config. Please let me know if something else comes to your mind. Since what you say was part of the problem initially I'm giving you an up vote. – alexm Nov 26 '18 at 13:24
  • 1
    Can you please provide logs from when you app starts up so that we can see what the exception is? This might indicate why the app is unable to "connect to the cloud" – dazza5000 Nov 26 '18 at 14:13
  • the only log I get from firebase is this: E/FA: Missing google_app_id. Firebase Analytics disabled. See https.... isn't this id autogenerated? – alexm Nov 26 '18 at 16:43
  • this line shows before the log in my previous comment "E/FA: GoogleService failed to initialize, status: 10, Missing google app id value from from string resources with name google_app_id." Btw. the google_app_id string is present at values generated in the build directory, for every variant – alexm Nov 26 '18 at 16:52