passbase / rn-passbase

Passbase React Native Package
MIT License
3 stars 2 forks source link

Gradle sync fails with OneSignal installed #2

Closed mfkrause closed 4 years ago

mfkrause commented 4 years ago

I'm currently trying to integrate Passbase into our RN app. While iOS worked flawlessly using the documentation, I've been stuck with a Gradle error for the past four hours or so now that I simply cannot seem to fix unfortunately.

We're using React Native 0.61.5 and the latest rn-passbase (master).

I followed the Android-specific instructions from the documentation, and these are the errors I now get with every Gradle sync:

ERROR: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com.google.android.gms:play-services-location:[15.0.0, 16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com.google.firebase:firebase-iid:[18.0.0].
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com.google.android.gms:play-services-basement:[15.0.1,16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not resolve com.google.android.gms:play-services-location:[15.0.0, 16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not resolve com.google.firebase:firebase-iid:[18.0.0].
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not resolve com.google.android.gms:play-services-basement:[15.0.1,16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@debugUnitTest/compileClasspath': Could not resolve com.google.firebase:firebase-iid:[17.0.4].
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@release/compileClasspath': Could not resolve com.google.android.gms:play-services-location:[15.0.0, 16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@release/compileClasspath': Could not resolve com.google.firebase:firebase-iid:[18.0.0].
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@release/compileClasspath': Could not resolve com.google.android.gms:play-services-basement:[15.0.1,16.0.0).
Show Details
Affected Modules: app

ERROR: Unable to resolve dependency for ':app@releaseUnitTest/compileClasspath': Could not resolve com.google.firebase:firebase-iid:[17.0.4].
Show Details
Affected Modules: app

I think I've narrowed this down to the fact that we're using OneSignal as well in our app. When I deactivate the OneSignal gradle wrapper in our gradle scripts, all of the errors pointing to the com.google.android.gms:play-services disappear, the com.google.firebaseerrors stay though. I didn't try to fully remove OneSignal yet though (setting OneSignal up in a RN app is a science for itself, so haven't been looking forward to doing this so far), but I'd suppose that all of the errors come fron using OneSignal and Passbase together.

This is our root build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 23
        compileSdkVersion = 28
        targetSdkVersion = 28
        kotlin_version = "1.3.21"
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.4.2")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://jitpack.io' }

        maven {
            // expo-camera bundles a custom com.google.android:cameraview
            url "$rootDir/../node_modules/expo-camera/android/maven"
        }

        maven { url 'http://maven.facetec.com' }
    }
}

And this is the build.gradle from the :app module:

/**
 * Needed by react-native-one-signal
 */
buildscript {
    repositories {
        maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal
    }
    dependencies {
        classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.1, 0.99.99]'
    }
}

apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'
/**
 * END Needed by react-native-one-signal
 */

apply plugin: "com.android.application"

import com.android.build.OutputFile

/**
 * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
 * and bundleReleaseJsAndAssets).
 * These basically call `react-native bundle` with the correct arguments during the Android build
 * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
 * bundle directly from the development server. Below you can see all the possible configurations
 * and their defaults. If you decide to add a configuration block, make sure to add it before the
 * `apply from: "../../node_modules/react-native/react.gradle"` line.
 *
 * project.ext.react = [
 *   // the name of the generated asset file containing your JS bundle
 *   bundleAssetName: "index.android.bundle",
 *
 *   // the entry file for bundle generation
 *   entryFile: "index.android.js",
 *
 *   // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
 *   bundleCommand: "ram-bundle",
 *
 *   // whether to bundle JS and assets in debug mode
 *   bundleInDebug: false,
 *
 *   // whether to bundle JS and assets in release mode
 *   bundleInRelease: true,
 *
 *   // whether to bundle JS and assets in another build variant (if configured).
 *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
 *   // The configuration property can be in the following formats
 *   //         'bundleIn${productFlavor}${buildType}'
 *   //         'bundleIn${buildType}'
 *   // bundleInFreeDebug: true,
 *   // bundleInPaidRelease: true,
 *   // bundleInBeta: true,
 *
 *   // whether to disable dev mode in custom build variants (by default only disabled in release)
 *   // for example: to disable dev mode in the staging build type (if configured)
 *   devDisabledInStaging: true,
 *   // The configuration property can be in the following formats
 *   //         'devDisabledIn${productFlavor}${buildType}'
 *   //         'devDisabledIn${buildType}'
 *
 *   // the root of your project, i.e. where "package.json" lives
 *   root: "../../",
 *
 *   // where to put the JS bundle asset in debug mode
 *   jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
 *
 *   // where to put the JS bundle asset in release mode
 *   jsBundleDirRelease: "$buildDir/intermediates/assets/release",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in debug mode
 *   resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in release mode
 *   resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
 *
 *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means
 *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
 *   // date; if you have any other folders that you want to ignore for performance reasons (gradle
 *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
 *   // for example, you might want to remove it from here.
 *   inputExcludes: ["android/**", "ios/**"],
 *
 *   // override which node gets called and with what additional arguments
 *   nodeExecutableAndArgs: ["node"],
 *
 *   // supply additional arguments to the packager
 *   extraPackagerArgs: []
 * ]
 */

project.ext.react = [
    entryFile: "index.js",
    enableHermes: false,  // clean and rebuild if changing
]

apply from: "../../node_modules/react-native/react.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.package"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 136
        versionName "2.0.2"
    }

    dexOptions {
        javaMaxHeapSize "6g"
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://facebook.github.io/react-native/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // https://developer.android.com/studio/build/configure-apk-splits.html
            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }

        }
    }
}

apply from: '../../node_modules/react-native-unimodules/gradle.groovy'

dependencies {
    implementation project(':react-native-vector-icons')
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.facebook.react:react-native:+"  // From node_modules

    addUnimodulesDependencies()

    if (enableHermes) {
        def hermesPath = "../../node_modules/hermes-engine/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
        implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

I've already tried every single solution from StackOverflow and GitHub issues from the OneSignal repos - disabling the Google Play services version check, changing the order of some implementations, etc... - to no avail.

Could anyone help with this?

maakle commented 4 years ago

Hi @mfkrause let us quickly try to reproduce this issue. We will get back to you soon with next steps. In the meantime you are more than invited to join our developer slack, where we can give you more adhoc support.

mfkrause commented 4 years ago

Thanks @mattk90! Just joined the Slack. I'm simultaneously also trying to set-up a minimal reproducible example to help with this.

/edit: Got it I think. Set-up the OneSignal example project according to this documentation ("Running Example Project"): https://documentation.onesignal.com/docs/react-native-sdk-setup Then, simply follow the steps in the Android-specific Passbase docs. Add the npm module, and edit the gradle script according to the docs. The gradle sync then fails for me with the same errors as above.

KamranKhankhail commented 4 years ago

@mfkrause following is the workaround to fix the conflict caused by both sdks.

Adding resolutionStrategy to the project level build.gradle inside the allProjects block as follows:

allprojects {
    repositories {
        // other repositories ...
        maven { url 'https://maven.google.com' } // THIS ONE ADDED FOR ONE-SIGNAL
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
        maven { url 'http://maven.facetec.com' }
    }
    configurations.all { // THIS BLOCK ADDED FOR ONE-SIGNAL & PASSBASE CONFLICTS
        resolutionStrategy {
            eachDependency { DependencyResolveDetails details ->
                if (details.requested.group == 'com.google.firebase') {
                    details.useVersion "+"
                }
                if (details.requested.group == 'com.google.android.gms') {
                    details.useVersion "+"
                }
            }
        }
    }
}

sync the project and then build and run.

mfkrause commented 4 years ago

Thanks a lot @KamranKhankhail, that indeed fixed it! Works fine now. Closing this.