Cómo utilizar ThreeTenABP en el proyecto Android
Estoy usando Android Studio 2.1.2 y mi configuración de Java es la siguiente:
>java -version
> openjdk version "1.8.0_91"
> OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~15.10.1-b14)
> OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
Busqué durante horas tratando de resolver esto. La respuesta provino de una combinación de respuestas relacionadas, así que pensé en documentar lo que aprendí para cualquier otra persona que pudiera tener dificultades. Ver respuesta.
Atención: esta respuesta, aunque técnicamente correcta, ya no está actualizada.
La compatibilidad con la eliminación de azúcar de la API de Java 8+ ahora está disponible a través del complemento Android Gradle 4.0.0+
(Vea también la respuesta de Basil Bourque a continuación )
El desarrollo de la biblioteca ThreeTenABP está llegando a su fin. Considere cambiar al complemento Android Gradle 4.0, java.time.*, y su función de desazucar de biblioteca principal en los próximos meses.
Para habilitar la compatibilidad con estas API de lenguaje en cualquier versión de la plataforma Android, actualice el complemento de Android a 4.0.0 (o superior) e incluya lo siguiente en el archivo build.gradle de su módulo (de esta sección de la página de soporte de Java 8 en Sitio de desarrolladores de Android , que también tiene información adicional sobre cómo desazucarar):
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
}
Respuesta original
Primer descubrimiento: por qué debe utilizar ThreeTenABP en lugar de java.time , ThreeTen-Backport o incluso Joda-Time
Esta es una versión realmente corta del MUY LARGO PROCESO de definir un nuevo estándar. Todos estos paquetes son más o menos lo mismo: bibliotecas que proporcionan una buena y moderna funcionalidad de manejo para Java. Las diferencias son sutiles pero importantes.
La solución más obvia sería utilizar el paquete integrado java.time
, ya que esta es la nueva forma estándar de manejar la hora y las fechas en Java. Es una implementación de JSR 310 , que fue una nueva propuesta de estándar para el manejo del tiempo basada en la biblioteca Joda-Time .
Sin embargo, java.time
se introdujo en Java 8 . Android hasta Marshmallow se ejecuta en Java 7 ("Android N" es la primera versión que introduce las funciones del lenguaje Java 8). Por lo tanto, a menos que solo esté apuntando a Android N Nougat y superior, no puede confiar en las características del lenguaje Java 8 (no estoy realmente seguro de que esto sea 100% cierto, pero así es como lo entiendo). Así que java.time
está fuera.
La siguiente opción podría ser Joda-Time , ya que JSR 310 se basó en Joda-Time. Sin embargo, como indica el archivo Léame de ThreeTenABP , por varias razones, Joda-Time no es la mejor opción.
El siguiente es ThreeTen-Backport , que traslada gran parte (pero no toda) de la java.time
funcionalidad de Java 8 a Java 7. Esto está bien para la mayoría de los casos de uso, pero, como se indica en el archivo Léame de ThreeTenABP , tiene problemas de rendimiento con Android.
Entonces la última opción y aparentemente correcta es ThreeTenABP .
Segundo descubrimiento: herramientas de compilación y gestión de dependencias
Dado que compilar un programa (especialmente uno que utiliza un montón de bibliotecas externas) es complejo, Java casi invariablemente utiliza una "herramienta de compilación" para gestionar el proceso. Make , Apache Ant , Apache Maven y Gradle son herramientas de compilación que se utilizan con programas Java (consulte esta publicación para ver comparaciones). Como se indica más adelante, Gradle es la herramienta de compilación elegida para proyectos de Android.
Estas herramientas de compilación incluyen la gestión de dependencias. Apache Maven parece ser el primero en incluir un repositorio de paquetes centralizado. Maven presentó el Repositorio Central de Maven , que permite una funcionalidad equivalente a php composer
con Packagist y Ruby gem
con rubygems.org. En otras palabras, el Repositorio Central de Maven es para Maven (y Gradle) lo que Packagist es para Composer: una fuente definitiva y segura para paquetes versionados.
Tercer descubrimiento: Gradle maneja las dependencias en proyectos de Android
Una de mis prioridades en la lista de tareas pendientes es leer los documentos de Gradle aquí , incluidos sus libros electrónicos gratuitos. Si hubiera leído estas semanas cuando comencé a aprender Android, seguramente habría sabido que Gradle puede usar el Repositorio Central de Maven para administrar dependencias en Proyectos de Android. Además, como se detalla en esta respuesta de StackOverflow, a partir de Android Studio 0.8.9, Gradle usa el repositorio central de Maven implícitamente a través del JCenter de Bintray, lo que significa que no tiene que realizar ninguna configuración adicional para configurar el repositorio: simplemente enumera el dependencias.
Cuarto descubrimiento: las dependencias del proyecto se enumeran en [directorio del proyecto]/app/build.gradle
Nuevamente, es obvio para aquellos que tienen alguna experiencia en el uso de Gradle en Java, pero me tomó un tiempo darme cuenta de esto. Si ve gente que dice "Oh, simplemente agregue compile 'this-or-that.jar'
" o algo similar, sepa que compile
hay una directiva en ese archivo build.gradle que indica dependencias en tiempo de compilación. Aquí está la página oficial de Gradle sobre gestión de dependencias.
Quinto descubrimiento: ThreeTenABP está gestionado por Jake Wharton, no por ThreeTen
Otro problema más en el que pasé demasiado tiempo resolviendo. Si busca ThreeTen en Maven Central, solo verá paquetes para threetenbp
, no para threetenabp
. Si va al repositorio de github de ThreeTenABP , verá esa infame compile 'this-or-that'
línea en la sección Descargar del archivo Léame.
Cuando accedí por primera vez a este repositorio de github, no sabía qué significaba esa línea de compilación e intenté ejecutarla en mi terminal (con un error obvio y predecible). Frustrado, no volví a él hasta mucho después de que descubrí el resto y finalmente me di cuenta de que es una línea de Maven Repo que apunta al com.jakewharton.threetenabp
repositorio, a diferencia del org.threeten
repositorio. Por eso pensé que el paquete ThreeTenABP no estaba en el repositorio de Maven.
Resumen: Hacer que funcione
Ahora todo parece bastante fácil. Puede obtener funciones de manejo modernas en un proyecto de Android asegurándose de que su [project folder]/app/build.gradle
archivo tenga la implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
línea en su dependencies
sección:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "me.ahuman.myapp"
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:23.4.0'
implementation 'com.android.support:design:23.4.0'
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
}
También agregue esto a la clase de Aplicación:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
AndroidThreeTen.init(this);
//...
}
}
La respuesta aceptada por kael es correcta. Además, mencionaré un par de cosas y proporcionaré un diagrama sobre cómo obtener la funcionalidad java.time .
java.time integrado en Android 26+
Si apunta a Android 26 o posterior, encontrará una implementación de JSR 310 ( clases java.time ) incluida con Android. No es necesario agregar ThreeTenABP .
API casi idénticas
Solo para aclarar, ThreeTenABP para Android es una adaptación de la biblioteca ThreeTen-Backport que trae la mayor parte de la funcionalidad java.time a Java 6 y Java 7 . Este back-port comparte una API casi idéntica con java.time .
Supongamos que ahora está apuntando a Android anterior a 26, por lo que usa ThreeTenABP . Más adelante, es posible que eventualmente dejes de admitir estas versiones anteriores de Android para usar las clases java.time incluidas con Android. Cuando eso sucede, necesita realizar algunos cambios en su código base además de (a) cambiar import
declaraciones y (b) cambiar cualquier llamada que haya realizado org.threeten.bp.DateTimeUtils
para usar los nuevos métodos de conversión que se agregaron a las antiguas clases heredadas de fecha y hora ( Date
, GregorianCalendar
) . .
El proceso de transición de ThreeTenABP a java.time debería ser sencillo y casi indoloro.
Cuándo usar qué marco
Aquí hay un gráfico que muestra los tres marcos e indica cuándo usar cuál y en qué escenarios.
➥ Actualización: Android Gradle Plugin 4.0.0+ trae una nueva cuarta opción, API desazucaring para poner a disposición un subconjunto de la funcionalidad java.time que no estaba integrada originalmente en Android anterior. Vea la parte superior de la respuesta principal de kael.
Acerca de java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases reemplazan a las antiguas y problemáticas clases de fecha y hora heredadas , como java.util.Date
, Calendar
y SimpleDateFormat
.
Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*
clases. Hibernate 5 y JPA 2.2 admiten java.time .
¿Dónde obtener las clases java.time?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 y posteriores: parte de la API de Java estándar con una implementación incluida.
- Java 9 trajo algunas características y correcciones menores.
- Java SE 6 y Java SE 7
- La mayor parte de la funcionalidad java.time está adaptada a Java 6 y 7 en ThreeTen-Backport .
- Androide
- Versiones posteriores de implementaciones de paquetes de Android (26+) de las clases java.time .
- Para Android anterior (<26), el proceso de eliminación de azúcar de API aporta un subconjunto de la funcionalidad java.time que no estaba integrada originalmente en Android.
- Si el desazucar no ofrece lo que necesitas, el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) a Android. Consulte Cómo utilizar ThreeTenABP… .
Agregue lo siguiente en su archivo de compilación gradle (nivel de módulo) en Android Studio:
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
Cree la clase Aplicación e inicialícela así:
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}