Intereting Posts
Циркуляр показывает переход для новой активности Google oauth2 работает с одним временным кодом, созданным с Android, но не работает для кода, созданного с помощью JS SDK Всплывающее окно Android отклоняется при нажатии Изменение макета виджетов программно Android – переключение вкладок изнутри действия на вкладке ActionBarSherlock, ViewPager, вкладки TabsAdapter вложенные вкладки Android-виджет не обновляется – имеет неправильный идентификатор виджетов Как преобразовать HttpEntity в JSON? Исключение исключенного события цикла в плагине org.eclipse.ui Цвет фона списка становится белым в прокрутке при использовании android.support.v4.app.ListFragment; Приложение Android открывается из ссылок, отправленных по электронной почте Неисправность установки Multidex Ошибка: причина: buildToolsVersion не указывается Не удалось инициализировать класс android.support.design.widget.CoordinatorLayout Шаблоны для конвертации вкладок, чтобы просмотреть навигацию, если нет места

Использование типов сборки в Gradle для запуска того же приложения, которое использует ContentProvider на одном устройстве

Я установил 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.

Я вижу одну возможность решить эту проблему. Если я правильно понимаю, вы должны указать различные файлы, которые будут использоваться при создании. Затем я мог бы разместить разные полномочия в разных файлах ресурсов (и из Manifest set authority в качестве ресурса строки) и сказать Gradle использовать другой ресурс для сборки отладки. Это возможно? Если да, то любые намеки на то, как достичь этого, были бы замечательными!

Или, возможно, можно напрямую модифицировать манифест с помощью Gradle? Любое другое решение о том, как запустить такое приложение с ContentProvider на одном устройстве, всегда приветствуется.

Solutions Collecting From Web of "Использование типов сборки в Gradle для запуска того же приложения, которое использует ContentProvider на одном устройстве"

Ни один из существующих ответов не удовлетворил меня, однако Либерти была близка. Так вот как я это делаю. Прежде всего, в настоящий момент я работаю с:

  • Android Studio Beta 0.8.2
  • Плагин Gradle 0.12. +
  • Грейд 1.12

Моя цель – запустить версию Debug вместе с версией Release на том же устройстве, используя тот же ContentProvider .


В build.gradle суффикса вашего приложения для сборки Debug:

 buildTypes { debug { applicationIdSuffix ".debug" } } 

В AndroidManifest.xml файле установите значение android:authorities вашего ContentProvider :

 <provider android:name="com.example.app.YourProvider" android:authorities="${applicationId}.provider" android:enabled="true" android:exported="false" > </provider> 

В свойстве кода AUTHORITY которое можно использовать везде, где это необходимо в вашей реализации:

 public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider"; 

Совет. До этого был BuildConfig.PACKAGE_NAME

Это оно! Он будет работать как шарм. Продолжайте читать, если вы используете SyncAdapter!


Обновление для SyncAdapter (14.11.2014)

Еще раз я начну с моей текущей установки:

  • Android Studio Beta 0.9.2
  • Плагин Gradle 0.14.1
  • Зелень 2.1

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

  • Используйте buildConfigField для доступа к нему из класса BuildConfig.java
  • Используйте resValue для доступа к нему из ресурсов, например @ string / your_value

В качестве альтернативы ресурсам вы можете создавать отдельные каталоги buildType или аромата и переопределять XML-файлы или значения внутри них. Однако я не буду использовать его в приведенном ниже примере.

пример


В файле build.gradle добавьте следующее:

 defaultConfig { resValue "string", "your_authorities", applicationId + '.provider' resValue "string", "account_type", "your.syncadapter.type" buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type"' } buildTypes { debug { applicationIdSuffix ".debug" resValue "string", "your_authorities", defaultConfig.applicationId + '.debug.provider' resValue "string", "account_type", "your.syncadapter.type.debug" buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type.debug"' } } 

Вы увидите результаты в классе BuildConfig.java

 public static final String ACCOUNT_TYPE = "your.syncadapter.type.debug"; 

И в сборке / сгенерированном / res / сгенерированном / debug / values ​​/ generated.xml

 <?xml version="1.0" encoding="utf-8"?> <resources> <!-- Automatically generated file. DO NOT MODIFY --> <!-- Values from default config. --> <item name="account_type" type="string">your.syncadapter.type.debug</item> <item name="authorities" type="string">com.example.app.provider</item> </resources> 

В вашем файле authenticator.xml используйте ресурс, указанный в файле build.gradle.

 <?xml version="1.0" encoding="utf-8"?> <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="@string/account_type" android:icon="@drawable/ic_launcher" android:smallIcon="@drawable/ic_launcher" android:label="@string/app_name" /> 

В вашем файле syncadapter.xml снова используется тот же ресурс и @ строка / полномочия тоже

 <?xml version="1.0" encoding="utf-8"?> <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" android:contentAuthority="@string/authorities" android:accountType="@string/account_type" android:userVisible="true" android:supportsUploading="false" android:allowParallelSyncs="false" android:isAlwaysSyncable="true" /> 

Совет: автозаполнение (Ctrl + Space) не работает для этих сгенерированных ресурсов, поэтому вам нужно вводить их вручную

Новый совет по установке системы Android: переименование полномочий ContentProvider

Думаю, вы все слышали о новой системе сборки на базе Android Gradle. Давайте будем честными, эта новая система сборки является огромным шагом вперед по сравнению с предыдущим. Это еще не окончательно (на момент написания этой статьи последняя версия 0.4.2), но вы уже можете безопасно использовать ее в большинстве своих проектов.

Я лично включил большую часть своего проекта в эту новую систему сборки и имел некоторые проблемы из-за отсутствия поддержки в некоторых конкретных ситуациях. Одна из них – поддержка переименования полномочий ContentProvider

Новая система, созданная на базе Android, позволяет обрабатывать различные типы вашего приложения, просто изменяя имя пакета во время сборки. Одним из главных преимуществ этого улучшения является то, что теперь вы можете одновременно использовать две разные версии вашего приложения на одном устройстве. Например:

 android { compileSdkVersion 17 buildToolsVersion "17.0.0" defaultConfig { packageName "com.cyrilmottier.android.app" versionCode 1 versionName "1" minSdkVersion 14 // Listen to +Jeff Gilfelt advices :) targetSdkVersion 17 } buildTypes { debug { packageNameSuffix ".debug" versionNameSuffix "-debug" } } } 

Используя такую ​​конфигурацию Gradle, вы можете собрать два разных APK:

• Отладка APK с именем пакета com.cyrilmottier.android.app.debug. • APK выпуска с именем com.cyrilmottier.android.app.

Единственная проблема заключается в том, что вы не сможете установить оба APK одновременно, если они оба предоставляют ContentProvider с теми же полномочиями. Довольно логически нам нужно переименовать полномочия в зависимости от текущего типа сборки … но это не поддерживается системой сборки Gradle (еще? … я уверен, что она будет исправлена ​​в ближайшее время). Итак, вот путь:

Сначала нам нужно переместить декларацию ContentProvider поставщика Android в соответствующий тип сборки. Для этого у нас просто будет:

SRC / отлаживать / AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cyrilmottier.android.app" android:versionCode="1" android:versionName="1"> <application> <provider android:name=".provider.Provider1" android:authorities="com.cyrilmottier.android.app.debug.provider" android:exported="false" /> </application> </manifest> 

SRC / выпуск / AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cyrilmottier.android.app" android:versionCode="1" android:versionName="1"> <application> <provider android:name=".provider.Provider1" android:authorities="com.cyrilmottier.android.app.provider" android:exported="false" /> </application> </manifest> 

Обязательно удалите объявление ContentProvider из AndroidManifest.xml в src / main /, потому что Gradle не знает, как объединить ContentProviders с тем же именем, но с другим полномочием.

Наконец, нам может потребоваться доступ к полномочиям в коде. Это можно сделать довольно легко, используя файл BuildConfig и метод buildConfig:

 android { // ... final PROVIDER_DEBUG = "com.cyrilmottier.android.app.debug.provider" final PROVIDER_RELEASE = "com.cyrilmottier.android.app.provider" buildTypes { debug { // ... buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_DEBUG } release { buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_RELEASE } } } 

Благодаря этому решению вы сможете использовать BuildConfig.PROVIDER_AUTHORITY в своем ProviderContract и одновременно установить две разные версии вашего приложения.


Исправлено в Google+: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ

Хотя пример Кирилла отлично работает, если у вас есть только несколько типов сборки, он быстро усложняется, если у вас есть много типов сборки и / или продуктов, поскольку вам нужно поддерживать множество разных AndroidManifest.xml.

Наш проект состоит из 3-х различных типов сборки и 6 вариантов вкуса, состоящих из 18 вариантов сборки, поэтому вместо этого мы добавили поддержку «.res-auto» в органах ContentProvider, которые расширяются до текущего имени пакета и устраняют необходимость поддерживать различные AndroidManifest.xml

 /** * Version 1.1. * * Add support for installing multiple variants of the same app which have a * content provider. Do this by overriding occurrences of ".res-auto" in * android:authorities with the current package name (which should be unique) * * V1.0 : Initial version * V1.1 : Support for ".res-auto" in strings added, * eg. use "<string name="auth">.res-auto.path.to.provider</string>" * */ def overrideProviderAuthority(buildVariant) { def flavor = buildVariant.productFlavors.get(0).name def buildType = buildVariant.buildType.name def pathToManifest = "${buildDir}/manifests/${flavor}/${buildType}/AndroidManifest.xml" def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android") def xml = new XmlParser().parse(pathToManifest) def variantPackageName = xml.@package // Update all content providers xml.application.provider.each { provider -> def newAuthorities = provider.attribute(ns.authorities).replaceAll('.res-auto', variantPackageName) provider.attributes().put(ns.authorities, newAuthorities) } // Save modified AndroidManifest back into build dir saveXML(pathToManifest, xml) // Also make sure that all strings with ".res-auto" are expanded automagically def pathToValues = "${buildDir}/res/all/${flavor}/${buildType}/values/values.xml" xml = new XmlParser().parse(pathToValues) xml.findAll{it.name() == 'string'}.each{item -> if (!item.value().isEmpty() && item.value()[0].startsWith(".res-auto")) { item.value()[0] = item.value()[0].replace(".res-auto", variantPackageName) } } saveXML(pathToValues, xml) } def saveXML(pathToFile, xml) { def writer = new FileWriter(pathToFile) def printer = new XmlNodePrinter(new PrintWriter(writer)) printer.preserveWhitespace = true printer.print(xml) } // Post processing of AndroidManifest.xml for supporting provider authorities // across build variants. android.applicationVariants.all { variant -> variant.processManifest.doLast { overrideProviderAuthority(variant) } } 

Пример кода можно найти здесь: https://gist.github.com/cmelchior/6988275

Поскольку плагин версии 0.8.3 (фактически 0.8.1, но он не работал должным образом), вы можете определить ресурсы в файле сборки, чтобы это могло быть более чистым решением, потому что вам не нужно создавать файлы строк и дополнительные отладки / выпуска папки.

build.gradle

 android { buildTypes { debug{ resValue "string", "authority", "com.yourpackage.debug.provider" } release { resValue "string", "authority", "com.yourpackage.provider" } } } 

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yourpackage" android:versionCode="1" android:versionName="1"> <application> <provider android:name=".provider.Provider1" android:authorities="@string/authority" android:exported="false" /> </application> </manifest> 

Я не знаю, упоминает ли кто-нибудь об этом. На самом деле после плагина android gradle 0.10+ манифестное слияние предоставит официальную поддержку этой функции: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger

В AndroidManifest.xml вы можете использовать $ {packageName} следующим образом:

 <provider android:name=".provider.DatabasesProvider" android:authorities="${packageName}.databasesprovider" android:exported="true" android:multiprocess="true" /> 

И в вашем build.gradle вы можете:

 productFlavors { free { packageName "org.pkg1" } pro { packageName "org.pkg2" } } 

См. Полный пример здесь: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152

И здесь: https://code.google.com/p/anymemo/source/browse/build.gradle#41

Я предпочел бы предпочесть смесь между Кирилом и Ркйовати. Я думаю, что это проще, у вас есть только две модификации.

build.gradle выглядит так:

 android { ... productFlavors { production { packageName "package.name.production" resValue "string", "authority", "package.name.production.provider" buildConfigField "String", "AUTHORITY", "package.name.production.provider" } testing { packageName "package.name.debug" resValue "string", "authority", "package.name.debug.provider" buildConfigField "String", "AUTHORITY", "package.name.debug.provider" } } ... } 

И AndroidManifest.xml :

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="package.name" > <application ...> <provider android:name=".contentprovider.Provider" android:authorities="@string/authority" /> </application> </manifest> 

Основываясь на образце от @ChristianMelchior, вот мое решение, которое устраняет две проблемы в предыдущих решениях:

  • Решения, которые меняют values.xml в каталоге сборки, приводят к полному переустановке ресурсов (включая адаптацию всех чертежей)

  • По неизвестной причине IntelliJ (и, возможно, Android Studio) не надежно обрабатывает ресурсы, в результате чего сборка содержит .res-auto provider

Это новое решение делает многое более удобным для Gradle путем создания новой задачи и позволяет создавать инкрементные сборки путем определения входных и выходных файлов.

  1. Создайте файл (в примере, который я поместил в каталог variants ), отформатирован как XML-файл ресурса, который содержит строковые ресурсы. Они будут объединены в ресурсы приложения, и любое появление .res-auto в значениях будет заменено на имя пакета варианта, например <string name="search_provider">.res-auto.MySearchProvider</string>

  2. Добавьте файл build_extras.gradle из этого gist в ваш проект и build.gradle на него с основного build.gradle , добавив apply from: './build_extras.gradle' где apply from: './build_extras.gradle' то выше блока android

  3. Убедитесь, что вы установили имя пакета по умолчанию, добавив его в блок android.defaultConfig для build.gradle

  4. В AndroidManifest.xml и других файлах конфигурации (таких как xml/searchable.xml для поставщиков автозавершения поиска), @string/search_provider к провайдеру (например, @string/search_provider )

  5. Если вам нужно получить то же имя, вы можете использовать переменную BuildConfig.PACKAGE_NAME , например BuildConfig.PACKAGE_NAME + ".MySearchProvider"

https://gist.github.com/paour/9189462


Обновление: этот метод работает только на Android 2.2.1 и более поздних версиях. Для более ранних платформ см. Этот ответ , который имеет свой собственный набор проблем, поскольку новое слияние манифеста все еще очень грубо по краям …

Используйте заполнители ${applicationId} в xml и BuildConfig.APPLICATION_ID в коде.

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

AndroidManifest.xml

Вы можете использовать заполнитель приложения из ящика в манифесте. Объявите своего провайдера следующим образом:

 <provider android:name=".provider.DatabaseProvider" android:authorities="${applicationId}.DatabaseProvider" android:exported="false" /> 

Обратите внимание на бит ${applicationId} . Это заменяется во время сборки фактическим приложением для встроенного варианта сборки.

В коде

Ваш ContentProvider должен построить строку полномочий в коде. Он может использовать класс BuildConfig.

 public class DatabaseContract { /** The authority for the database provider */ public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".DatabaseProvider"; // ... } 

Обратите внимание на бит BuildConfig.APPLICATION_ID . Это сгенерированный класс с фактическим именем приложения для встроенного варианта сборки.

Res / xml / files, например syncadapter.xml, accountauthenticator.xml

Если вы хотите использовать адаптер синхронизации, вам необходимо предоставить метаданные для ContentProvider и AccountManager в xml-файлах в каталоге res / xml /. Заполнитель приложения не поддерживается здесь. Но вы можете расширить скрипт сборки самостоятельно, чтобы взломать его.

 <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="${applicationId}" android:allowParallelSyncs="false" android:contentAuthority="${applicationId}.DatabaseProvider" android:isAlwaysSyncable="true" android:supportsUploading="true" android:userVisible="true" /> <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="${applicationId}" android:icon="@drawable/ic_launcher" android:label="@string/account_authenticator_label" android:smallIcon="@drawable/ic_launcher" /> 

Снова обратите внимание на ${applicationId} . Это работает только в том случае, если вы добавите сценарий ниже уровня градиента в корень вашего модуля и примените его из build.gradle.

build.gradle

Примените дополнительный скрипт сборки из скрипта build.gradle модуля. Хорошее место находится под плагином Android-плагинов.

 apply plugin: 'com.android.application' apply from: './build-processApplicationId.gradle' android { compileSdkVersion 21 // etc. 

строить-processApplicationId.gradle

Ниже приведен рабочий источник для сценария сборки res / xml / placeholder. Более подробная документация доступна на github . Усовершенствования и расширения приветствуются.

 def replace(File file, String target, String replacement) { def result = false; def reader = new FileReader(file) def lines = reader.readLines() reader.close() def writer = new FileWriter(file) lines.each { line -> String replacedLine = line.replace(target, replacement) writer.write(replacedLine) writer.write("\n") result = result || !replacedLine.equals(line) } writer.close() return result } def processXmlFile(File file, String applicationId) { if (replace(file, "\${applicationId}", applicationId)) { logger.info("Processed \${applicationId} in $file") } } def processXmlDir(File dir, String applicationId) { dir.list().each { entry -> File file = new File(dir, entry) if (file.isFile()) { processXmlFile(file, applicationId) } } } android.applicationVariants.all { variant -> variant.mergeResources.doLast { def applicationId = variant.mergedFlavor.applicationId + (variant.buildType.applicationIdSuffix == null ? "" : variant.buildType.applicationIdSuffix) def path = "${buildDir}/intermediates/res/${variant.dirName}/xml/" processXmlDir(new File(path), applicationId) } } 

strings.xml

На мой взгляд, нет необходимости добавлять поддержку заполнителя для строк ресурсов. Для вышеуказанного варианта использования, по крайней мере, он не нужен. Однако вы можете легко изменить сценарий не только для замены заполнителей в каталоге res / xml /, но также в каталоге res / values ​​/.

Я написал блог-версию с примером Github, который решает эту проблему (и другие подобные проблемы) несколько иначе, чем Cyril's.

http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html

gradle.build

 android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { applicationId "com.example.awsomeapp" minSdkVersion 9 targetSdkVersion 23 versionCode 1 versionName "1.0.0" } productFlavors { prod { applicationId = "com.example.awsomeapp" } demo { applicationId = "com.example.awsomeapp.demo" versionName = defaultConfig.versionName + ".DEMO" } } buildTypes { release { signingConfig signingConfigs.release debuggable false minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } debug { applicationIdSuffix ".debug" versionNameSuffix = ".DEBUG" debuggable true } } applicationVariants.all { variant -> variant.outputs.each { output -> // rename the apk def file = output.outputFile; def newName; newName = file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"); newName = newName.replace(project.name, "awsomeapp"); output.outputFile = new File(file.parent, newName); } //Generate values Content Authority and Account Type used in Sync Adapter, Content Provider, Authenticator def valueAccountType = applicationId + '.account' def valueContentAuthority = applicationId + '.authority' //generate fields in Resource string file generated.xml resValue "string", "content_authority", valueContentAuthority resValue "string", "account_type", valueAccountType //generate fields in BuildConfig class buildConfigField "String", "ACCOUNT_TYPE", '"'+valueAccountType+'"' buildConfigField "String", "CONTENT_AUTHORITY", '"'+valueContentAuthority+'"' //replace field ${valueContentAuthority} in AndroidManifest.xml mergedFlavor.manifestPlaceholders = [ valueContentAuthority: valueContentAuthority ] } } 

authenticator.xml

 <?xml version="1.0" encoding="utf-8"?> <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="@string/account_type" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:smallIcon="@drawable/ic_launcher" /> 

sync_adapter.xml

 <?xml version="1.0" encoding="utf-8"?> <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" android:contentAuthority="@string/content_authority" android:accountType="@string/account_type" android:userVisible="true" android:allowParallelSyncs="false" android:isAlwaysSyncable="true" android:supportsUploading="true"/> 

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0" package="com.example.awsomeapp"> <uses-permission android:name="android.permission.GET_ACCOUNTS"/><!-- SyncAdapter and GCM requires a Google account. --> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> <uses-permission android:name="android.permission.USE_CREDENTIALS"/> <!-- GCM Creates a custom permission so only this app can receive its messages. --> <permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/> <application.... ....... <!-- Stub Authenticator --> <service android:name="com.example.awsomeapp.service.authenticator.CAuthenticatorService" android:exported="true"> <intent-filter> <action android:name="android.accounts.AccountAuthenticator"/> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator"/> </service> <!-- --> <!-- Sync Adapter --> <service android:name="com.example.awsomeapp.service.sync.CSyncService" android:exported="true" android:process=":sync"> <intent-filter> <action android:name="android.content.SyncAdapter"/> </intent-filter> <meta-data android:name="android.content.SyncAdapter" android:resource="@xml/sync_adapter" /> </service> <!-- --> <!-- Content Provider --> <provider android:authorities="${valueContentAuthority}" android:exported="false" android:name="com.example.awsomeapp.database.contentprovider.CProvider"> </provider> <!-- --> </application> </manifest> 

Код:

 public static final String CONTENT_AUTHORITY = BuildConfig.CONTENT_AUTHORITY; public static final String ACCOUNT_TYPE = BuildConfig.ACCOUNT_TYPE; 

К сожалению, текущая версия (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 манифеста с контент-провайдером в каждом вкусе, так как kevinrschultz сказал:

 productFlavors { free { packageName "your.package.name.free" } paid { packageName "your.package.name.paid" } other { packageName "your.package.name.other" } } 

Ваш основной манифест не включает поставщиков:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" > <!-- Permissions --> <application> <!-- Nothing about Content Providers at all --> <!-- Activities --> ... <!-- Services --> ... </application> 

И ваш манифест в каждом вашем вкусе, включая поставщика.

Свободно:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" > <application> <!-- Content Providers --> <provider android:name="your.package.name.Provider" android:authorities="your.package.name.free" android:exported="false" > </provider> </application> </manifest> 

Выплачено:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" > <application> <!-- Content Providers --> <provider android:name="your.package.name.Provider" android:authorities="your.package.name.paid" android:exported="false" > </provider> </application> </manifest> 

Другие:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" > <application> <!-- Content Providers --> <provider android:name="your.package.name.Provider" android:authorities="your.package.name.other" android:exported="false" > </provider> </application> </manifest> 

Почему бы просто не добавить это?

Type.packageNameSuffix = ". $ Type.name"

Мое решение – использовать замену заполнителя в AndroidManifest.xml . Он также обрабатывает атрибуты packageNameSuffix чтобы вы могли debug и release а также любые другие пользовательские сборки на одном устройстве.

 applicationVariants.all { variant -> def flavor = variant.productFlavors.get(0) def buildType = variant.buildType variant.processManifest.doLast { println '################# Adding Package Names to Manifest #######################' replaceInManifest(variant, 'PACKAGE_NAME', [flavor.packageName, buildType.packageNameSuffix].findAll().join()) // ignores null } } def replaceInManifest(variant, fromString, toString) { def flavor = variant.productFlavors.get(0) def buildtype = variant.buildType def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml" def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString) new File(manifestFile).write(updatedContent, 'UTF-8') } 

У меня тоже есть gist если вы хотите узнать, развивается ли он позже.

Я нашел более элегантный подход, чем множественные ресурсы и подходы к анализу XML.