Android Gradle заменить имя пакета для значения в манифесте
Я использую Gradle с аксессуарами Product, где я устанавливаю другое имя пакета для каждого из них.
productFlavors {
appone {
packageName "com.dg.app1"
}
apptwo {
packageName "com.dg.app2"
}
appthree {
packageName "com.dg.app3"
}
appfour {
packageName "com.dg.app4"
}
}
Мне нужно иметь возможность заменить имя пакета внутри манифеста для каждого соответствующего приложения.
У моего манифеста есть следующее:
<receiver android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.dg.example" />
</intent-filter>
</receiver>
Поэтому мне нужно заменить com.dg.example для каждого имени пакета приложений. Каков наилучший способ сделать это?
Ответы
Ответ 1
Gradle Плагин v0.12 и выше:
Используйте ${applicationId}
вместо ${packageName}
.
Gradle Плагин v0.11 и выше:
Начиная с версии v.11, вам больше не нужно указывать, чтобы не использовать старое слияние манифеста.
Gradle Плагин v0.10 и выше:
Предполагая, что вы используете версию 0.10 или новее, это официально поддерживается:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// Make sure this is at least 0.10.+
classpath 'com.android.tools.build:gradle:0.10.+'
}
}
Начиная с версии 10.10, вам также придется вручную включить новое слияние манифеста , хотя я бы ожидал, что это требование исчезнет в версии или два раза, когда новое слияние становится стандартным:
android {
useOldManifestMerger false
}
Затем просто используйте ${packageName}
где-нибудь в AndroidManifest.xml
, который обычно будет жестко задавать имя пакета. Например:
<category android:name="my.package.name"/>
станет
<category android:name="${packageName}"/>
Gradle Плагин v0.9 и ниже:
Итак, ссылаясь на этот пост, похоже, что это еще не официально поддерживается через Gradle. Простым решением является следующее:
- Заменить имя пакета с помощью настраиваемого тега (например,
<category android:name="my.package.name"/>
станет <category android:name="_PACKAGENAME_"/>
- Добавьте в свой
build.gradle
следующее в области android
:
applicationVariants.all { variant ->
// After processing the manifest, replace all instances of your tag
// with the variant actual package name.
variant.processManifest << {
def manifestOutFile = variant.processManifest.manifestOutputFile
def newFileContents = manifestOutFile.getText('UTF-8').replace("_PACKAGENAME_", variant.packageName)
manifestOutFile.write(newFileContents, 'UTF-8')
}
}
Ответ 2
Чтобы сделать что-то подобное, я использую buildTypes в моем файле gradle, но я уверен, что это будет работать и с ароматами. Для меня я пытаюсь установить поле метки в действиях.
У меня есть xml файл строк для каждого из моих buildTypes.
Затем у меня есть sourceSet для каждого типа buildType, который содержит правильный файл строк.
Затем в манифесте я не использую строчную кодированную строку, а скорее "@string/my_var", которая вытащит правильную строку в зависимости от того, как определяются исходные наборы.
Этот google + post и связанный gist может помочь.
Что-то еще нужно сделать, чтобы поместить файл AndroidManifest.xml в src/flavor, который содержит только биты, которые имеют отношение к каждому аромату. Затем выньте эти биты из основного файла манифеста. Во время сборки файлы манифеста будут объединены в один файл. Вы можете увидеть результат всех объединенных манифестов в сборке/манифестах.
Ответ 3
У меня была та же проблема и был реализован метод замены заполнителя в Gradle. Он делает именно то, что вы ожидаете, но также заботится о атрибутах 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.
Ответ 4
Вариант Gradle:
Использовать класс attributes API. Что-то вроде этого
manifest.attributes(["attr1":"value1", "attr2":"value2"])
Вариант 1
Как насчет преобразования проекта в проект библиотеки Android и создания дополнительного проекта для каждой компании. Чем вы можете редактировать файл Manifest
по своему усмотрению.
Вариант 2
Напишите командный файл.