2009-08-03 13 views
45

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

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

This is one solution for this problem, but that has to be done by hand

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

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

+0

Я ответил на аналогичный вопрос здесь, возможно, он может вам тоже помочь: http://stackoverflow.com/questions/16840127/how-to-install-the-same-app-twice-without-interference/21332803 # 21332803 –

+2

Принятый ответ немного устарел. Есть один, который вывешен краном, который, вероятно, теперь правильный способ сделать это. – Darthg8r

+0

Вы ** определенно ** хотите использовать ['Gradle' flavors] (http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors), который происходит изначально, даже в Android Studio. – craned

ответ

23

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

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

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»; это единственное изменение.

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

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

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

кредит на http://soledadpenades.com/2011/06/17/android-library-projects-with-intellij-idea/ для шагов Idea – larham1

+0

Я считаю, что это решение не существовало в то время, но оно определенно лучше, чем через исходные файлы с регулярными выражениями. Раньше я использовал решение Prashast, и он работал хорошо. Но для новых проектов я выступаю за проект библиотеки. –

+0

Мне нравится это решение waaaay лучше, чем изменять десятки исходных файлов (кошмар контроля источника!). –

4

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

+7

Это уничтожает автоматически сгенерированный файл R. Таким образом, вам нужно пройти более или менее все исходные файлы и изменить импорт файла R (пункт 8). –

+0

Ах. Хорошая точка зрения. Все еще написано, просто больнее. – CommonsWare

+0

Мы решили проблему R. импорт старый.package.string. *; импорт новый.package.string. *; Это просто импортирует R для обоих сборок. – Fedor

6

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

Это решило мою проблему, спасибо. Теперь я использую два replaceregexp. Один из них точно так же, как ваш, и другой для замены имени пакета в AndroidManifest.xml. –

+0

Не работает для меня, потому что все исходные файлы все еще находятся в структуре каталогов, соответствующей старому имени пакета. Как вы это решили? – Matthias

+0

Для меня исходное местоположение файла не имело значения. Пока у них есть правильная информация о пакете. Открытие его в Eclipse может не работать. Я использовал это только с сборкой муравьев и использовал сгенерированный файл apk. – Prashast

1

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

2

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

Подготовка файлов $ муравей -f config.xml -Dpartner.dir = "ххх "-Dpkg.name =" xxx "-Dver.code =" xxx "-Dver.name =" xxx "readyfiles

Создать build.xml Сложение $ муравей отлаживать или $ муравей релиз

+0

это хорошо, если вы работаете только с муравьем. , если вы работаете в eclipse, после запуска regexp u может работать, но если вы измените ресурс, вы снова застрянете. – codeScriber

+0

В файле были некоторые незначительные проблемы, но в целом хорошая идея! Я скопировал это и немного изменил его для использования в клиентском проекте. Благодаря! – BrianPlummer

0

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

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

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

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

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

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

0

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

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

5

Вам определенно хотите использовать Gradle flavors, который исходит, рекомендуется даже на A Студия ndroid.

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

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

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

+0

Это путь. +1 –

Смежные вопросы