Android. Как мне динамически установить имя пакета во время сборки для проекта с открытым исходным кодом?

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

Я использую ant для построения. По-видимому, я могу изменить build.xml, но я считаю, что это перезаписано android update. Все, что будет использовано, будет передано в репозиторий Git, и это не должно быть слишком сложным.

В настоящее время процесс построения кода прямо из репо Git довольно прост. Здесь выдержка из файла README:

$ cd ~/src/isokeys/IsoKeys
$ android list targets # I build against API level 10.
$ android update project --name IsoKeys --target 1 --path ./ # Only needed first time.
$ ant debug && adb -d install -r bin/IsoKeys-debug.apk

Для меня имеет смысл поставить имя пакета в local.properties, потому что это .gitignore 'd. Поскольку имя пакета не будет нигде, сборка завершится неудачно, не сделав этого. Таким образом, в README должно быть не менее 1 дополнительного шага, но я хочу свести его к минимуму.

Edit: Конечно, еще одно требование состоит в том, что различия имеют смысл, - что они не делают, если вы вручную переименуете имя пакета.

Ответы

Ответ 1

Я сделал что-то подобное (но не по этой причине), которое потребовало обновления манифеста во время сборки. То, как я это сделал, это сделать второй AndroidManifest и поместить его под каталог с именем config. Таким образом, в config/AndroidManifest у вас может быть что-то вроде этого:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="@[email protected]"
      android:versionCode="@[email protected]"
      android:versionName="@[email protected]">


<!-- EVERYTHING ELSE GOES HERE -->


</manifest>

Затем вы можете использовать обычные голые кости build.xml ant script всего несколькими изменениями (нет необходимости копировать весь script из системы сборки Android, поскольку они добавили некоторые крючки для вас, чтобы использовать без изобретать колесо). Строка script должна считывать local.properties по умолчанию, но если не добавить (или раскомментировать) строку вроде этого:

<property file="local.properties" />

В вашей сборке script вы должны увидеть задачу с именем -pre-build, измените ее следующим образом:

<target name="-pre-build">
     <copy file="config/AndroidManifest.xml" todir="." overwrite="true" encoding="utf-8">
       <filterset>
          <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
          <filter token="CONFIG.APP_VERSION" value="${app.version}" />
          <filter token="CONFIG.APP_VERSION_CODE" value="${app.versioncode}" />
       </filterset>
     </copy>           
</target>

Затем в файле local.properties вы поместите имя пакета, имя/код версии так:

app.version=1.0
app.versioncode=1
app.packagename=com.mypackage.name

Теперь вам просто нужно убедиться, что в вашем манифесте вы полностью квалифицируете все свои действия/службы/прослушиватели вещания и т.д. Это означает, что вы всегда указываете полный пакет исходного кода. Если вы хотите, чтобы пакет для вашего исходного кода был динамическим, вы могли бы заменить каждый префикс для каждого класса. Но это кажется глупым. Просто достаточно упаковать свой код под своим собственным именем пакета, и они может использовать его из любого проекта, просто включив источник или банку в свой проект.

- ОБНОВЛЕНИЕ - О, и еще одна вещь, которую вы можете сделать, чтобы уведомить пользователя о том, что они должны определить имя пакета, использует тег fail в вашем XML файле сборки следующим образом:

<fail message="app.packagename is missing. This must be defined in your local.properties file" unless="app.packagename" />

Поместите это после строки, которая читает файл local.properties

Ответ 2

С благодарностью Мэтту Вулфу за его помощь, я отправляю частичный ответ с моими усилиями до сих пор.

Я заметил, что по умолчанию barebones build.xml также импортирует custom_rules.xml:

<import file="custom_rules.xml" optional="true" />

Итак, я создал этот файл и начал мастерить. Это то, что я придумал до сих пор:

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" default="debug">
    <target name="-pre-build">
        <fail message="Please define app.packagename in your local.properties file." unless="app.packagename" />
        <taskdef resource="net/sf/antcontrib/antcontrib.properties">
            <classpath>
                <pathelement location="/usr/share/java/ant-contrib.jar"/>
            </classpath>
        </taskdef>
        <!-- How do I check for propertyregex?
        <fail message="Depends on ant-contrib propertyregex for app.packagename.path." unless="propertyregex" />
        -->
        <propertyregex property="app.packagename.path"
            input="${app.packagename}/"
            regexp="\."
            replace="/"
            global="true"
        />
        <copy todir="build/" overwrite="true" encoding="utf-8">
            <fileset dir="./">
                <include name="AndroidManifest.xml" />
                <include name="res/**" />
                <include name="lib/**" />
            </fileset>
            <filterset>
                <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
            </filterset>
        </copy>
        <copy todir="build/src/${app.packagename.path}" overwrite="true" encoding="utf-8">
            <fileset dir="./src/isokeys/">
                <include name="**" />
            </fileset>
            <filterset>
                <filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
            </filterset>
        </copy>
    </target>
    <target name="-pre-clean" description="Removes output files created by -pre-build.">
        <delete file="build/AndroidManifest.xml" verbose="${verbose}" />
        <delete dir="build/res/" verbose="${verbose}" />
        <delete dir="build/lib/" verbose="${verbose}" />
        <delete dir="build/src/" verbose="${verbose}" />
    </target>
    <!-- NOW CHANGE DIRECTORY TO build/ BEFORE HANDING BACK OVER TO build.xml!!! -->
</project>

Это устанавливает все в build/ (у которого есть дополнительный бонус, чтобы держать вещи аккуратными и аккуратными), теперь цель состоит в том, чтобы sdk tools build.xml запускался из этого каталога build/. Однако я не могу найти способ cd 'ing.

Ответ 3

Самый простой способ может заменить имя пакета как можно позже. Таким образом, вам даже не нужно прикасаться к вашему коду. Существует хорошая статья под названием Переименование пакета манифеста Android (http://www.piwai.info/renaming-android-manifest-package/). Краткое описание:

  • Вы можете использовать aapt --rename-manifest-package для изменения имени пакета

  • В качестве альтернативы, если вы хотите, чтобы замена имени пакета являлась частью процесса сборки ant, вы можете переопределить цель -package-resources:

    • скопировать цель -package-resources из SDK build.xml
    • добавить manifestpackage параметр