Я настроил Gradle, чтобы добавить суффикс имени пакета в мое приложение отладки, чтобы иметь версию выпуска, которую я использую, и версию отладки на одном телефоне. Я ссылался на это: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
Мой файл build.gradle выглядит так:
...
android
{
...
buildTypes
{
debug
{
packageNameSuffix ".debug"
versionNameSuffix " debug"
}
}
}
Все работает нормально, пока я не начну использовать ContentProvider в своем приложении. Я получил:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]
Я понимаю, что это происходит потому, что два приложения (выпуск и отладка) регистрируют один и тот же орган ContentProvider.
Я вижу одну возможность решить эту проблему. Если я правильно понимаю, у вас должна быть возможность указать разные файлы для использования при сборке. Затем я должен иметь возможность помещать разные права доступа в разные файлы ресурсов (и из манифеста устанавливать права доступа как строковый ресурс) и указывать Gradle использовать другой ресурс для сборки отладки. Это возможно? Если да, то любые подсказки о том, как этого добиться, были бы потрясающими!
Или, может быть, можно напрямую изменить Manifest с помощью Gradle? Всегда приветствуется любое другое решение о том, как запустить одно и то же приложение с ContentProvider на одном устройстве.
Ответы:
Ни один из существующих ответов меня не удовлетворил, однако Liberty была близка. Вот как я это делаю. В первую очередь на данный момент я работаю с:
Моя цель - запустить
Debug
версию вместе сRelease
версией на одном устройстве, используя то же самоеContentProvider
.В build.gradle вашего приложения установите суффикс для сборки Debug:
В файле AndroidManifest.xml установите
android:authorities
свойство вашегоContentProvider
:В свойстве кодового набора,
AUTHORITY
которое можно использовать везде, где это необходимо в вашей реализации:Совет: раньше это было
BuildConfig.PACKAGE_NAME
Это оно! Это будет работать как шарм. Продолжайте читать, если вы используете SyncAdapter!
Обновление для SyncAdapter (14.11.2014)
Еще раз начну с моей текущей настройки:
В принципе, если вам нужно настроить некоторые значения для разных сборок, вы можете сделать это из файла build.gradle:
BuildConfig.java
классаВ качестве альтернативы для ресурсов вы можете создать отдельные каталоги buildType или разновидностей и переопределить XML-файлы или значения в них. Однако я не собираюсь использовать его в примере ниже.
пример
В файл build.gradle добавьте следующее:
Вы увидите результаты в классе BuildConfig.java
и в build / generated / res / generated / debug / values / generated.xml
В вашем Authenticator.xml используйте ресурс, указанный в файле build.gradle
В вашем syncadapter.xml использовать один и тот же ресурс снова и @ струнные / власти слишком
Совет: автозаполнение (Ctrl + Пробел) не работает для этих сгенерированных ресурсов, поэтому вам придется вводить их вручную
источник
Совет по новой системе сборки Android: переименование центра ContentProvider
Думаю, все вы слышали о новой системе сборки Android на основе Gradle. Давайте будем честными, эта новая система сборки - огромный шаг вперед по сравнению с предыдущей. Это еще не окончательная версия (на момент написания последней версии была 0.4.2), но вы уже можете безопасно использовать ее в большинстве своих проектов.
Я лично переключил большую часть своего проекта на эту новую систему сборки, и у меня возникли некоторые проблемы из-за отсутствия поддержки в некоторых конкретных ситуациях. Одним из них является поддержка переименования полномочий ContentProvider.
Новая система, созданная для Android, позволяет вам работать с различными типами приложений, просто изменяя имя пакета во время сборки. Одним из основных преимуществ этого улучшения является то, что теперь вы можете одновременно установить две разные версии вашего приложения на одном устройстве. Например:
Используя такую конфигурацию Gradle, вы можете собрать два разных APK:
• APK-файл отладки с именем пакета com.cyrilmottier.android.app.debug. • APK-файл выпуска с именем пакета com.cyrilmottier.android.app.
Единственная проблема заключается в том, что вы не сможете установить два APK одновременно, если они оба предоставляют ContentProvider с одинаковыми полномочиями. Довольно логично, что нам нужно переименовать авторитет в зависимости от текущего типа сборки ... но это не поддерживается системой сборки Gradle (пока? ... Я уверен, что это скоро будет исправлено). Итак, вот способ:
Сначала нам нужно переместить объявление ContentProvider в манифесте Android-провайдера в соответствующий тип сборки. Для этого у нас просто будет:
SRC / отлаживать / AndroidManifest.xml
SRC / выпуск / AndroidManifest.xml
Обязательно удалите объявление ContentProvider из AndroidManifest.xml в src / main /, потому что Gradle не знает, как объединить ContentProvider с тем же именем, но с разными полномочиями.
Наконец, нам может потребоваться доступ к полномочиям в коде. Это легко сделать с помощью файла BuildConfig и метода buildConfig:
Благодаря этому обходному пути вы сможете использовать BuildConfig.PROVIDER_AUTHORITY в своем ProviderContract и одновременно устанавливать две разные версии вашего приложения.
Первоначально в Google+: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ
источник
Хотя пример Кирилла отлично работает, если у вас есть только несколько типов сборки, он быстро усложняется, если у вас много типов сборки и / или разновидностей продукта, поскольку вам нужно поддерживать множество разных AndroidManifest.xml.
Наш проект состоит из 3 различных типов сборки и 6 разновидностей, всего 18 вариантов сборки, поэтому вместо этого мы добавили поддержку ".res-auto" в органах управления ContentProvider, которые расширяются до текущего имени пакета и устраняют необходимость поддерживать разные файлы AndroidManifest.xml.
Пример кода можно найти здесь: https://gist.github.com/cmelchior/6988275
источник
Поскольку версия плагина 0.8.3 (на самом деле 0.8.1, но она не работала должным образом), вы можете определять ресурсы в файле сборки, чтобы это могло быть более чистым решением, потому что вам не нужно создавать файлы строк или дополнительную отладку / выпуск папки.
build.gradle
AndroidManifest.xml
источник
Не знаю, упоминал ли об этом кто-нибудь. Фактически после плагина android gradle 0.10+ слияние манифестов обеспечит официальную поддержку этой функции: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger
В AndroidManifest.xml вы можете использовать $ {packageName} следующим образом:
И в вашем build.gradle вы можете иметь:
См. Полный пример здесь: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152
и здесь: https://code.google.com/p/anymemo/source/browse/build.gradle#41
источник
Используйте
${applicationId}
заполнители в xml иBuildConfig.APPLICATION_ID
в коде.Вам нужно будет расширить скрипт сборки, чтобы включить заполнители в XML-файлах, кроме манифеста. Вы можете использовать исходный каталог для каждого варианта сборки, чтобы предоставить разные версии файлов xml, но обслуживание очень быстро станет обременительным.
AndroidManifest.xml
Вы можете использовать заполнитель applicationId из коробки в манифесте. Объявите своего провайдера так:
Обратите внимание на
${applicationId}
бит. Он заменяется во время сборки фактическим applicationId для строящегося варианта сборки.В коде
Ваш ContentProvider должен создать в коде авторитетную строку. Он может использовать класс BuildConfig.
Обратите внимание на
BuildConfig.APPLICATION_ID
бит. Это сгенерированный класс с фактическим идентификатором applicationId для строящегося варианта сборки.res / xml / files, например syncadapter.xml, accountauthenticator.xml
Если вы хотите использовать адаптер синхронизации, вам необходимо будет предоставить метаданные для ContentProvider и AccountManager в файлах xml в каталоге res / xml /. Заполнитель applicationId здесь не поддерживается. Но вы можете самостоятельно расширить скрипт сборки, чтобы взломать его.
Снова обратите внимание на расширение
${applicationId}
. Это работает, только если вы добавите приведенный ниже скрипт gradle в корень своего модуля и примените его из build.gradle.build.gradle
Примените дополнительный сценарий сборки из сценария модуля build.gradle. Хорошее место ниже плагина Android Gradle.
наращивание processApplicationId.gradle
Ниже приведен рабочий источник сценария сборки res / xml / placeholder. Лучшая документированная версия доступна на github . Улучшения и расширения приветствуются.
strings.xml
На мой взгляд, нет необходимости добавлять поддержку заполнителей для строк ресурсов. По крайней мере, для вышеуказанного варианта использования это не требуется. Однако вы можете легко изменить сценарий, чтобы не только заменить заполнители в каталоге res / xml /, но и в каталоге res / values /.
источник
Я бы предпочел смесь Cyril и rciovati. Думаю проще, у вас всего две модификации.
В
build.gradle
выглядит следующим образом :И
AndroidManifest.xml
:источник
gradle.build
authenticator.xml
sync_adapter.xml
AndroidManifest.xml
Код:
источник
На основе образца @ChristianMelchior вот мое решение, которое устраняет две проблемы в предыдущих решениях:
решения, которые изменяют values.xml в каталоге сборки, вызывают полное перестроение ресурсов (включая APT всех чертежей)
по неизвестной причине IntelliJ (и, вероятно, Android Studio) не обрабатывает ресурсы надежно, в результате чего сборка содержит незамещенные
.res-auto
полномочия поставщика.Это новое решение делает вещи более похожими на Gradle, создавая новую задачу и допускает инкрементные сборки, определяя входные и выходные файлы.
создать файл (в этом примере я поместил его в
variants
каталог), отформатированный как ресурсный xml-файл, который содержит строковые ресурсы. Они будут объединены с ресурсами приложения, и любое вхождение.res-auto
в значениях будет заменено на имя пакета варианта, например<string name="search_provider">.res-auto.MySearchProvider</string>
добавьте
build_extras.gradle
файл из этой сущности в свой проект и ссылайтесь на него из основногоbuild.gradle
, добавивapply from: './build_extras.gradle'
где-нибудь надandroid
блокомубедитесь, что вы установили имя пакета по умолчанию, добавив его в
android.defaultConfig
блокbuild.gradle
in
AndroidManifest.xml
и другие файлы конфигурации (например,xml/searchable.xml
для поставщиков поиска с автозаполнением), укажите поставщика (например@string/search_provider
)если вам нужно получить такое же имя, вы можете использовать
BuildConfig.PACKAGE_NAME
переменную, напримерBuildConfig.PACKAGE_NAME + ".MySearchProvider"
https://gist.github.com/paour/9189462
Обновление: этот метод работает только на Android 2.2.1 и новее. Для более ранних платформ см. Этот ответ , который имеет свой собственный набор проблем, поскольку новое слияние манифестов все еще очень грубое ...
источник
variants/res-auto-values.xml
относительно/Applications/Android Studio.app/bin/
. т.е. я не получаю FileNotFoundException для/Applications/Android Studio.app/bin/variants/res-auto-values.xml
. Я работаю на Mac. Это отличное решение, но мне бы хотелось, чтобы оно работало в среде IDE для других членов команды.System.getProperty("user.dir")
, что возвращает другой результат при вызове сборкой Android Studio. Решение состоит в том, чтобы использовать путь относительно каталога проекта, который возвращается сgradle.startParameter.getProjectDir()
. См. Также мой комментарий в связанной сущности Paour.Я написал сообщение в блоге с примером проекта Github, который решает эту проблему (и другие подобные проблемы) немного иначе, чем у Кирилла.
http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html
источник
К сожалению, текущая версия (0.4.1) плагина для Android, похоже, не дает хорошего решения для этого. У меня не было времени , чтобы попробовать это еще, но можно обойти эту проблему будет использовать строковый ресурс
@string/provider_authority
, и использование , что в манифесте:android:authority="@string/provider_authority"
. Затем у вас естьres/values/provider.xml
в папке res каждого типа сборки, которая должна переопределить полномочия, в вашем случае это будетsrc/debug/res
Я изучал возможность создания xml-файла на лету, но, опять же, в текущей версии плагина, похоже, нет хороших ловушек для него. Я бы порекомендовал отправить запрос функции, я могу представить, что больше людей столкнутся с этой же проблемой.
источник
Ответ в этом посте мне подходит.
http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/
Я использую 3 разных вкуса, поэтому я создаю 3 манифеста с поставщиком контента в каждом аромате, как сказал Кевинршульц:
Ваш основной манифест не включает поставщиков:
И ваш манифест в каждом вашем вкусе, включая поставщика.
Свободно:
Выплачено:
Другой:
источник
Почему бы просто не добавить это?
источник
Мое решение - использовать замену заполнителя в
AndroidManifest.xml
. Он также обрабатываетpackageNameSuffix
атрибуты, поэтому вы можете иметьdebug
иrelease
любые другие пользовательские сборки на одном устройстве.У меня тоже есть это,
gist
если вы хотите увидеть, изменится ли он позже.Я обнаружил, что это более элегантный подход, чем подходы с использованием нескольких ресурсов и синтаксического анализа XML.
источник