studio - La mejor forma de tener una versión paga y gratuita de una aplicación de Android
el mejor bloc de notas para android 2018 (9)
¿Por qué no hacer dos proyectos diferentes de Eclipse? No es tan difícil arreglar las pocas cosas que se refieren al nombre del paquete a mano. Tenga cuidado de cambiar las instrucciones de importación y el archivo de manifiesto. Necesitas codificar dos veces de todos modos. Por supuesto, es una molestia arreglar el código en ambos lugares.
La solución adecuada estaría en el mercado. Debería permitir dos aplicaciones con los mismos nombres de paquete, y solicitar reemplazar el uno cuando el otro se va a instalar. Una vez cargado, debe verificar si el nombre del paquete es realmente del mismo proveedor de software.
Rene
Ya tengo una aplicación gratuita en Android Market, pero quiero agregar una versión paga con mejores funciones. No puedo subir lo mismo con algunas constantes modificadas para desbloquear esas funciones, ya que Market me dice que ya tengo una aplicación con ese nombre de paquete en el mercado.
¿Cuál es la forma más limpia de hacer esto?
Cambiar el nombre del paquete ayudará.
Simplemente cambie el nombre del paquete de su aplicación paga usando eclipse y póngalo en el mercado.
Eso resolverá su problema.
Con el sistema de compilación Gradle, ahora puede tener diferentes sabores de producto, cada uno con su propio nombre de paquete. Lo que sigue es un script de ejemplo de gradle que tiene sabores gratuitos y pro de la misma aplicación.
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
clase R
aún se generará en el nombre del paquete especificado en AndroidManifest.xml
por lo que no es necesario cambiar una sola línea de código al cambiar de sabores.
Puede cambiar el sabor del panel Build Variants
que se puede acceder desde la esquina inferior izquierda de Android Studio. Además, cuando desee generar una APK firmada, el estudio de Android le preguntará el sabor que desea para crear la APK.
Además, puede tener diferentes recursos para cada sabor. Por ejemplo, puede crear un directorio pro
en su directorio src
. La estructura del directorio debe ser similar al directorio main
. (Por ejemplo, si desea tener un icono de iniciador diferente para la versión pro, puede colocarlo en src/pro/res/drawable
. Esto reemplazará el ícono gratuito ubicado en src/main/res/drawable
, cuando haya cambiado a pro
sabor).
Si creas un strings.xml
en el directorio de recursos pro
descrito anteriormente, los principales strings.xml
y pro strings.xml
se fusionarán para obtener un strings.xml
final cuando se construya en pro
flavor. Si existe una determinada clave de cadena en free y pro xml, el valor de cadena se tomará de pro xml.
Si necesita verificar si la versión actual es pro o gratuita en el código, puede usar un método como el siguiente.
public boolean isPro() {
return context.getPackageName().equals("com.example.my.app.pro");
}
Para obtener más información, consulte this
El SDK de Android aborda formalmente el problema de una base de código compartida o común con algo llamado proyecto de biblioteca.
http://developer.android.com/tools/projects/index.html
Básicamente, el código compartido se define como un proyecto de biblioteca, luego una versión paga y una versión gratuita son simplemente dos proyectos diferentes en su banco de trabajo eclipse, ambos referenciados al proyecto de biblioteca mencionado anteriormente.
En tiempo de compilación, el proyecto de la biblioteca se fusiona con cualquiera de sus versiones, que es lo que desea.
El código fuente del ejemplo de Android SDK contiene un proyecto llamado TicTacToe que lo ayudará a comenzar con el uso de proyectos de la biblioteca.
Buena suerte.
Daniel
En caso de que también tenga un módulo de desgaste, se necesita trabajo adicional.
Aquí hay algunos ejemplos de archivos Gradle para empaquetar un módulo de desgaste con sabores y tipos de construcción.
Módulo móvil 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'')
}
Módulo Wear 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 {
...
}
Existen varios enfoques, pero por lo general no se ven los inconvenientes hasta que los pruebes por ti mismo. Aquí están mis experiencias:
Aplicación de desbloqueo Esto es muy fácil de implementar, crea una nueva aplicación que actúa como licencia: tu aplicación original debería verificar si la firma de la aplicación desbloqueadora coincide con la de tu aplicación (en caso afirmativo, el desbloqueo está disponible en el dispositivo; de lo contrario, no); su desbloqueador debe solicitar la descarga de su aplicación gratuita si no está instalada; de lo contrario, iníciela y elimine su ícono del iniciador.
Pros: fácil de implementar y solo hay una base de código para mantener.
Contras: se dice que los usuarios a veces se confunden con este modelo, simplemente no entienden por qué tienen dos íconos de iniciador, o qué es lo que acaban de descargar. La eliminación de un icono del iniciador es engorrosa, los cambios solo son visibles si el dispositivo se reinicia. Además, parece que no podrá usar la API de licencias de Google (LVL), ya que su aplicación gratuita no puede realizar solicitudes de licencias en nombre de su aplicación de desbloqueo de pago. Cualquier solución para este último conduce a una mala experiencia del usuario.Aplicación en la compra. Esto es fácil de implementar si tiene IAP en su código de todos modos, de lo contrario tomará bastante tiempo hacer las cosas bien.
Pros: solo hay una base de código para mantener y el flujo de compras para el usuario es bastante conveniente.
Contras: se dice que los usuarios están preocupados acerca de si su compra es ''persistente'', lo que significa que están confundidos sobre si todavía podrían usar las características pro si luego instalaron la aplicación en otro dispositivo o la reinstalaron.Versiones gratuitas y de pago con proyecto de biblioteca compartida. Esto no debería ser una tarea difícil de codificar y parece una decisión lógica tener una única base de código que contenga la mayor parte de la lógica de la aplicación y mantener solo las diferencias.
Pros: los usuarios están menos confundidos con este modelo, pero probablemente estén preocupados sobre si sus preferencias se perderán si comienzan a usar la versión paga.
Contras: Java / Eclipse en mi experiencia no es realmente amigable cuando se trata de bibliotecas. Llevará algún tiempo configurar los proyectos correctamente, pero seguirá siendo confuso cómo funciona todo, qué poner en qué manifiesto, qué pasa con los recursos, etc. Te enfrentarás a problemas de compilación con proyectos mal configurados, problemas de compilación con no se encuentran recursos (el proyecto de la biblioteca no ''verá'' los recursos ya mencionados, por lo que tendrá que editar las referencias una a una). Además, los archivos de activos no son compatibles con este modelo, lo que significa que tendrás que hacer algunos trucos con enlaces simbólicos, copias u otra magia que simplemente aumentará el terrible desastre en el que se ha convertido tu proyecto de "base de código única". Y cuando tu proyecto finalmente se desarrolle, solo tienes que cruzar los dedos para que todo funcione como se espera, prepárate para las imágenes faltantes y los errores ocultos que debes buscar. Y, por supuesto, deberá proporcionar a sus usuarios una forma conveniente de migrar sus preferencias a la versión paga en el primer lanzamiento.Versiones gratuitas y de pago con bases de código separadas y control de fuente. A primera vista, esto también parece una buena idea ya que un sistema de control de fuente decente podría levantar peso de tus hombros pero ...
Pros: lo mismo que 3.
Contras: mantendrás dos bases de código diferentes y nada más que un infierno de fusión / ramificación que se espera aquí. Los nombres de los paquetes de aplicaciones deben ser diferentes, por lo que probablemente necesite diferenciar cada archivo que tenga para mantener las cosas limpias. Y, por supuesto, deberá proporcionar a sus usuarios una forma conveniente de migrar sus preferencias a la versión paga en el primer lanzamiento.Versiones gratuitas y de pago con un script que deriva uno del otro. Suena como un truco sucio para lograr, pero sabes con certeza que funciona.
Pros: al igual que 3 más, solo mantiene una única base de código.
Contras: la creación de los scripts requiere un poco de tiempo (asegúrese de cambiar el nombre de las carpetas, reemplazar el paquete, los nombres de las aplicaciones y los proyectos) y deberá tener cuidado de actualizar los scripts de vez en cuando si es necesario (esto no sucederá) si no hay demasiadas diferencias entre las versiones gratuitas y las pagadas). Y, por supuesto, deberá proporcionar a sus usuarios una forma conveniente de migrar sus preferencias a la versión paga en el primer lanzamiento.
Ninguna solución es perfecta, pero lo anterior puede, con suerte, orientarlo en la dirección correcta si está a punto de comenzar a implementar una de las posibilidades.
Si no desea utilizar proyectos de la biblioteca y está satisfecho con los riesgos que un par de personas han mencionado en los comentarios, entonces @ user426990 ha proporcionado una respuesta excelente, en teoría. Sin embargo, eclipse parece borrar todo el contenido del directorio gen al realizar una compilación nueva para exportar (lo que me resulta difícil argumentar como principio general).
Una solución alternativa, basada en el mismo principio, es la siguiente, asumiendo que ha escrito com.acme.superprogram y desea crear com.acme.superprogrampaid
Asegúrese de que su manifiesto indique las actividades, los servicios, etc., por nombre completo. Según la respuesta de @ user426990, ".CoolActivity" debe aparecer como com.acme.superprogram.CoolActivity
Cree una nueva clase MyR en su código (com.activity.superprogram, con el resto del código) de la siguiente manera:
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(); }
¡Deberá variar el contenido exacto para reflejar los recursos que usa! Por ejemplo, puede que no necesite la línea xml y puede necesitar otra. Mire el archivo real de R.java en gen / com / acme / superprogram y necesitará una línea por clase. Puede necesitar subclase.
Ahora (a) elimine todas las líneas "import com.acme.superprogram.R" de su código y (b) reemplace todas las "R." referencias a "MyR". De esta forma, todas sus referencias a R se indirectan en un solo lugar. el inconveniente es que todos reciben advertencias sobre no ser lo suficientemente estáticos. Tiene tres opciones con estas advertencias: puede suprimirlas, puede ignorarlas, o puede hacer una versión más completa de MyR, con una línea para cada entrada en R que utiliza:
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 ...
Según @ user426990, ahora puede cambiar el paquete en el manifiesto de "com.acme.superprogram" a "com.acme.superprogrampaid"; probablemente también desee cambiar el nombre, el icono de inicio y las variables clave en este punto.
Cambie la línea de importación en MyR para importar com.acme.superprogrampaid.R
Y lejos tu vas.
PD. Recuerde cambiar el nombre del archivo en el cuadro de diálogo de exportación final ...
Tuve el mismo problema, lo que decidí es crear dos aplicaciones para Android, una llamada my_epic_app_free y otra my_epic_app_paid. Lo que haría sería solo hacer cambios en la versión paga, luego tengo un programa de consola java por separado, todo lo que hace es acceder a todos los archivos .java directamente desde el disco, copiarlos en la memoria, manipular los nombres de los paquetes y las líneas de manifiesto. luego pégalos directamente en la aplicación gratuita. Tengo esto presionando un botón en el escritorio, así que cuando termine de desarrollar en la versión paga, presiono el botón, luego compilo la versión gratuita. Tengo tanto la aplicación paga como la aplicación gratuita que se comunican entre sí, el usuario puede incluso instalar ambas, y la versión gratuita ve el pago y se desbloquea en la versión paga.
Otra idea es hacer que la aplicación de pago sea solo un programa básico que contiene un archivo de claves. La aplicación paga, si se ejecuta, ejecutará automáticamente la versión gratuita, y la versión gratuita se comportará como la versión paga.
La aplicación gratuita verifica la presencia del archivo de clave de la aplicación paga y, si existe, desbloqueará la aplicación gratuita. Esto evita la duplicación de código. Los nombres de los paquetes aún tienen que ser diferentes, pero lo ideal es que la aplicación paga no tenga que cambiarse a menudo.
Ventaja: no se pierden datos / configuraciones de usuario cuando se "actualiza" a la versión paga.
Desventaja: si el usuario instala primero la versión paga, deberá dirigirse a instalar la versión gratuita, lo cual es una molestia, ¿por qué tienen que instalar dos aplicaciones para la versión paga?
Un código fuente dos aplicaciones (Eclipse)
Hay un problema recurrente de administrar una aplicación con dos formas de presentación en el mercado, tal vez con solo una diferencia de bit entre los dos (paidFor = true;) Quizás el ícono también sea diferente.
Este enfoque utiliza la descripción de los nombres de paquetes explicada por Mihai en http://blog.javia.org/android-package-name/ que subraya la distinción entre el nombre del paquete utilizado para administrar el código fuente y el nombre del paquete utilizado para publicar el apk en el Android Market. En este ejemplo, los dos nombres de paquetes publicados son com.acme.superprogram y com.acme.superprogrampaid, el nombre del paquete del código fuente de Java es com.acme.superprogram.
En el manifiesto, las Actividades se enumeran y se nombran como .ActivityName. Mike Wallace señaló en su reciente presentación que el punto anterior es importante y puede ser reemplazado por un paquete completamente calificado. Por ejemplo, "com.acme.superprogram.DialogManager" puede reemplazar ".DialogManager" en el texto manifest.xml.
El paso 1 consiste en reemplazar todas las actividades android: nombre de las entradas con estos nombres de paquetes totalmente calificados, utilizando el nombre del paquete java source code management (com.acme.superprogram).
Entonces el nombre del Manifiesto del paquete puede ser cambiado ...
En Eclipse esto obliga a recompilar y se crea un nuevo R.java en la carpeta gen. Aquí es donde se vuelve un poco complicado; hay dos carpetas com.acme.superprogram y com.acme.superprogrampaid, solo una tiene R.java. Simplemente copie R.java en la otra carpeta para que el programa pueda resolver los elementos de R.layout.xyz.
Cuando cambia el paquete en el
Lo he probado en un par de aplicaciones. Tengo ambos corriendo juntos en el emulador, mi teléfono 2.1 y ambos están en el Android Market.