Как уменьшить размер apk для Android-приложения, которому требуется openCv lib (только для обработки изображений)

Я создаю приложение для Android с минимальным SDK 15, которое использует библиотеку OpenCV. Проблема в том, что при сборке apk его размер превышает 60 МБ, что не очень хорошо.

Я проверил файл приложения и увидел, что его размер слишком велик из-за файла libopencv_java3.so во всех архитектурах, таких как amr64, armeabi, mips, x86 и т.д.

enter image description here

Я использую opneCv только для обработки изображений. Эта библиотека имеет много других функций, таких как обработка видео, 3D-изображения, обнаружение объектов и многое другое, что мне не нужно в моем приложении, как

Если я удалю все эти файлы и соберу APK, то размер уменьшится на 50 МБ, но чтобы это приложение работало, мне нужно установить OpenCVManager для запуска моего приложения.

Есть ли способ уменьшить размер моего apk?

Или же можно просто извлечь из OpenCV интересующую меня функцию и создать .so для этих функций?

Ответы

Ответ 1

Для меня alijandro ответ на второй ответ был лучшим решением, но я застрял в этом процессе. Итак, я решил проблему apk split. Вам нужно загрузить apk, связанную с платформой, а также универсальный apk. Это было бы идеально, поскольку OpenCV не обеспечивает добавление зависимости на уровне модуля.

Universal apk будет загружен в случае, если платформа не соответствует. Вот хорошо написанный блог о apk публикации mutiple apk. Вам нужно поддерживать одинаковый идентификатор приложения, Keystore, ту же версию приложения, но другую версию кода

Шаг 1. Добавьте код градиента для разделения spk. Включите архитектуру, для которой вы хотите создать отдельный apk.

android{
//......
splits {
    abi {
        enable true
        reset()
        include "armeabi","armeabi-v7a",'arm64-v8a',"mips","x86","x86_64",'arm64-v8a'
        universalApk true
    }
}
}

Шаг 2. Добавьте код ниже для другой версии кода для другой платформы.

android{
//......
}
ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5, 
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
// For each APK output variant, override versionCode with a combination 
// of ABI APK value * 1000 + defaultConfig.versionCode
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
    def abiFilter = output.getFilter(OutputFile.ABI)
    def abiMultiplier = 0
    if (abiFilter != null) {
        abiMultiplier = project.ext.versionCodes.get(abiFilter)
    }
    output.versionCodeOverride =
            abiMultiplier * 1000 + android.defaultConfig.versionCode
   }
  }

Например, если исходный код версии равен 1, то сгенерированные коды будут:

 armeabi -> 3001
 armeabi-v7a -> 4001
 arm64-v8a -> 5001
 mips -> 6001
 x86 -> 7001
 x86_64 -> 8001

Все вместе ваш код Gradle будет выглядеть следующим образом.

 android{
//......
splits {
abi {
    enable true
    reset()
    include "armeabi","armeabi-v7a",'arm64-
v8a',"mips","x86","x86_64",'arm64-v8a'
    universalApk true
 }
 }

 ext.versionCodes = ['armeabi': 3, 'armeabi-v7a': 4, 'arm64-v8a': 5, 
mips: 6, 'x86': 7, 'x86_64': 8]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def abiFilter = output.getFilter(OutputFile.ABI)
def abiMultiplier = 0
if (abiFilter != null) {
    abiMultiplier = project.ext.versionCodes.get(abiFilter)
}
output.versionCodeOverride =
        abiMultiplier * 1000 + android.defaultConfig.versionCode
}
}

Теперь вам нужно публиковать все apk на playstore по одному.

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

Ответ 2

Вы не можете удалить библиотеку libopencv_java3.so, это обязательно.

Есть ли способ уменьшить размер моего apk?

Без изменения библиотеки libopencv_java3.so вы можете создать несколько apks для разных архитектур, а не упаковывать плоский APK. Только одна арка из libopencv_java3.so будет упакована в ваш сплит APK. Например, вы можете использовать приведенную ниже конфигурацию для сборки только для x86, armeabi-v7a и mips в вашем build.gradle

splits {
    abi {
      enable true
      reset()
      include "x86", "armeabi-v7a", "mips"
      universalApk false
    }
  }

Более подробную информацию об уменьшении размера apk путем разделения смотрите здесь.

Или же можно просто извлечь из OpenCV интересующую меня функцию и создать .so для этих функций?

Да, конечно. Процесс сборки opencv полностью настроен. Если вы уже знаете, как собрать opencv для Android, перейдите к шагу 2 напрямую.

шаг 1

  1. получить исходник opencv
  2. создать каталог opencv_build
  3. перейти в корневой каталог opencv вы только что клонировали
  4. вызывать скрипт сборки platforms/android/build_sdk.py --ndk_path $ANDROID_NDK_ROOT --sdk_path $ANDROID_SDK_ROOT../opencv_build.

Заметка

Процедура сборки требует команды android для сборки apk, поэтому версия Android SDK должна быть менее 25.3.0, из 25.3.0, команда android удалена.

шаг 2

Предположим, что шаг 1 выше работает правильно. Здесь я возьму armeabi-v7a в качестве примера.

  1. Перейдите в каталог opencv_build/o4a/lib/armeabi-v7a
  2. Вы найдете много *.a для различных модулей opencv, библиотека libopencv_java3.so также в этом каталоге
  3. Создайте крошечную версию библиотеки общего доступа из модуля, который вам нужен, например,

    $ arm-linux-androideabi-gcc -shared -o libopencv_tiny.so --sysroot=$ANDROID_NDK_ROOT/platforms/android-9/arch-arm -Wl,--whole-archive libopencv_core.a libopencv_imgcodecs.a libopencv_imgproc.a -Wl,--no-whole-archive
    $ du -h libopencv_tiny.so 
    5.2M    libopencv_tiny.so
    $ arm-linux-androideabi-strip --strip-unneeded libopencv_tiny.so 
    $ du -h libopencv_tiny.so 
    4.1M    libopencv_tiny.so
    $ du -h libopencv_java3.so 
    9.8M    libopencv_java3.so
    

Миниатюрная версия, включающая в себя core, image codecs и image proc имеет размер 4.1M после полосы, но полная версия libopencv_java3.so имеет размер 9.8M.

Я использую libopencv_tiny.so в качестве имени просто для удобства, вы должны использовать то же имя libopencv_java3.so в вашем проекте. В противном случае System.loadLibrary в Java не может найти нативную библиотеку.

Для остальной части архитектуры вам нужно, например arm64-v8a, сделать то же самое.

Ответ 3

Приведенные выше два ответа довольно полны, но на всякий случай, если вам нужно больше деталей и регуляторов настройки, найдите эту статью.

Ответ 4

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

 buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
        }
    }

Если вы хотите удалить неиспользуемый код, используйте методы 64K

LINK2

Вы также можете задать вопрос в OpenCV

Q/A сайт

Ответ 5

Как создать .so файлы из некоторых функций OpenCV в Windows 10?