Android - несколько пользовательских версий одного и того же приложения - PullRequest
46 голосов
/ 03 августа 2009

Каков наилучший способ развертывания нескольких настроенных версий приложения Android?

В настоящее время у меня есть скрипт для обмена папкой ресурсов для получения настроенной версии моего приложения. Он отлично работает, но все пользовательские версии по-прежнему имеют одинаковое имя пакета в AndroidManifest.xml. Поэтому невозможно установить две настроенные версии приложения одновременно.

Это одно из решений этой проблемы, но это должно быть сделано вручную

Можете ли вы придумать более простое решение или как его можно встроить в скрипт?

(кстати: это не порно / спам / все приложения, даже не заплатил один)

Ответы [ 8 ]

23 голосов
/ 08 сентября 2011

Возможно, концепция встроенной Android-библиотеки не была полностью выпечена на момент публикации, но это может быть предпочтительный метод с 2011 года. Выполните следующие шаги для сборки муравья:

Начиная с рабочего приложения (назовем его каталогом «myOrigApp», пакет com.foo.myapp), просто добавьте эту строку в «default.properties», чтобы сделать его библиотекой:

android.library=true

Теперь создайте новое приложение в каталоге одноуровневого каталога любым удобным для вас способом (назовем его каталогом «одноуровневый», пакет com.foo.myVariant). Например, используя Intellij Idea, создайте проект «с нуля» с каталогом «sibling», и он создаст все файлы / каталоги, которые вам обычно необходимы.

В этом новом каталоге родственника отредактируйте "default.properties", чтобы добавить зависимость:

android.library.reference.1=../myOrigApp

Скопируйте Манифест из оригинального каталога:

cd sibling
cp ../myOrigApp/AndroidManifest.xml  ../myOrigApp/local.properties ../myOrigApp/build.properties  .

Отредактируйте этот скопированный файл манифеста, чтобы изменить его имя пакета на ваш новый вариант, "com.foo.myVarient"; это единственное изменение.

Если вы просто запустите сценарии сборки муравья, возможно, все будет готово. (Я должен был просто установить ключи подписи.)

Если вы хотите настроить IDE, например, Idea, чтобы проект библиотеки зависел от варианта проекта, выполните следующие действия, чтобы добавить проект библиотеки в проект варианта (предполагается, что у вас уже есть проект, настроенный для обоих). :

  • Откройте исходный проект, откройте «Настройки проекта», выберите ваш фасет, отметьте «Is Library Project» и сохраните.
  • Откройте вариант проекта, откройте настройки проекта, выберите Модули
  • Добавить модуль
  • Выберите «Импортировать существующий модуль»
  • Перейдите в исходный каталог (myOrigApp) и выберите его файл .iml (исходный файл проекта IntelliJ)
  • Нажмите «Готово». (Проект библиотеки добавляется как модуль в вариант проекта.)
  • В списке модулей щелкните проект Variant, чтобы выбрать его.
  • В правой части выберите вкладку "Зависимости".
  • Нажмите «Добавить…»
  • Выберите «Зависимость модуля…» (должен появиться список, содержащий имя модуля / библиотеки, которое вы ранее добавили в проект - возможно, единственную запись в списке).
  • Выберите проект библиотеки, который вы добавили, и нажмите OK. (Он будет добавлен в список зависимостей вашего проекта.)
  • Нажмите OK, чтобы завершить настройку проекта. (Вы должны увидеть 2 модуля с ресурсами и классами библиотеки, доступными и распознаваемыми в проекте Variant.)
6 голосов
/ 23 апреля 2014

Вы определенно хотите использовать Gradle ароматов , которые изначально и даже приветствуются в Android Studio.

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

Как объясняет веб-сайт, одна из целей этого дизайна состояла в том, чтобы сделать его более динамичным и упростить создание нескольких APK с практически одинаковым кодом, что звучит примерно так, как вы делаете.

Я, вероятно, не объяснил это лучше, но этот веб-сайт довольно неплохо справляется.

6 голосов
/ 03 августа 2009

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

Например, чтобы заменить его во всех ваших java-файлах в каталоге src:

 <replaceregexp flags="g" byline="false">
    <regexp pattern="old.package.string" /> 
    <substitution expression="new.package.string" />
    <fileset dir="src" includes="**/*.java" /> 
 </replaceregexp>
4 голосов
/ 03 августа 2009

Связанное решение не должно быть сделано вручную. Имейте в виду, что атрибут package в элементе <manifest> не обязательно должен находиться там, где находится код, при условии, что вы указали полностью определенные классы в других местах манифеста (например, activity android:name="com.commonsware.android.MyActivity" вместо * 1004). *). Сценарий изменения манифеста и использовать Ant для создания нового APK. AFAIK, это должно работать.

2 голосов
/ 10 мая 2011

Поддержка нескольких партнеров Подготовьте config.xml

Построить проект для другого партнера

<!--partner.dir, pkg.name, ver.code, ver.name are input from command line when execute 'ant' -->

<!-- set global properties for this build -->
<property name="build.bin" location="bin"/>
<property name="build.gen" location="gen"/>
<property name="src" location="src"/>
<property name="res" location="res"/>

<target name="preparefiles" description="Prepare files for different partner" >
    <delete dir="${build.bin}" />
    <delete dir="${build.gen}" />

    <copy todir="${res}" overwrite="true" />
        <fileset dir="${partner.dir}/res" /> 
    </copy>

    <!-- change the import in all Java source files -->
    <replaceregexp file="AndroidManifest.xml"
        match='android.versionCode="(.*)"'
        replace='android.versionCode="${ver.code}"'
        byline="false">

    <replaceregexp file="AndroidManifest.xml"
        match='android.versionName="(.*)"'
        replace='android.versionName="${ver.name}"'
        byline="false">

    <replaceregexp file="AndroidManifest.xml"
        match='package="(.*)"'
        replace='package="${pkg.name}"'
        byline="false">

    <!-- change the package name in AndroidManifest -->
    <replaceregexp flags="g" byline="false">
        <regexp pattern="import(.*)com.myproject.com.R;" /> 
        <substitution expression="import com.${pkg.name}.R;" />
        <fileset dir="${src}" includes="**/*.java" /> 
    </replaceregexp>

    <replaceregexp flags="g" byline="false">
        <regexp pattern="(package com.myproject.com;)" /> 
        <substitution expression="\1&#10;import com.${pkg.name}.R;" />
        <fileset dir="${src}" includes="**/*.java" /> 
    </replaceregexp>
</target>

Подготовить файлы $ ant -f config.xml -Dpartner.dir = "xxx" -Dpkg.name = "xxx" -Dver.code = "xxx" -Dver.name = "xxx" preparefiles

Создать build.xml строить $ ant debug или же $ ant release

1 голос
/ 25 мая 2010

Я использую maven-android-plugin для достижения этой цели. Укажите один файл AndroidManifest.xml для цели генерируемых источников и другой файл AndroidManifest.xml для конечной цели apk. Таким образом, проект исходного кода сохраняет фактическое имя пакета исходного кода во время генерации класса R и фазы сборки, в то время как адаптированное к рынку имя пакета манифеста находится во втором AndroidManifest.xml, который включен в окончательный файл apk.

0 голосов
/ 05 декабря 2012

Я думаю, что лучший способ - это создать новый проект и скопировать материал. шаги, - создать новый проект Android без класса - создать пакет (имя пакета должно соответствовать указанному в файле манифеста) или просто скопировать имя пакета в папку 'gen' - скопировать файлы Java - скопировать нарисованные папки - скопируйте файлы макета - скопировать любые другие файлы, используемые в вашем проекте - скопировать данные файла манифеста

для меня это было проще для задачи

0 голосов
/ 03 апреля 2012

Я завел скрипт, который исправляет исходники; исправление источника звучит рискованно, но при наличии контроля версий риск приемлем.

Итак, я сделал одну версию, зафиксировал исходный код, сделал другую версию, зафиксировал исходный код и, глядя на diff, написал скрипт исправления на Python.

Я не уверен, что это лучшее решение. (И код пропускает некоторые os.path.joins)

Сердцем скрипта является следующая функция:

# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,mandatory=True):
    with open(fname, 'r+') as f:
    read_data = f.read()
    pattern = r"("+re.escape(before)+r")\w+("+re.escape(after)+r")"
    replacement = r"\1"+newtext+r"\2"
    new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
    if replacements_made and really:
        f.seek(0)
        f.truncate()
        f.write(new_data)
        if verbose:
            print "patching ",fname," (",replacements_made," occurrence", "s" if 1!=replacements_made else "",")"
    elif replacements_made:
        print fname,":"
        print new_data
    elif mandatory:
        raise Exception("cannot patch the file: "+fname)

И вы можете найти следующее:

# Change the application resource package name everywhere in the src/ tree.
# Yes, this changes the java files. We hope that if something goes wrong,
# the version control will save us.
def patchResourcePackageNameInSrc(pname):
    for root, dirs, files in os.walk('src'):
    if '.svn' in dirs:
        dirs.remove('.svn')
    for fname in files:
        fileReplace(os.path.join(root,fname),"import com.xyz.",pname,".R;",mandatory=False)

Существует также функция, которая копирует активы из x-assets-cfgname в assets (ранее оказалось, что для меня удобнее иметь подкаталог в assets).

def copyAssets(vname,force=False):
    assets_source = "x-assets-"+vname+"/xxx"
    assets_target = "assets/xxx"
    if not os.path.exists(assets_source):
        raise Exception("Invalid variant name: "+vname+" (the assets directory "+assets_source+" does not exist)")
    if os.path.exists(assets_target+"/.svn"):
        raise Exception("The assets directory must not be under version control! "+assets_target+"/.svn exists!")
    if os.path.exists(assets_target):
        shutil.rmtree(assets_target)
    shutil.copytree(assets_source, assets_target, ignore=shutil.ignore_patterns('.svn'))

Ну, вы поняли. Теперь вы можете написать свой собственный скрипт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...