compileSdkVersion не указан во время конфигурации проекта ‘expo-camera’

Вопрос или проблема

При сборке моего приложения expo react-native я получаю ошибку сборки:

  • Где:
    Скрипт ‘/DELIBERATELY_HIDDEN/node_modules/expo-modules-autolinking/scripts/android/autolinking_implementation.gradle’ строка: 377

  • Что пошло не так:
    Произошла проблема при оценке проекта ‘:expo’.

Произошла проблема при настройке проекта ‘:expo-camera’.
Не удалось уведомить слушателя оценки проекта.
> com.android.builder.errors.EvalIssueException: compileSdkVersion не указан. Пожалуйста, добавьте его в build.gradle
> Не удалось получить неизвестное свойство ‘release’ для контейнера SoftwareComponent типа org.gradle.api.internal.component.DefaultSoftwareComponentContainer.

Я попробовал каждый ответ в каждом связанном посте, но это не помогло.

Я посмотрел на файлы build.gradle на уровне проекта android, уровне приложения android и уровне node_modules expo-camera, но они все указывают compileSdkVersion!

Я не хочу вносить изменения в node_modules, так как они будут удалены каждый раз, когда мне нужно будет переустановить их.

Раньше сборка проходила нормально с использованием версии expo-camera 14.1.3, react 18.2.0, react native 0.73.6 и expo 50.0.0, и я не менял эти версии.

Кстати, я также вижу следующее в вкладке проблем в VS Code, но подобные ошибки происходили и с другими модулями ранее, без вызова ошибок сборки:

Отсутствует папка конфигурации проекта Gradle: .settings

Вот мои файлы build.gradle:

Уровень проекта:

// Файл сборки верхнего уровня, где вы можете добавить параметры конфигурации, общие для всех подпроектов/модулей.

buildscript {
    ext {
        buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
        minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
        compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
        targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
        kotlinVersion = findProperty('android.kotlinVersion') ?: '1.8.10'

        ndkVersion = "25.1.8937393"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath('com.android.tools.build:gradle')
        classpath('com.facebook.react:react-native-gradle-plugin')
    }
}

apply plugin: "com.facebook.react.rootproject"

allprojects {
    repositories {
        maven {
            // Весь React Native (JS, Obj-C источники, Android бинарные файлы) установлен из npm
            url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
        }
        maven {
            // Android JSC установлен из npm
            url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist'))
        }

        google()
        mavenCentral()
        maven { url 'https://www.jitpack.io' }
        maven {
            // expo-camera включает пользовательский com.google.android:cameraview
            url "$rootDir/../node_modules/expo-camera/android/maven"
        }
    }
}

Уровень приложения:

apply plugin: 'com.android.application'
apply plugin: "com.facebook.react"

def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()

/**
 * Это блок конфигурации для настройки вашего Android-приложения React Native.
 * По умолчанию вам не нужно применять никакую конфигурацию, просто раскомментируйте нужные строки.
 */
react {
    entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
    reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
    hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
    codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()

    // Используйте Expo CLI для создания приложения, это гарантирует, что конфигурация Metro
    // работает правильно с проектами Expo.
    cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim())
    bundleCommand = "export:embed"

    /* Папки */
    //   Корень вашего проекта, то есть где находится "package.json". По умолчанию это '..'
    // root = file("../")
    //   Папка, где находится пакет react-native NPM. По умолчанию это ../node_modules/react-native
    // reactNativeDir = file("../node_modules/react-native")
    //   Папка, где находится пакет Codegen для react-native. По умолчанию это ../node_modules/@react-native/codegen
    // codegenDir = file("../node_modules/@react-native/codegen")

    /* Варианты */
    //   Список вариантов, которые можно отлаживать. Для них мы собираемся
    /* Упаковка */
    //   Список, содержащий команду node и ее параметры. По умолчанию это просто 'node'.
    // nodeExecutableAndArgs = ["node"]

    //
    //   Путь к файлу конфигурации CLI. По умолчанию пустой.
    // bundleConfig = file(../rn-cli.config.js)
    // hermesFlags = ["-O", "-output-source-map"]
}

/**
 * Установите это значение в true, чтобы запустить Proguard в релизных сборках для минификации байт-кода Java.
 */
def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean()

/**
 * Предпочтительный вариант сборки JavaScriptCore (JSC)
 *
 * Например, чтобы использовать международный вариант, вы можете использовать:
 * `def jscFlavor="org.webkit:android-jsc-intl:+"`
 *
 * Международный вариант включает библиотеку ICU i18n и необходимые данные,
 * позволяя использовать, например, `Date.toLocaleString` и `String.localeCompare`, которые
 * дают правильные результаты при использовании с локалями, отличными от en-US. Обратите внимание,
 * что этот вариант на 6 МиБ больше на архитектуру, чем по умолчанию.
 */
def jscFlavor="org.webkit:android-jsc:+"

apply plugin: "org.jetbrains.kotlin.android"

android {
    ndkVersion rootProject.ext.ndkVersion

    buildToolsVersion rootProject.ext.buildToolsVersion
    compileSdk rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    namespace 'co.uk.tycho.provisioner'
    defaultConfig {
        applicationId 'co.uk.tycho.provisioner'
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 14
        versionName "1.0.0"

        buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString())

        missingDimensionStrategy 'react-native-camera', 'general'
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'provisionerDebugKey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Осторожно! В производстве вам нужно сгенерировать свой собственный файл keystore.
            // см. https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false)
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    packagingOptions {
        jniLibs {
            useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
        }
    }
    // flavorDimensions 'react-native-camera'
    // productFlavors {
    //     general {
    //         dimension 'react-native-camera'
    //     }
    //     mlkit {
    //         dimension 'react-native-camera'
    //     }
    // }
}

// Примените статические значения из `gradle.properties` к `android.packagingOptions`
// Принимает значения в списках, разделенных запятыми, пример:
// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini
["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop ->
    // Разделить опцию: 'foo,bar' -> ['foo', 'bar']
    def options = (findProperty("android.packagingOptions.$prop") ?: "").split(",");
    // Удалить все элементы на месте.
    for (i in 0..<options.size()) options[i] = options[i].trim();
    // `[] - ""` это по сути `[""].filter(Boolean)`, устраняя все пустые строки.
    options -= ""

    if (options.length > 0) {
        println "android.packagingOptions.$prop += $options ($options.length)"
        // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**'
        options.each {
            android.packagingOptions[prop] += it
        }
    }
}

dependencies {
    // Версию react-native задает плагин Gradle React Native
    implementation("com.facebook.react:react-android")

    def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
    def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
    def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";

    if (isGifEnabled) {
        // Для поддержки анимированных gif
        implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
    }

    if (isWebpEnabled) {
        // Для поддержки webp
        implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
        if (isWebpAnimatedEnabled) {
            // Поддержка анимированного webp
            implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
        }
    }

    implementation("com.facebook.react:flipper-integration")

    if (hermesEnabled.toBoolean()) {
        implementation("com.facebook.react:hermes-android")
    } else {
        implementation jscFlavor
    }
}

apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
applyNativeModulesAppBuildGradle(project)

Уровень node_modules expo-camera:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'

group = 'host.exp.exponent'
version = '14.1.3'

def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
if (expoModulesCorePlugin.exists()) {
  apply from: expoModulesCorePlugin
  applyKotlinExpoModulesCorePlugin()
  // Удалите эту проверку, но сохраните содержимое после прекращения поддержки SDK49
  if (safeExtGet("expoProvidesDefaultConfig", false)) {
    useExpoPublishing()
    useCoreDependencies()
  }
}

buildscript {
  // Простой помощник, который позволяет корневому проекту переопределять версии, объявленные этой библиотекой.
  ext.safeExtGet = { prop, fallback ->
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
  }

  // Обеспечивает обратную совместимость
  ext.getKotlinVersion = {
    if (ext.has("kotlinVersion")) {
      ext.kotlinVersion()
    } else {
      ext.safeExtGet("kotlinVersion", "1.8.10")
    }
  }

  repositories {
    mavenCentral()
  }

  dependencies {
    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
  }
}

// Удалите этот if и его содержимое, когда поддержка SDK49 будет прекращена
if (!safeExtGet("expoProvidesDefaultConfig", false)) {
  afterEvaluate {
    publishing {
      publications {
        release(MavenPublication) {
          from components.release
        }
      }
      repositories {
        maven {
          url = mavenLocal().url
        }
      }
    }
  }
}

android {
  // Удалите этот if и его содержимое, когда поддержка SDK49 будет прекращена
  if (!safeExtGet("expoProvidesDefaultConfig", false)) {
    compileSdkVersion safeExtGet("compileSdkVersion", 34)

    defaultConfig {
      minSdkVersion safeExtGet("minSdkVersion", 23)
      targetSdkVersion safeExtGet("targetSdkVersion", 34)
    }

    publishing {
      singleVariant("release") {
        withSourcesJar()
      }
    }

    lintOptions {
      abortOnError false
    }
  }

  def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
  if (agpVersion.tokenize('.')[0].toInteger() < 8) {
    compileOptions {
      sourceCompatibility JavaVersion.VERSION_11
      targetCompatibility JavaVersion.VERSION_11
    }

    kotlinOptions {
      jvmTarget = JavaVersion.VERSION_11.majorVersion
    }
  }

  namespace "expo.modules.camera"
  defaultConfig {
    versionCode 32
    versionName "14.1.3"
  }
}

repositories {
  mavenCentral()
  maven {
    url "$projectDir/maven"
  }
}

dependencies {
  // Удалите этот if и его содержимое, когда поддержка SDK49 будет прекращена
  if (!safeExtGet("expoProvidesDefaultConfig", false)) {
    implementation project(':expo-modules-core')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
  }
  def camerax_version = "1.4.0-alpha02"

  api "androidx.exifinterface:exifinterface:1.3.6"
  api 'com.google.android:cameraview:1.0.0'

  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  implementation "androidx.camera:camera-video:${camerax_version}"

  implementation "androidx.camera:camera-view:${camerax_version}"
  implementation "androidx.camera:camera-extensions:${camerax_version}"
  implementation "com.google.mlkit:barcode-scanning:17.2.0"
  implementation 'androidx.camera:camera-mlkit-vision:1.4.0-alpha02'

  api 'com.google.android:cameraview:1.0.0'
}

Мой app.json:

{
    "expo": {
        "name": "*********",
        "slug": "*********",
        "version": "1.0.0",
        "orientation": "portrait",
        "icon": "./assets/icon.png",
        "userInterfaceStyle": "automatic",
        "splash": {
            "image": "./assets/splash_screen.png",
            "resizeMode": "contain",
            "backgroundColor": "#ffffff"
        },
        "assetBundlePatterns": [
            "**/*"
        ],
        "ios": {
            "supportsTablet": true,
            "bundleIdentifier": "**.**.*****.***********",
            "userInterfaceStyle": "automatic"
        },
        "android": {
            "splash": {
                "mdpi": "./android/app/src/main/res/drawable-mdpi/splashscreen_image.webp",
                "hdpi": "./android/app/src/main/res/drawable-hdpi/splashscreen_image.webp",
                "xhdpi": "./android/app/src/main/res/drawable-xhdpi/splashscreen_image.webp",
                "xxhdpi": "./android/app/src/main/res/drawable-xxhdpi/splashscreen_image.webp",
                "xxxhdpi": "./android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.webp"
            },
            "adaptiveIcon": {
                "foregroundImage": "./assets/adaptive-icon.png",
                "backgroundColor": "#ffffff"
            },
            "package": "co.uk.tycho.provisioner",
            "permissions": [
                "android.permission.BLUETOOTH",
                "android.permission.BLUETOOTH_ADMIN",
                "android.permission.BLUETOOTH_CONNECT"
            ],
            "userInterfaceStyle": "automatic"
        },
        "web": {
            "favicon": "./assets/favicon.png"
        },
        "extra": {
            "eas": {
                "projectId": "b61fde1e-5aad-4cc3-9cea-76a06fc6dd54"
            }
        },
        "plugins": [
            [
                "expo-camera",
                {
                    "cameraPermission": "Разрешить $(PRODUCT_NAME) получить доступ к вашей камере для создания фотографии профиля?"
                }
            ]
        ]
    }
}

Ответ или решение

Проблема, с которой вы столкнулись, связана с настройкой версии compileSdkVersion в конфигурации вашего проекта Expo React Native, в частности, для модуля expo-camera. Ошибка, указывающая на то, что compileSdkVersion не указан, может возникать даже в тех случаях, когда вы уверены, что он настроен правильно, что вызывает путаницу. В этом ответе мы подробно рассмотрим различные пути решения данной проблемы.

1. Понимание ошибки

Ошибка возникает в Gradle во время конфигурации, когда не удаётся найти значение compileSdkVersion. В вашей конфигурации проекта вы уже указали его на уровне проекта, однако некоторые модули (в данном случае expo-camera) могут требовать наличие этой переменной в своем собственном build.gradle.

2. Проверка конфигурации Gradle

Проектный уровень build.gradle

Вы правильно указали compileSdkVersion на уровне проекта, но также необходимо убедиться, что плагин expo-camera может получить к нему доступ. В вашем проектном build.gradle:

ext {
    compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
}

Убедитесь, что эта переменная корректно доступна всем подмодулям, на которые она ссылается.

Уровень приложения build.gradle

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

android {
    compileSdk rootProject.ext.compileSdkVersion
}

Если compileSdkVersion по-прежнему не распознаётся на уровне модуля expo-camera, стоит добавить параметр явно:

android {
    compileSdkVersion rootProject.ext.compileSdkVersion ?: 34 // Убедитесь, что 34 здесь — это ваша версия SDK
}

3. Проверка версии модуля

Вы проверили, что ранее все работало с версией expo-camera 14.1.3. Возможно, вы случайно обновили пакет или его зависимости. Убедитесь, что используете правильные и совместимые версии всех зависимостей. Установка более старой версии модуля может быть временным решением:

npm install expo-camera@14.1.3

4. Проверка node_modules

Изменения в node_modules не рекомендуется делать, так как они могут быть перезаписаны. Вы можете попробовать удалить все зависимости и установить их заново:

rm -rf node_modules
npm install

5. Переделка app.json

В некоторых случаях указание конфигурации Android непосредственно в app.json может помочь:

"android": {
    "compileSdkVersion": 34,
    "targetSdkVersion": 34,
    "minSdkVersion": 23
}

6. Использование gradle.properties

Если проблема сохраняется, вы можете попробовать добавить параметры в файл gradle.properties:

android.compileSdkVersion=34
android.minSdkVersion=23
android.targetSdkVersion=34

7. Обновление кэша Gradle

В некоторых случаях кэш Gradle может содержать устаревшую информацию. Попробуйте очистить кэш:

./gradlew cleanBuildCache

Заключение

Если все вышеперечисленные методы не помогут, попробуйте обратиться за поддержкой к сообществу Expo и React Native. Возможно, проблема связана с багом в конкретной версии модуля. Также важно следить за обновлениями и релизами библиотек, так как разработчики внедряют исправления, которые могут помочь в подобной ситуации.

В случае возникновения дополнительных вопросов, не стесняйтесь обращаться за помощью.

Оцените материал
Добавить комментарий

Капча загружается...