Вопрос или проблема
При сборке моего приложения 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. Возможно, проблема связана с багом в конкретной версии модуля. Также важно следить за обновлениями и релизами библиотек, так как разработчики внедряют исправления, которые могут помочь в подобной ситуации.
В случае возникновения дополнительных вопросов, не стесняйтесь обращаться за помощью.