Лучший способ получить платную и бесплатную версию приложения для Android


У меня уже есть бесплатное приложение в Android Market, но я хочу добавить платную версию с лучшими функциями. Я не могу загрузить то же самое с некоторыми измененными константами, чтобы разблокировать эти функции, поскольку рынок говорит мне, что у меня уже есть приложение с этим именем пакета на рынке.

что самый чистый способ сделать это?

9 59

9 ответов:

Android SDK формально решает проблему общей или общей кодовой базы с чем-то, что называется библиотечным проектом.

http://developer.android.com/tools/projects/index.html

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

во время сборки проекта библиотеки добавляется с любым из ваших релизов, который является то, что вы хотите.

пример исходного кода Android SDK содержит проект под названием TicTacToe, который поможет вам начать работу с использованием библиотечных проектов.

удачи.

Даниил

существует несколько подходов, но вы обычно не видите недостатков, пока не попробуете их для себя. Вот мой опыт:

  1. приложение Unlocker. Это очень легко реализовать, создайте новое приложение, которое действует как лицензия: ваше исходное приложение должно проверить, соответствует ли подпись приложения unlocker подписи вашего приложения (если да, то unlocker доступен на устройстве, в противном случае нет); ваш unlocker должен запрашивать загрузку бесплатного приложения, если оно не установлено, в противном случае запустите его и удалить его значок.

    плюсы: легко реализовать и есть только одна кодовая база для поддержания.
    плюсы: говорят, что пользователи иногда путают эту модель, они просто не понимают, почему у них две иконки запуска, или что они только что скачали. Удаление значка запуска является громоздким, изменения видны только при перезагрузке устройства. Кроме того, похоже, вы не сможете использовать API лицензирования Google (LVL), потому что ваш бесплатное приложение не может делать запросы на лицензирование от имени вашего платного приложения unlocker. Любое обходное решение для этого последнего приводит к плохому пользовательскому опыту.

  2. in-app purchase. Это легко реализовать, если у вас есть IAP в вашем коде в любом случае, в противном случае потребуется довольно много времени, чтобы все исправить.

    плюсы: существует только одна кодовая база для поддержания и покупки потока для пользователя довольно удобно.
    плюсы: пользователи говорят обеспокоенный тем, является ли их покупка "persisent", что означает, что они путают, могут ли они по-прежнему использовать функции pro, если они позже установили приложение на другое устройство или переустановили его.

  3. бесплатные и платные версии с общей библиотекой проекта. Это не должно быть трудно кодировать и кажется логичным решением иметь одну кодовую базу, содержащую большую часть логики вашего приложения, и поддерживать только различия.

    плюсы: пользователи меньше путают с этой моделью, но они, вероятно, обеспокоены тем, будут ли их предпочтения потеряны, если они начнут использовать платную версию.
    плюсы: Java / Eclipse по моему опыту не очень дружелюбен, когда речь заходит о библиотеках. Потребуется некоторое время, чтобы правильно настроить проекты, но все равно будет непонятно, как все это работает, что положить в какой манифест, что происходит с ресурсами и т. д. Вы столкнетесь с проблемами сборки с неверно настроенными проектами, построить проблемы с не найденными ресурсами (проект библиотеки не будет "видеть" уже упомянутые ресурсы, поэтому вам придется редактировать ссылки один за другим). Кроме того, файлы активов не поддерживаются в этой модели, что означает, что вам придется делать некоторые трюки с символической связью, копированием или другой магией, которая просто добавит к ужасному беспорядку ваш проект "single codebase" уже стал. И когда ваш проект, наконец, строит вы просто должны держать пальцы скрещенными для всего этого, чтобы работать, как ожидалось, быть подготовлено для отсутствующих изображений и скрытых ошибок для поиска. И, конечно же, вам нужно будет предоставить своим пользователям удобный способ переноса своих предпочтений в платную версию при первом запуске.

  4. бесплатные и платные версии с отдельными кодовыми базами и системой управления версиями. На первый взгляд это также кажется хорошей идеей, так как приличная система управления версиями может снять вес с ваших плеч, но...

    плюсы: же 3.
    плюсы: вы будете поддерживать две разные кодовые базы и ничего больше, кроме слияния/ветвления ада, который следует ожидать здесь. Имена пакетов приложений должны быть разными, поэтому вам, вероятно, нужно будет различать каждый файл, который у вас есть, чтобы держать вещи в чистоте. И, конечно же, вам нужно будет предоставить своим пользователям удобный способ переноса своих предпочтений в платную версию при первом запуске.

  5. бесплатные и платные версии со скриптом, который происходит один от другого. Оно звучит как грязный хак для выполнения, но вы точно знаете, что это работает.

    плюсы: так же, как 3 плюс вы поддерживаете только одну кодовую базу.
    плюсы: создание скриптов занимает немного времени (убедитесь, что вы переименовываете папки, заменяете имена пакетов, приложений и проектов), и вам нужно будет быть осторожным, чтобы обновлять свои скрипты время от времени, если это необходимо (это не произойдет, если нет слишком много различий между бесплатной и платной версиями). И, конечно же, вам нужно будет предоставить своим пользователям удобный способ переноса своих предпочтений в платную версию при первом запуске.

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

С системой сборки Gradle теперь вы можете иметь разные вкусы продукта, каждый из которых имеет свое собственное имя пакета. Ниже приведен пример сценария gradle, имеющий бесплатные и профессиональные вкусы одного и того же приложения.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "19.1"

    defaultConfig {
        applicationId "com.example.my.app"
    }

    productFlavors {
        free {
            applicationId "com.example.my.app"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 12
            versionName '12'
        }
        pro {
            applicationId "com.example.my.app.pro"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 4
            versionName '4'
        }
    }

R класс все равно будет сгенерирован в имени пакета, указанном в AndroidManifest.xml Так что вам не нужно менять ни одной строки кода при переключении вкусов.

вы можете переключить вкус от Build Variants панель, доступная из левого нижнего угла Android Studio. Кроме того, когда вы хотите создать подписанный APK, android studio спросит вас, какой вкус вы хотите создать APK.

кроме того, вы можете иметь различные ресурсы для каждого флейвора. Например, вы можете создать каталог pro в своем . Структура каталогов должна быть аналогична . (Например: если вы хотите иметь другой значок запуска для версии pro, вы можете разместить его в src\pro\res\drawable. Это заменит бесплатный значок, расположенный в src\main\res\drawable, когда вы переключились на pro вкус).

при создании strings.xml на pro каталог ресурсов описан выше, основной strings.xml и про strings.xml будет объединен, чтобы получить окончательный strings.xml при строительстве в pro вкусом. Если определенный строковый ключ существует как в свободном, так и в pro xml, строковое значение будет взято из pro xml.

Если вам нужно проверить, является ли текущая версия pro или бесплатной в коде, вы можете использовать такой метод, как следующий.

public boolean isPro() {
    return context.getPackageName().equals("com.example.my.app.pro");
}

дополнительную информацию см. этой

один исходный код два приложения (Eclipse)

существует повторяющаяся проблема управления приложением с двумя формами представления на рынке, возможно, только с одной разницей в битах между ними ( paidFor = true;), возможно, значок тоже отличается.

этот подход использует описание имен пакетов, объясненное Михаем в http://blog.javia.org/android-package-name/ что подчеркивает различие между именем пакета, используемым для управления источником код и имя пакета, используемого для публикации apk на Android Market. В этом примере двумя опубликованными именами пакетов являются com.вершина.суперпрограмма и com.вершина.superprogrampaid, имя пакета исходного кода Java-com.вершина.суперпрограмма.

в манифесте действия перечислены и названы как .ActivityName. Майк Уоллес отметил в своей недавней презентации, что предыдущая точка важна, и ее можно заменить полностью квалифицированным пакетом. Например "com.вершина.суперпрограмма.DialogManager" может заменить ".DialogManager" в манифесте.текст XML.

Шаг 1 заключается в замене всех записей activity android: name этими полными именами пакетов, используя имя пакета управления исходным кодом java (com.вершина.суперпрограмма).

тогда имя пакета Манифеста может быть изменено...

в Eclipse это заставляет перекомпилировать и новый R.java создается в папке gen. Вот где это становится немного сложнее; есть две папки com.вершина.суперпрограмма и com.вершина.superprogrampaid, только у одного есть R.java. Просто скопируйте R.java в другую папку, так что программа может решить R. макет.элементы xyz.

когда вы изменяете пакет в

Я пробовал его на несколько приложений. У меня есть оба работают вместе на эмуляторе, мой 2.1 телефон, и они оба на Android Market.

У меня была та же проблема, что я остановился на создании двух приложений для android, один называется my_epic_app_free, а другой my_epic_app_paid. То, что я бы сделал, это только внести изменения в платную версию, тогда у меня есть отдельная консольная программа java, все, что она делает, это доступ ко всем .java-файлы непосредственно с диска, скопируйте их в память, поиграйте с именами пакетов и строками манифеста, а затем вставьте их непосредственно в бесплатное приложение. У меня есть это на кнопке на рабочем столе, поэтому, когда я закончу разработку на платной версии я нажимаю кнопку, а затем компилирую бесплатную версию. У меня есть как платное приложение, так и бесплатное приложение для общения друг с другом, пользователь может даже установить их обоих, а бесплатная версия видит платную и разблокирует платную версию.

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

свободный приложение проверяет наличие ключевого файла платного приложения, и если он существует, то он будет разблокировать бесплатное приложение. Это предотвращает дублирование кода. Имена пакетов по-прежнему должны быть разными, но в идеале платное приложение не нужно будет часто менять.

преимущество: никакие пользовательские данные / настройки не теряются при" обновлении " до платной версии.

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

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

вот некоторые примеры файлов Gradle для упаковки модуля износа с ароматизаторами и типами зданий.

модуль Mobile build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 85
        versionName "2.5.2"
    }
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
            embedMicroApp = true
            minifyEnabled false
        }
        release {
            embedMicroApp = true
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            zipAlignEnabled true
        }
    }
    productFlavors {
        free{
            applicationId "com.example.app"
        }
        pro{
            applicationId "com.example.app.pro"
        }
    }
}

configurations {
    freeDebugWearApp
    proDebugWearApp
    freeReleaseWearApp
    proReleaseWearApp
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'

    freeDebugWearApp project(path: ':wear', configuration: 'freeDebug')
    proDebugWearApp project(path: ':wear', configuration: 'proDebug')

    freeReleaseWearApp project(path: ':wear', configuration: 'freeRelease')
    proReleaseWearApp project(path: ':wear', configuration: 'proRelease')
}

Износ Модуль build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    publishNonDefault true

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 20
        targetSdkVersion 23
        versionCode 85
        versionName "2.5.2"
    }
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
            minifyEnabled false
        }
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            zipAlignEnabled true
        }
    }
    productFlavors {
        free {
            applicationId "com.example.app"
        }
        pro {
            applicationId "com.example.app.pro"
        }
    }
}

dependencies {

    ...

}

Если вы не хотите использовать библиотечные проекты, и довольны рисками, которые несколько человек упомянули в комментариях, то @user426990 дал отличный ответ, в теории. Однако eclipse, похоже, стирает все содержимое каталога gen при выполнении новой сборки для экспорта (с которым мне трудно спорить в качестве общего принципа).

альтернативное решение, основанное на том же принципе, заключается в следующем, предполагая, что вы написали com.вершина.суперпрограмму и вы хотите создать com.вершина.superprogrampaid

  1. убедитесь, что ваш манифест указывает на действия, услуги и так далее по полному имени. Согласно ответу @user426990 ".CoolActivity " должен быть указан как com.вершина.суперпрограмма.CoolActivity

  2. создайте новый класс MyR в своем коде (com.деятельность.суперпрограмма, с остальной частью кода) следующим образом:

    package com.acme.superprogram;
    import com.acme.superprogram.R;
    
    public final class MyR {
        public final static R.attr     attr     = new R.attr();
        public final static R.color    color    = new R.color();
        public final static R.dimen    dimen    = new R.dimen();
        public final static R.layout   layout   = new R.layout();
        public final static R.id       id       = new R.id();
        public final static R.string   string   = new R.string();
        public final static R.drawable drawable = new R.drawable();
        public final static R.raw      raw      = new R.raw();
        public final static R.style    style    = new R.style();
        public final static R.xml      xml      = new R.xml();
    }
    

    вам нужно будет изменить точное содержание отражать ресурсы, которые вы используете! Например, вам может не понадобиться строка xml,а может понадобиться другая. Посмотрите на реальное R.java файл в gen/com/acme / superprogram, и вам понадобится одна строка для каждого класса. Возможно, Вам потребуется подкласс.

  3. теперь (a) удалить все "импорт com.вершина.суперпрограмма.R " строки из вашего кода и (b) заменить все "R." ссылки на "MyR.". Таким образом, все ваши ссылки на R опосредованы через одно место. недостатком является то, что все они получают предупреждения о нет быть достаточно статичным. У вас есть три варианта с этими предупреждениями: вы можете подавить их, вы можете игнорировать их, или вы можете сделать более полную версию MyR, со строкой для каждой записи в R, которую вы используете:

    package com.acme.superprogram;
    import com.acme.superprogram.R;
    
    public final class MyR {
        final static class attr {
            final static int XXXX = R.attr.XXXX
    // And so on ...
    
  4. согласно @user426990, теперь вы можете изменить пакет в манифесте из "com.вершина.суперпрограмма " to " com.вершина.superprogrampaid"; вы, вероятно, также хотите изменить имя, значок запуска и ключевые переменные при этом точка.

  5. изменение импорта в мире, чтобы импортировать com.вершина.суперпрограмма платная.R

и вы уходите.

ps. Не забудьте изменить имя файла в диалоговом окне окончательный экспорт ...

изменение имени пакета поможет.
Просто измените имя пакета вашего платного приложения с помощью eclipse и поставить его на рынок.

Это решит вашу проблему.

Почему бы не сделать два разных проекта в Eclipse? Это не так сложно исправить несколько вещей, относящихся к имени пакета вручную. Позаботьтесь о том, чтобы изменить инструкции импорта и файл манифеста. Вам нужно кодировать дважды в любом случае. Конечно, это неприятность, чтобы исправить код в обоих местах.

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

Рене