Cómo usar ThreeTenABP en Android Project

193

Estoy haciendo esta pregunta porque soy nuevo en Java y Android y busqué durante horas tratando de resolver esto. La respuesta vino de una combinación de respuestas relacionadas, así que pensé que documentaría lo que aprendí para cualquier otra persona que pueda estar luchando. Ver respuesta.

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)
kael
fuente

Respuestas:

192

Atención: soporte de desaplanado de API Java 8+ (Android Gradle Plugin 4.0.0+)

El desarrollo en esta biblioteca ( ThreeTenABP ) está terminando. Considere la posibilidad de cambiar a Android Gradle plugin 4.0, java.time. *, Y su función principal de eliminación de bibliotecas en los próximos meses.

Para habilitar la compatibilidad con estas API de idiomas 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:

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'
}

Primer descubrimiento: por qué debe usar ThreeTenABP en lugar de java.time , ThreeTen-Backport o incluso Joda-Time

Esta es una versión realmente corta del PROCESO MUY LARGO de definir un nuevo estándar. Todos estos paquetes son más o menos lo mismo: bibliotecas que proporcionan una funcionalidad de manejo moderna y buena para Java. Las diferencias son sutiles pero importantes.

La solución más obvia sería usar el java.timepaquete integrado , 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 era una nueva propuesta estándar para el manejo del tiempo basada en la biblioteca Joda-Time .

Sin embargo, java.timese introdujo en Java 8 . Android hasta Marshmallow se ejecuta en Java 7 ("Android N" es la primera versión en introducir las características 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 (en realidad no estoy seguro de que esto sea 100% cierto, pero así es como lo entiendo). Así java.timeestá 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 transfiere gran parte (pero no toda) de la java.timefuncionalidad 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 y aparentemente correcta opción es ThreeTenABP .

Segundo descubrimiento: herramientas de compilación y gestión de dependencias

Dado que compilar un programa, especialmente uno que usa un montón de bibliotecas externas, es complejo, Java casi siempre usa una "herramienta de compilación" para administrar 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 señaló más abajo, Gradle es la herramienta de compilación elegida para proyectos de Android.

Estas herramientas de compilación incluyen 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's composercon Packagist y Ruby's gemcon rubygems.org. En otras palabras, el repositorio central de Maven es para Maven (y Gradle) lo que Packagist es para componer: una fuente definitiva y segura para paquetes versionados.

Tercer descubrimiento: Gradle maneja las dependencias en proyectos de Android

Lo más importante en mi 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 depósito 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 utiliza el repositorio central de Maven implícitamente a través del JCenter de Bintray, lo que significa que no tiene que hacer ninguna configuración adicional para configurar el repositorio: solo debe enumerar el dependencias

Cuarto descubrimiento: las dependencias del proyecto se enumeran en [dir del proyecto] /app/build.gradle

Una vez más, es obvio para aquellos que tienen experiencia en el uso de Gradle en Java, pero me tomó un tiempo resolver esto. Si ve personas que dicen "Oh, solo agregue compile 'this-or-that.jar'" o algo similar, sepa que compilehay 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 es administrado por Jake Wharton, no por ThreeTen

Otro problema que pasé demasiado tiempo resolviendo. Si busca ThreeTen en Maven Central, solo verá paquetes para threetenbp, no threetenabp. Si va al repositorio de Github para ThreeTenABP , verá esa compile 'this-or-that'línea infame en la sección Descargar del archivo Léame.

Cuando llegué 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 eso 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.threetenabprepositorio, en oposición al org.threetenrepositorio. Es por eso que 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 modernas de manejo de tiempos en un proyecto de Android asegurándose de que su [project folder]/app/build.gradlearchivo tenga la implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'línea en su dependenciessecció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'
}

Agregue también esto a la clase de aplicación:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
kael
fuente
1
Gracias por la gran publicación. Sin embargo, me pregunto si también ha considerado JodaTimeAndroid .
Bob
@Bob, no he experimentado con JodaTimeAndroid, pero solo porque realmente no estoy trabajando en nada en este momento que lo requiera. Por lo que recuerdo, la java.timeimplementación estuvo bien (siendo básicamente un puerto de JodaTime), y estoy seguro de que en uno o dos años más, el 90% de los usuarios estarán en Nougat +, por lo que es una solución viable para el desarrollo.
kael
2
@Bob, JodaTime es básicamente lo mismo que JSR-310 (incluso básicamente hecho por los mismos chicos), excepto que JSR-310 supuestamente tiene menos fallas de diseño (ver este artículo , por ejemplo). [... continúa abajo]
M. Prokhorov
2
Para aclarar los comentarios ... El marco java.time ( JSR 310 ) es el sucesor oficial del proyecto Joda-Time . Ambos proyectos están dirigidos por el mismo hombre, Stephen Colebourne . El proyecto Joda-Time ahora está en modo de mantenimiento, y el equipo aconseja migrar a java.time.
Basil Bourque
66
Asegúrate de que llamar AndroidThreeTen.init(this)antes de usar la API, por ejemplo, en onCreate().Ver error ThreeTen-Backport en Android - ZoneRulesException: archivos de datos de zona horaria no está registrado .
Ole VV
5

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 puerto trasero comparte una API casi idéntica con java.time .

Supongamos que ahora está apuntando a Android antes de 26, por lo que usa ThreeTenABP . Más tarde, eventualmente puede dejar de admitir estas versiones anteriores de Android, para usar las clases java.time incluidas con Android. Cuando eso suceda, debe realizar algunos cambios en su base de código que no sea (a) cambiar las importdeclaraciones y (b) cambiar las llamadas que realizó org.threeten.bp.DateTimeUtilspara usar los nuevos métodos de conversión que se agregaron a las antiguas clases de fecha y hora heredadas (Date , GregorianCalendar) .

El proceso de transición de ThreeTenABP a java.time debería ser suave 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 en qué escenarios.

➥ Actualización: Android Gradle Plugin 4.0.0+ trae una nueva cuarta opción, API desugaring para poner a disposición un subconjunto de la funcionalidad java.time que originalmente no estaba integrada en Android anterior. Vea la parte superior de la respuesta principal de kael.

Tabla de qué biblioteca java.time usar con qué versión de Java o Android


Sobre java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora 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 .

Puedes intercambiar java.time objetos 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?

Albahaca Bourque
fuente
4

Agregue lo siguiente en su archivo gradle de compilación 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)
    }
}
Richard Kamere
fuente