Intereting Posts
Меню опций Android при нажатии кнопки Шаблон репозитория с SqlBrite / SqlDelight (автономная база данных) и дооснащение (запрос Http) Управление жизненным циклом Android фрагментов в ViewPager и FragmentPagerAdapter Фрагмент ViewState восстановлен в onStart? Есть ли лучший способ восстановить состояние SearchView? Com.firebase.client.FirebaseException: не удалось разобрать узел с классом класса CLASS_NAME android Почему значки, установленные с Notification.Builder.setSmallIcon в Android Lollipop, отображаются как белый квадрат? Удаленная отладка с эмулятором Android Создайте собственный lockscreen для Android 4.0 или более поздней версии? Создайте DummyActivity внутри папки androidTest для тестирования Что делает Eclipse, когда говорится, что он обновляет индексы? Почему вызываются фрагменты onCreateView, onCreate, onActivityCreated Как получить 720p Android Camera Preview Data? String.equals () с несколькими условиями (и одним действием по результату) Как использовать SQLiteDatabase.CursorFactory

Gradle android build для разных процессорных архитектур

Я хочу построить 4 отдельных apks для 4 различных архитектур процессоров Android (armeabi armeabi-v7a x86 mips), используя Gradle.

У меня есть собственные библиотеки OpenCV, построенные для 4 архитектур процессора в папке libs .

libs -armeabi -armeabi-v7a -x86 -mips 

Я хочу, чтобы каждый apk содержал только библиотеку OpenCV, соответствующую правильной архитектуре процессора.

Текущий скрипт сборки выглядит следующим образом:

 apply plugin: 'android' dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile project(':workspace:OpenCV4Android:sdk:java') } android { compileSdkVersion 11 buildToolsVersion "18.1.0" sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } // Move the tests to tests/java, tests/res, etc... instrumentTest.setRoot('tests') debug.setRoot('build-types/debug') release.setRoot('build-types/release') flavorGroups "abi", "version" productFlavors { x86 { flavorGroup "abi" } arm { flavorGroup "abi" } mips { flavorGroup "abi" } } } } 

Может кто-нибудь помочь мне решить это, пожалуйста?

Ура,

Solutions Collecting From Web of "Gradle android build для разных процессорных архитектур"

Начиная с версии Android Gradle Plugin версии 13 вы можете создавать отдельные APK, используя новый механизм «split». Вы можете прочитать об этом здесь .

Структура файлов по умолчанию для размещения ваших файлов .so:

 src -main -jniLibs -armeabi -arm.so -armeabi-v7a -armv7.so -x86 -x86.so -mips -mips.so 

Обратите внимание, что имя файла .so не имеет значения, если оно имеет расширение .so.

Затем в файле сборки Gradle:

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

а также

 // map for the version code ext.versionCodes = ['armeabi-v7a':1, mips:2, x86:3] import com.android.build.OutputFile android.applicationVariants.all { variant -> // assign different version code for each output variant.outputs.each { output -> output.versionCodeOverride = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000000 + android.defaultConfig.versionCode } } 

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

Расколотое решение ABI APK для градиента является самым простым, что я нашел до сих пор. @withoutclass имеет хорошую запись здесь: https://stackoverflow.com/a/26129447/254573 Мне пришлось ссылаться на документацию на Android, так как это новая функция, которую можно изменить: http://tools.android.com/tech -docs / новая сборка-система / пользователь руководство / APK-расколы

Тем не менее, мне пришлось отказаться от этой простой реализации, так как мне нужно было поддерживать как сборку с живыми строками, так и архитектуру. Вы можете столкнуться с этой же проблемой, если вы поддерживаете как хранилище Google Play (которое поддерживает APK с архитектурой), так и App Store Амазонки (который поддерживает только APK с жиром).

Возможно, это будет возможно с помощью split APK, если вы можете добавить компонент вкуса, но пока что split + flavor еще не поддерживается: https://code.google.com/p/android/issues/detail?id= 76469

Я закончил использование abiFilter, см. Пример кода ниже:

 android { flavorDimensions "abi" productFlavors { fat { flavorDimension "abi" ndk { abiFilters "x86", "armeabi-v7a", "armeabi" versionCode = 0; } } arm { flavorDimension "abi" ndk { abiFilter "armeabi" versionCode = 1; } } armv7a { flavorDimension "abi" ndk { abiFilter "armeabi-v7a" versionCode = 3; } } x86 { flavorDimension "abi" ndk { abiFilter "x86" versionCode = 6; } } } } // Each APK needs a different version code when submitted to Google, // bump the versionCode we set in defaultConfig android.applicationVariants.all { variant -> // Ugly hard coded flavorDimensions position // If you have more than one flavorDimension, make sure to target the position for "abi" def abiVersion = variant.productFlavors.get(0).versionCode variant.mergedFlavor.versionCode = abiVersion * 1000 + android.defaultConfig.versionCode } 

Обновление. Используя universalApk, установленное в true, решает это решение, просто добавляет время для сборки каждого apk.

 android { // Rest of Gradle file splits { abi { enable true reset() include 'armeabi', 'armeabi-v7a', 'x86' universalApk true } } } //Ensures architecture specific APKs have a higher version code //(otherwise an x86 build would end up using the arm build, which x86 devices can run) ext.versionCodes = [armeabi:1, 'armeabi-v7a':3, x86:6] android.applicationVariants.all { variant -> // assign different version code for each output variant.outputs.each { output -> int abiVersionCode = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) ?: 0 output.versionCodeOverride = (abiVersionCode * 1000) + android.defaultConfig.versionCode } } 

ОБНОВЛЕНИЕ – со времени этой публикации в процессе построения градиентов был достигнут значительный прогресс, поэтому этот ответ может быть не рекомендованной лучшей практикой, и новые изменения могут даже остановить его. Используйте свое собственное усмотрение.

Для этого сначала необходимо поместить собственные библиотеки в следующую иерархию папок отдельно

 lib -armeabi -arm.so -*.so 

 lib -x86 -x86.so -*.so 

Затем застегните папки lib (без 's') (например, arm.zip и x86.zip) и переименуйте расширение «zip» в «jar» (например, arm.jar и x86.jar). Поместите эти банки в соответствующие папки (например, armeabi / libs и x86 / libs). Теперь мы собираемся включить зависимости для каждого аромата. Но мы не можем использовать «файл компиляции» … ». Мы должны использовать файл «flavorCompile» … »

например

  flavorGroups 'abi' productFlavors { arm { flavorGroup 'abi' dependencies { armCompile files('arm/libs/armeabi.jar') } } x86 { flavorGroup 'abi' dependencies { x86Compile files('x86/libs/x86.jar') } } } 

====

Вот более сложная среда. У вас не только варианты архитектуры процессора, но также у вас есть библиотеки отладки ( .jar, .so) для процессоров. Пример здесь имеет Debug.jar для отладки руки и NonDebug.jar для выпуска Arm; И * .so для обеих рук и X86. Такая конфигурация может быть достигнута с помощью gradle ExtraPropertiesExtension. Пожалуйста, прочтите мой SO-ответ здесь, https://stackoverflow.com/a/19941684/319058 , чтобы понять, как можно структурировать папки отладки.

 android { compileSdkVersion 18 buildToolsVersion "19.0.0" final DEBUG_ROOT = "build-types/debug" final RELEASE_ROOT = "build-types/release" project.ext.set("projRoot", "") buildTypes { debug { project.projRoot = DEBUG_ROOT dependencies { debugCompile files(DEBUG_ROOT+"/libs/Debug.jar") } } release { project.projRoot = RELEASE_ROOT dependencies { releaseCompile files(RELEASE_ROOT+"/libs/NonDebug.jar") } runProguard true proguardFile 'proguard.cfg' } } sourceSets { final PROJ_ROOT = project.ext.get("projRoot") final BUILD_TYPE_RES = PROJ_ROOT + "/res" main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java'] //resources.srcDirs = ['src/main'] //aidl.srcDirs = ['src/main'] //renderscript.srcDirs = ['src/main'] res.srcDirs = ['src/main/res',BUILD_TYPE_RES] assets.srcDirs = ['src/main/assets'] } flavorGroups 'abi' productFlavors { arm { flavorGroup 'abi' final ARM_LIB_PATH = PROJ_ROOT + "/arm/libs/armeabi.jar" dependencies { armCompile files(ARM_LIB_PATH) } } x86 { flavorGroup 'abi' final X86_LIB_PATH = PROJ_ROOT + "/x86/libs/x86.jar" dependencies { x86Compile files(X86_LIB_PATH) } } } // Move the tests to tests/java, tests/res, etc... instrumentTest.setRoot('tests') // Move the build types to build-types/<type> // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... // This moves them out of them default location under src/<type>/... which would // conflict with src/ being used by the main source set. // Adding new build types or product flavors should be accompanied // by a similar customization. debug.setRoot(DEBUG_ROOT) release.setRoot(RELEASE_ROOT) } 

}

У меня нет ответа на градле, но я думаю, что теперь у меня есть общий ответ для любого инструмента для создания Android. Вот моя идея о том, как создавать отдельные файлы APK для каждой поддерживаемой архитектуры процессора:

  1. Создайте APK с любыми инструментами, которые вы используете, включая все поддерживаемые базовые библиотеки кода, например armeabi, armeabi-v7a, x86 и mips. Я назову его «оригинальным» APK-файлом.

  2. Разархивируйте ваш оригинальный APK в пустую папку, используя любую утилиту zip / unzip, лучше всего используйте инструменты командной строки, чтобы впоследствии можно было автоматизировать ее с помощью сценария оболочки или командного файла.

  3. В папке, где оригинальный APK был несжатым, удалите подпапку META-INF (это содержит подписи, нам нужно будет снова подписать APK после всех модификаций, чтобы исходный META-INF был удален).

  4. Перейдите в подпапку lib и удалите подпапки для любых архитектур процессоров, которые вы не хотите в новом файле APK. Например, оставьте только подкаталог «x86», чтобы сделать APK для процессоров Intel Atom.

  5. Важно: каждый APK для другой архитектуры должен иметь другой номер «versionCode» в AndroidManifest.xml, а код версии, например, armeabi-v7a, должен быть немного выше, чем у armeabi (читайте инструкции Google для создания нескольких APK здесь: http://developer.android.com/google/play/publishing/multiple-apks.html ). К сожалению, файл манифеста находится в скомпилированной двоичной форме внутри APK. Нам нужен специальный инструмент для модификации версии Code. Смотри ниже.

  6. После того, как манифест изменен с новым кодом версии, и ненужные каталоги и файлы удалены, повторно запишите, подпишите и выровняйте свой меньший APK (используйте инструменты jarsigner и zipalign из Android SDK).

  7. Повторите процесс для всех других архитектур, которые вам нужны для поддержки, создавая небольшие файлы APK со слегка отличающимися кодами версий (но с тем же именем версии).

Единственной нерешенной проблемой является способ изменения «versionCode» в двоичном файле манифеста. Я не мог найти решение для этого в течение долгого времени, поэтому, наконец, пришлось сесть и запустить мой собственный код, чтобы сделать это. В качестве отправной точки я взял APKExtractor от Prasanta Paul, http://code.google.com/p/apk-extractor/ , написанного на Java. Я старая школа и все еще более комфортно с C ++, поэтому моя небольшая утилита «aminc», написанная на C ++, теперь находится на GitHub:

https://github.com/gregko/aminc

Я опубликовал все решение Visual Studio 2012, но вся программа представляет собой один .cpp-файл, который, вероятно, может быть скомпилирован на любой платформе. И вот пример файла Windows .bat, который я использую для разделения моего «жирного» apk с именем atVoice.apk на 4 небольших файла с именем atVoice_armeabi.apk, atVoice_armeabi-v7a.apk, atVoice_x86.apk и atVoice_mips.apk. Я фактически отправляю эти файлы в Google Play (см. Мое приложение на https://play.google.com/store/apps/details?id=com.hyperionics.avar ), и все работает отлично. Также см. Этот проект Github от Jorge Suárez de Lis , который размещает аналогичный сценарий для Linux.

 @echo off REM My "fat" apk is named atVoice.apk. Change below to whatever or set from %1 set apkfile=atVoice del *.apk REM My tools build atVoice-release.apk in bin project sub-dir. REM Copy it here for splitting. copy ..\bin\%apkfile%-release.apk %apkfile%.apk zip -d %apkfile%.apk META-INF/* REM ------------------- armeabi ------------------------ unzip %apkfile%.apk AndroidManifest.xml copy/y %apkfile%.apk %apkfile%.zip zip -d %apkfile%.zip lib/armeabi-v7a/* lib/x86/* lib/mips/* aminc AndroidManifest.xml 1 zip -f %apkfile%.zip ren %apkfile%.zip %apkfile%_armeabi.apk jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi.apk MyKeyName zipalign 4 %apkfile%_armeabi.apk %apkfile%_armeabi-aligned.apk del %apkfile%_armeabi.apk ren %apkfile%_armeabi-aligned.apk %apkfile%_armeabi.apk REM ------------------- armeabi-v7a --------------------- copy/y %apkfile%.apk %apkfile%.zip zip -d %apkfile%.zip lib/armeabi/* lib/x86/* lib/mips/* aminc AndroidManifest.xml 1 zip -f %apkfile%.zip ren %apkfile%.zip %apkfile%_armeabi-v7a.apk jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi-v7a.apk MyKeyName zipalign 4 %apkfile%_armeabi-v7a.apk %apkfile%_armeabi-v7a-aligned.apk del %apkfile%_armeabi-v7a.apk ren %apkfile%_armeabi-v7a-aligned.apk %apkfile%_armeabi-v7a.apk REM ------------------- x86 --------------------- copy/y %apkfile%.apk %apkfile%.zip zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/mips/* aminc AndroidManifest.xml 9 zip -f %apkfile%.zip ren %apkfile%.zip %apkfile%_x86.apk jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_x86.apk MyKeyName zipalign 4 %apkfile%_x86.apk %apkfile%_x86-aligned.apk del %apkfile%_x86.apk ren %apkfile%_x86-aligned.apk %apkfile%_x86.apk REM ------------------- MIPS --------------------- copy/y %apkfile%.apk %apkfile%.zip zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/x86/* aminc AndroidManifest.xml 10 zip -f %apkfile%.zip ren %apkfile%.zip %apkfile%_mips.apk jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_mips.apk MyKeyName zipalign 4 %apkfile%_mips.apk %apkfile%_mips-aligned.apk del %apkfile%_mips.apk ren %apkfile%_mips-aligned.apk %apkfile%_mips.apk del AndroidManifest.xml del %apkfile%.apk :done 

Greg