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

Android - несколько пользовательских версий одного и того же приложения

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

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

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

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

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

4b9b3361

Ответ 1

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

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

android.library=true

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

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

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

Скопировать через манифест из исходного каталога:

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

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

Если вы просто запустите скрипты ant build, вы можете сделать это. (Мне нужно было просто настроить подписывающие ключи.)

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

  • Откройте исходный проект, поднимите настройки проекта, выберите свой Facet и отметьте "Проект библиотеки" и сохраните.
  • Откройте вариант проекта, выберите "Настройки проекта", выберите "Модули"
  • Добавить модуль
  • Выберите "Импортировать существующий модуль"
  • Перейдите в каталог Original (myOrigApp) и выберите его .iml файл (исходный файл проекта IntelliJ).
  • Нажмите "Готово". (Проект библиотеки добавляется как модуль в рамках варианта проекта.)
  • В списке модулей щелкните по проекту "Вариант", чтобы выбрать его.
  • С правой стороны выберите вкладку "Зависимости".
  • Нажмите "Добавить..."
  • Выберите "зависимость модуля..." (должен появиться список, который включает имя модуля/библиотеки, которое вы ранее добавили в проект, возможно, единственная запись в списке).
  • Выберите проект библиотеки, который вы добавили, и нажмите OK. (Он будет добавлен в список зависимостей вашего проекта.)
  • Нажмите OK, чтобы завершить настройку проекта. (Вы должны увидеть 2 модуля с доступными и доступными библиотечными ресурсами и классами в проекте Variant.)

Ответ 2

Что я сделал для чего-то похожего, так это просто использовать задачу 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>

Ответ 3

Вы определенно хотите использовать Gradle flavors, который исходит, даже поощряется, в Android Studio.

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

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

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

Ответ 4

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

Ответ 5

Поддержка нескольких партнеров Подготовьте 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

Ответ 6

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

Ответ 7

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

Итак, я сделал одну версию, зафиксировал источник, сделал другую версию, передал источник, и, глядя на diffs, написал патч script в Python.

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

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

# 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'))

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

Ответ 8

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

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