Подтвердить что ты не робот

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 для каждого имени пакета приложений. Каков наилучший способ сделать это?

4b9b3361

Ответ 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

Напишите командный файл.