React Native: сопоставить несколько URL Maven с конкретными зависимостями? - PullRequest
3 голосов
/ 20 июня 2019

Пожалуйста, не отмечайте это как дубликат. Я потратил два дня на изучение Github, Stack, документов для Android Studio, RN и Gradle, чтобы найти ответ.

Проблема

Наш проект React Native не будет основываться на Android. Одна ошибка сборки

Could not find com.github.wix-playground:ahbottomnavigation:2.4.9

Исправление для этой ошибки - добавление maven { url 'https://jitpack.io' } к проекту build.gradle

Однако, добавив это, мы получаем вторую ошибку, которая

Execution failed for task ':react-native-ble-plx:compileDebugJavaWithJavac'

Исправление для этого добавляет maven { url 'https://maven.google.com' } к build.gradle

Но после добавления этого второго исправления мы снова вызываем первую ошибку.

Вопрос

Есть ли способ перечислить оба maven { <url> } в build.gradle таким образом, чтобы каждый maven { <url> } использовался только для конкретной зависимости, зависящей от него?

OR

Можем ли мы заставить одну и ту же версию библиотеки поддержки для всех зависимостей?

  • Я испробовал множество методов из этих Gradle Docs
  • Я попробовал ответ в этом Stack Post
  • Я обновился до Android Studio 3.4.1

Любая помощь будет принята с благодарностью.

Наши файлы

Уровень проекта build.gradle

buildscript {
    repositories {
        google()
        mavenLocal()
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.1'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        mavenLocal()
        // maven { url 'https://maven.google.com' }
        maven { url 'https://jitpack.io' }     
        maven {
          url "$rootDir/../node_modules/react-native/android" // This URL still works
        }
    }
}
  ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 19
        compileSdkVersion = 26
        targetSdkVersion = 26
        supportLibVersion = "28.0.0"
    }

    subprojects { subproject ->
    afterEvaluate {
        if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
            android {
                variantFilter { variant ->
                    def names = variant.flavors*.name
                    if (names.contains("reactNative51") || names.contains("reactNative56")) {
                        setIgnore(true)
                    }
                }
            }
        }
    }
}

app/build.gradle

buildscript {
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }
    dependencies {
        classpath 'io.fabric.tools:gradle:1.+'
    }
}

apply plugin: "com.android.application"
apply plugin: "io.fabric"
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

import com.android.build.OutputFile

project.ext.react = [
    entryFile: "index.js",
    bundleInStaging: true,
    devDisabledInStaging: true,
    inputExcludes: ["ios/**", "__tests__/**", "bundle_out/**"]
]

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

def enableSeparateBuildPerCPUArchitecture = false

def enableProguardInReleaseBuilds = false

def debugKeystorePropertiesFile = rootProject.file("keystores/debug.keystore.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(debugKeystorePropertiesFile))

def releaseKeystorePropertiesFile = rootProject.file("keystores/release.keystore.properties");
def releaseKeystoreProperties = new Properties()
releaseKeystoreProperties.load(new FileInputStream(releaseKeystorePropertiesFile))

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "com.example"
        missingDimensionStrategy "RNN.reactNativeVersion", "reactNative55"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 177
        versionName "2.0.4"
        multiDexEnabled true
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
        manifestPlaceholders = [
            FABRIC_API_KEY: project.env.get("FABRIC_API_KEY"),
            FABRIC_SECRET: project.env.get("FABRIC_SECRET")
        ]
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    signingConfigs {
        debug {
            storeFile file(keystoreProperties['key.store'])
            storePassword keystoreProperties['key.store.password']
            keyAlias keystoreProperties['key.alias']
            keyPassword keystoreProperties['key.alias.password']
        }
        release {
            storeFile file(releaseKeystoreProperties['key.store'])
            storePassword releaseKeystoreProperties['key.store.password']
            keyAlias releaseKeystoreProperties['key.alias']
            keyPassword releaseKeystoreProperties['key.alias.password']
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro", "proguard-devsupport.pro"
            testProguardFile 'proguard-debug.pro'
        }
        staging {
            signingConfig signingConfigs.debug
            matchingFallbacks = ['release', 'debug']
        }
        debug {
            signingConfig signingConfigs.debug
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def versionCodes = ["armeabi-v7a":1, "x86":2]
            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
            }
        }
    }
}

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support' && requested.name != 'multidex') {
            details.useVersion "${rootProject.ext.supportLibVersion}"
        }
    }
}

dependencies {
    compile('com.google.android.gms:play-services-gcm:11.8.0') {
        force = true
    }
    compile project(':react-native-push-notification')
    implementation project(':react-native-awesome-card-io')
    implementation project(':react-native-fabric')
    implementation project(':react-native-randombytes')
    implementation project(':react-native-linear-gradient')
    implementation project(':react-native-spinkit')
    implementation project(':react-native-keychain')
    implementation project(':react-native-vector-icons')
    implementation project(':react-native-ble-plx')
    implementation project(':react-native-config')
    implementation project(':react-native-sentry')
    implementation project(':react-native-device-info')
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.0.0-alpha3'
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.android.support:appcompat-v7:27.1.0"
    implementation 'com.android.support:design:27.1.0'
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation('com.crashlytics.sdk.android:crashlytics:2.9.3@aar') {
        transitive = true;
    }
    implementation project(':react-native-navigation')
    implementation project(':react-native-tcp')
    implementation 'com.android.support:design:25.4.0'
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation 'com.android.support:multidex:1.0.3'
    implementation ('com.github.wix-playground:ahbottomnavigation:2.4.9') {
        exclude group: "com.android.support"
    }
}

task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!-- < Only if you're using GCM or localNotificationSchedule() > -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <permission
        android:name="${applicationId}.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
    <!-- < Only if you're using GCM or localNotificationSchedule() > -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application
      android:name="android.support.multidex.MultiDexApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:fullBackupContent="false"
      android:theme="@style/AppTheme">

        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_channel_name"
            android:value="YOUR NOTIFICATION CHANNEL NAME"/>
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_channel_description"
            android:value="YOUR NOTIFICATION CHANNEL DESCRIPTION"/>
        <!-- Change the resource name to your App's accent color - or any other color you want -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
            android:resource="@android:color/white"/>

        <!-- < Only if you're using GCM or localNotificationSchedule() > -->
        <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="${applicationId}" />
            </intent-filter>
        </receiver>
        <!-- < Only if you're using GCM or localNotificationSchedule() > -->

        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>

        <!-- < Only if you're using GCM or localNotificationSchedule() > -->
        <service
            android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerServiceGcm"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>

      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustPan">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <meta-data
        android:name="io.fabric.ApiKey"
        android:value="${FABRIC_API_KEY}"
      />
      <meta-data
        android:name="io.fabric.ApiSecret"
        android:value="${FABRIC_SECRET}"
       />
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Есть ли способ перечислить оба maven {} в build.gradle таким образом, что каждый maven {} используется только для конкретной зависимости, зависящей от него?

Сопоставление репозиториев с зависимостями является инкубационной функцией.

В настоящее время вы можете проверить официальный документ об определении множественного репо:

Вы можете определить более одного репозитория для разрешения зависимостей. Объявление нескольких репозиториев полезно, если некоторые зависимости доступны только в одном репозитории, но не доступны в другом.

Порядок объявления определяет, как Gradle будет проверять зависимости во время выполнения. Если Gradle найдет дескриптор модуля в определенном хранилище, он попытается загрузить все артефакты для этого модуля из того же хранилища. Вы можете узнать больше о внутренней работе механизма разрешения Gradle.

Также

Можем ли мы принудительно установить одну и ту же версию библиотеки поддержки для всех зависимостей?

Вы можете:

  • Исключить конфликтующий модуль / библиотеку из одной из зависимостей
  • явно объявить версию библиотеки поддержки

например: например:

  implementation "your dependency:$version" {
       exclude group: "org.xxxx.xxx", module: "xxxxxxx"
   }

например:

android {
    configurations.all {
        resolutionStrategy.force 'com.android.support:support-xxxx:XX.YY.ZZ'
    }
}

Обратите внимание на этот подход, поскольку в некоторых библиотеках вы можете использовать обратную версию.

0 голосов
/ 21 июня 2019

Мы использовали стратегию разрешения (см. Комментарий выше), чтобы исправить нашу проблему. Кроме того, в нашем app/build.gradle мы решили не использовать androidx поддержки библиотек и вместо этого использовали старые com.android.support:xxx библиотеки. В итоге решение выглядело примерно так.

app/build.gradle

// Force the same support library version across all dependencies
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support' && requested.name != 'multidex') {
            details.useVersion "${rootProject.ext.supportLibVersion}"
        }
    }
}

implementation 'com.android.support:design:25.4.0'
implementation 'com.android.support:appcompatv7:${rootProject.ext.supportLibVersion}'
...