Почему собственные общие зависимости недоступны на цели, но в ее APK?

Я хочу поставлять собственные общие библиотеки вместе с моим 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.

1
0
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы явно не активировали доступ к ним во время первоначальной установки (с помощью команды 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/

А потом попробуйте, сработает ли это.

TLDR;

Android сохраняет свои собственные библиотеки в APK-файле хорошо организованными. Они извлекаются и используются соответствующим образом в зависимости от приложения, установленного на устройстве.

Ниже подробное объяснение всего процесса:

1. Родные библиотеки внутри 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) зарезервирован только один подкаталог.

2. Распаковка и установка

Процесс: В случае установки через любой установщик любого приложения Android:

а). Парсинг APK

Диспетчер пакетов устройства Android определяет каталог lib и знает, какие библиотеки необходимы для ABI устройства.

б). Разархивирование

Во время выполнения диспетчер пакетов извлечет собственные библиотеки ABI этого устройства в какое-то место в файловой системе устройства. Обычно это находится в каталоге личных данных приложения, для которого традиционно был класс:

/data/data/<package_name>/lib/

или для более новых версий Android (6.0 и выше) в разделенных каталогах APK:

/data/app/<package_name>-<identifier>/lib/<ABI>/

б.1) Родные библиотеки:

Некоторые приложения Android включают в себя собственные библиотеки, написанные на языке C/C++.

  • Прирост производительности в конкретных задачах для этих библиотек, но с необходимостью настройки на архитектуру устройства (ABI). extractNativeLibs Флаг:

Флаг extractNativeLibs устанавливается в файле AndroidManifest.xml приложения.

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

Влияние extractNativeLibs:

b.1.1) extractNativeLibs=true (по умолчанию для minSdkVersion < 21):
  • Менеджер пакетов извлекает все собственные библиотеки из APK и помещает их в папку, специфичную для устройства, обычно /data/data/<package_name>/lib/. Такой подход обеспечивает совместимость со старыми версиями Android (ниже уровня API 21);
  • Это приводит к тому, что приложениям предоставляется больший размер установки. Одни и те же библиотеки дублируются для разных ABI.
  • Требуется больше времени на демонтаж во время установки.
b.1.2) extractNativeLibs=false (по умолчанию для minSdkVersion >= 21):
  • Собственные библиотеки сжаты внутри APK.
  • Он извлекает только загружаемые библиотеки, совместимые с ABI устройства, например, в такие места, как /data/app/<package_name>-< identifier>/.
  • Это дает ряд преимуществ:
  • Это уменьшает размер установки приложения только до необходимых библиотек по порядку.
  • Быстрая установка за счет исключения ненужных извлечений.
  • Делает обновление приложений намного более эффективным.

Примечание:

Для новых приложений, ориентированных на уровень API 21 и выше, extractNativeLibs=false предпочтительнее, среди прочего, из-за эффективности. Вероятно, вы захотите использовать extractNativeLibs=true, если вам необходимо поддерживать старые версии Android или по другим причинам, например, для прямого использования функций NDK при создании собственных библиотек, предназначенных для конкретных ABI. Обзор Кроме того, флаги ExtractNativeLibs разрешают/запрещают извлечение собственных библиотек после установки приложения. Установка для этого поля значения false имеет значение в более поздних версиях ОС Android, обеспечивая эффективность размера, установки и обновления приложения.

в). Загрузка собственных библиотек

Затем они загружаются во время выполнения динамически, при каждом запуске приложения, с помощью Android Runtime (ART) или более старых версий Dalvik VM. Система добавляет путь, по которому эти библиотеки извлекаются, к пути поиска собственных библиотек для этого приложения.

3. Поддержка встроенной библиотеки

Обычно вы загружаете собственную библиотеку из кода Java/Kotlin, используя метод System.loadLibrary:

System.loadLibrary("native_lib_1");

Он загружает соответствующий файл .so при сканировании каталогов, в которые были бы извлечены собственные библиотеки.

4. Фильтры Multi-APK и ABI

Фильтры APK ABI. Если в вашем приложении используется более одного ABI, вы можете использовать фильтры APK ABI в своем APK, чтобы включать только нужные ABI:

android {
    ...
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
    ...
}

5. Разделение APK для собственных библиотек

Разработчики имеют возможность создавать собственные разделения 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
        }
    }
}

Более подробную информацию можно найти здесь :

Спасибо за ответ. Предоставленные вами ссылки оказались полезными, и установка android:extractNativeLibs = "true" в AndroidManifest.xml решила проблему.

fabian 29.05.2024 12:57

Шаг 2б должен упомянуть влияние extractNativeLibs.

Botje 29.05.2024 22:33

@Botje также добавил эти детали. Спасибо за замечание, пожалуйста, посмотрите. :-)Флаг extractNativeLibs объясняет, как извлекаются собственные библиотеки во время установки пакета приложения. Это частично уменьшает размер установленного файла пакетов, а также частично снижает скорость и эффективность установки обновлений для новых доступных версий Android.

Bob 30.05.2024 09:49

@fabian +1 за такой типичный вопрос.

Bob 18.06.2024 11:12

Другие вопросы по теме