Я хочу поставлять собственные общие библиотеки вместе с моим APK. Я добавил эти общие библиотеки в папку src/main/jniLibs/arm64-v8a. Скомпилированный
apk включает эти библиотеки. Я убедился в этом, проверив содержимое unzip build/outputs/apk/debug/app-debug.apk. Эти библиотеки
в lib/arm64-v8a/.
Однако я не могу найти библиотеки на своем целевом устройстве. Я установил приложение через adb install build/outputs/apk/debug/app-debug.apk. Я определил папку на цели с помощью adb shell pm list packages -f MY_APP. Хотя путь /data/app/{PATH1}/{PATH2}/lib/arm64/ существует, он пуст. Однако библиотеки включены в цель base.apk.
Я ничего не менял в своем приложении (например, конфигурацию Gradle или файлы CMake), кроме сохранения библиотек в src/main/jniLibs/arm64-v8a/. Я поэкспериментировал с некоторыми тиками в конфигурации Gradle, но это не помогло. Я не могу найти соответствующую информацию в документации Android, https://developer.android.com/studio/projects/gradle-external-native-builds. Я использую Gradle 8.
Вы явно не активировали доступ к ним во время первоначальной установки (с помощью команды adb install), поэтому вы получаете пустые папки arm64 и arm64-v8a.
Попробуйте приведенный ниже подход только для целей разработки. Вы можете использовать adb push, чтобы вручную перенести библиотеки с вашего компьютера в соответствующее место целевого устройства.
adb push <path_to_library_on_your_pc>/lib/arm64-v8a/ <target_device_path>/data/app/<package_name>/lib/arm64-v8a/
А потом попробуйте, сработает ли это.
Android сохраняет свои собственные библиотеки в APK-файле хорошо организованными. Они извлекаются и используются соответствующим образом в зависимости от приложения, установленного на устройстве.
По мере того как вы продолжаете разрабатывать свое Android-приложение с помощью собственных библиотек, библиотеки упаковываются вместе с вашим APK-файлом в каталог lib. Структура этого каталога следующая:
<APK>
└── lib/
├── armeabi-v7a/
│ └── <native_lib_1>.so
│ └── <native_lib_2>.so
├── arm64-v8a/
│ └── <native_lib_1>.so
│ └── <native_lib_2>.so
├── x86/
│ └── <native_lib_1>.so
│ └── <native_lib_2>.so
└── x86_64/
└── <native_lib_1>.so
└── <native_lib_2>.so
Для соответствующей архитектуры ЦП (ABI) зарезервирован только один подкаталог.
Процесс: В случае установки через любой установщик любого приложения Android:
Диспетчер пакетов устройства Android определяет каталог lib и знает, какие библиотеки необходимы для ABI устройства.
Во время выполнения диспетчер пакетов извлечет собственные библиотеки ABI этого устройства в какое-то место в файловой системе устройства. Обычно это находится в каталоге личных данных приложения, для которого традиционно был класс:
/data/data/<package_name>/lib/
или для более новых версий Android (6.0 и выше) в разделенных каталогах APK:
/data/app/<package_name>-<identifier>/lib/<ABI>/
Некоторые приложения Android включают в себя собственные библиотеки, написанные на языке C/C++.
extractNativeLibs Флаг:Флаг extractNativeLibs устанавливается в файле AndroidManifest.xml приложения.
Это определяет, как менеджер пакетов должен обрабатывать собственные библиотеки во время установки.
extractNativeLibs:extractNativeLibs=true (по умолчанию для minSdkVersion < 21):/data/data/<package_name>/lib/.
Такой подход обеспечивает совместимость со старыми версиями Android (ниже уровня API 21);extractNativeLibs=false (по умолчанию для minSdkVersion >= 21):/data/app/<package_name>-< identifier>/.Для новых приложений, ориентированных на уровень API 21 и выше, extractNativeLibs=false предпочтительнее, среди прочего, из-за эффективности. Вероятно, вы захотите использовать extractNativeLibs=true, если вам необходимо поддерживать старые версии Android или по другим причинам, например, для прямого использования функций NDK при создании собственных библиотек, предназначенных для конкретных ABI. Обзор Кроме того, флаги ExtractNativeLibs разрешают/запрещают извлечение собственных библиотек после установки приложения. Установка для этого поля значения false имеет значение в более поздних версиях ОС Android, обеспечивая эффективность размера, установки и обновления приложения.
Затем они загружаются во время выполнения динамически, при каждом запуске приложения, с помощью Android Runtime (ART) или более старых версий Dalvik VM. Система добавляет путь, по которому эти библиотеки извлекаются, к пути поиска собственных библиотек для этого приложения.
Обычно вы загружаете собственную библиотеку из кода Java/Kotlin, используя метод System.loadLibrary:
System.loadLibrary("native_lib_1");
Он загружает соответствующий файл .so при сканировании каталогов, в которые были бы извлечены собственные библиотеки.
Фильтры APK ABI. Если в вашем приложении используется более одного ABI, вы можете использовать фильтры APK ABI в своем APK, чтобы включать только нужные ABI:
android {
...
defaultConfig {
...
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
...
}
Разработчики имеют возможность создавать собственные разделения APK для различных ABI, чтобы оптимизировать размер доставки приложения. В результате, даже если мы загрузим наше приложение в Play Store, APK, обслуживаемый Play Store, будет содержать только ABI, необходимый устройству, и, следовательно, уменьшит размер APK. Можно сделать в build.gradle:
android {
...
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
universalApk false
}
}
}
Более подробную информацию можно найти здесь :
В моем случае System.loadLibrary(...) не удалось найти встроенную библиотеку
https://medium.com/androiddevelopers/smallerapk-part-8-native-libraries-open-from-apk-fc22713861ff
Шаг 2б должен упомянуть влияние extractNativeLibs.
@Botje также добавил эти детали. Спасибо за замечание, пожалуйста, посмотрите. :-)Флаг extractNativeLibs объясняет, как извлекаются собственные библиотеки во время установки пакета приложения. Это частично уменьшает размер установленного файла пакетов, а также частично снижает скорость и эффективность установки обновлений для новых доступных версий Android.
@fabian +1 за такой типичный вопрос.
Спасибо за ответ. Предоставленные вами ссылки оказались полезными, и установка android:extractNativeLibs = "true" в AndroidManifest.xml решила проблему.