ThreeTenABP ist eine Adapterbibliothek für Android, die die java.time-API (Paket org.threeten.bp) auf Geräten mit Android unter 8 (API < 26) bereitstellt. Laut der Spezifikation von Jake Wharton (GitHub, 2023) ist die Bibliothek ein Wrapper um das ThreeTen-Backport-Projekt, das für Android mit Ressourcenoptimierung und tzdata-Unterstützung über AssetManager angepasst wurde.
Wichtige Punkte
ThreeTenABP (ThreeTen Android Backport) ist eine von Jake Wharton erstellte Bibliothek zur Verwendung der Java 8 Datums-/Zeit-API auf älteren Android-Versionen. Sie ist ein Adapter für das ThreeTen-Backport-Projekt, das java.time (JSR-310) auf Java 7 und Android API < 26 portiert.
Das Hauptproblem, das die Bibliothek löst: Android vor Version 8 (API 26) enthielt java.time nicht in der Standarddistribution. Entwickler waren gezwungen, java.util.Date/Calendar zu verwenden oder Joda-Time hinzuzufügen. ThreeTenABP bietet dieselbe moderne API wie integriertes java.time, aber über das Paket org.threeten.bp.
Laut dem GitHub-Repository (2023) ist die Bibliothek für Android optimiert: tzdata (IANA Time Zone Database) wird in Assets gespeichert und über AssetManager geladen, anstatt über Classpath wie auf dem Desktop. Dies reduziert die APK-Größe und beschleunigt das Laden.
Die neueste stabile Version ist 1.4.0 (August 2021). Die Bibliothek befindet sich im Wartungsmodus, da mit der weit verbreiteten Einführung von Desugaring die Notwendigkeit dafür abnimmt, aber sie bleibt für Projekte mit minimaler API < 26 relevant.
Bevor java.time in Java 8 (2014) eingeführt wurde, verwendeten Entwickler java.util.Date und java.util.Calendar. Diese Klassen haben schwerwiegende Nachteile: Date ist veränderbar, Calendar verwendet nicht intuitive Konstanten (Calendar.JANUARY = 0), beide Klassen sind nicht threadsicher und neigen zu Fehlern bei der Arbeit mit Zeitzonen.
Joda-Time war vor Java 8 der De-facto-Standard, aber sein Schöpfer Stephen Colebourne entwarf java.time als offiziellen Ersatz, basierend auf den Erfahrungen mit Joda-Time und unter Berücksichtigung seiner Mängel. Das java.time-Paket war in JDK 8 enthalten, aber Android erhielt es erst mit API 26.
ThreeTen-Backport ist ein Port von java.time auf Java 7, erstellt vom selben Autor (Stephen Colebourne). Es enthält alle wichtigen Klassen: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period, DateTimeFormatter. ThreeTenABP passt diesen Port für Android an, indem es Initialisierung über AssetsManager und Optimierung für mobile Geräte hinzufügt.
Somit ermöglicht ThreeTenABP die Verwendung der modernen Datums-/Zeit-API auf Geräten mit Android 4.0+ (API 14+) ohne auf ein OS-Update warten zu müssen.
Das Hinzufügen erfolgt in zwei Schritten: Abhängigkeit in build.gradle (App-Ebene) hinzufügen und in der Application-Klasse initialisieren. Wichtig: ThreeTenABP benötigt compileSdk von mindestens 21 und Gradle-Version von mindestens 4.0.
Die Abhängigkeit wird im Abschnitt dependencies hinzugefügt: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0". Seit der Veröffentlichung von 1.4.0 wurde die Bibliothek nicht aktualisiert, da sie stabil ist und alle notwendigen Fälle abdeckt.
Laut der offiziellen Dokumentation enthält die Bibliothek tzdata in Assets. Wenn die App bereits einen Assets-Ordner mit anderen Dateien hat, koexistiert ThreeTenABP korrekt mit ihnen. Die Größe von tzdata beträgt komprimiert etwa 200 KB.
// build.gradle (App-Ebene)
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
}
Bevor Sie eine Klasse aus org.threeten.bp verwenden, muss die Bibliothek initialisiert werden. Die Initialisierung erfolgt einmal in Application.onCreate() durch Aufruf von AndroidThreeTen.init(this).
Die Initialisierung lädt tzdata-Daten aus Assets und konfiguriert die Systemuhr. Ohne Aufruf von init() werfen die now()-Methoden eine IllegalStateException mit der Meldung, dass die Bibliothek nicht initialisiert ist.
Für Tests können Sie AndroidThreeTen.init(applicationContext, zoneId) verwenden — eine Überladung mit expliziter Zeitzonenangabe. Dies ist nützlich für vorhersagbares Testverhalten. Wenn nur eine Basisinitialisierung ohne tzdata benötigt wird, verwenden Sie AndroidThreeTen.initWithoutFiles(context).
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// Verwendung nach Initialisierung
val today = LocalDate.now()
val now = LocalDateTime.now()
ThreeTenABP stellt alle wichtigen java.time-Klassen im Paket org.threeten.bp bereit. Die API ist praktisch identisch mit dem originalen java.time, was die Migration bei einem Wechsel zu API 26+ erleichtert.
Hauptklassen:
Hilfsklassen werden ebenfalls unterstützt: Clock, DayOfWeek, Month, Year, YearMonth, MonthDay. Die Zeitzonen sind in der Bibliothek enthalten (IANA tzdata). Die tzdata-Version in ThreeTenABP 1.4.0 entspricht 2021a.
Ab Android Gradle Plugin 4.0 (2020) und desugar_jdk_libs erhalten Entwickler die Möglichkeit, java.time auf allen Android-Versionen über coreLibraryDesugaring zu verwenden. Desugaring transformiert Bytecode, sodass java.time-Aufrufe auf älteren APIs ohne zusätzliche Bibliotheken funktionieren.
Vorteile von Desugaring: Verwendet das originale java.time-Paket (nicht org.threeten.bp), keine Initialisierung erforderlich, vollständige Integration mit Android Studio. Nachteile: Erfordert AGP 4.0+, verlängert die Build-Zeit, die APK-Größe kann um 2-3 MB steigen.
ThreeTenABP bleibt die beste Wahl für Legacy-Projekte, die AGP nicht auf 4.0+ aktualisieren können, oder wenn die APK-Größe kritisch ist. ThreeTenABP ist auch einfacher einzurichten — nur eine Abhängigkeit und eine Zeile Initialisierung. Laut Stack Overflow (2024) verwenden etwa 30% der Projekte mit minSdk < 26 immer noch ThreeTenABP anstelle von Desugaring.
Das erste Beispiel demonstriert die Arbeit mit Daten unter Verwendung von ThreeTenABP. Die API ist identisch mit java.time, aber die Importe stammen aus org.threeten.bp. Dies ermöglicht das Schreiben von Code, der nach der Migration nur den Austausch der Importe erfordert.
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalTime
import org.threeten.bp.Duration
fun isWeekend(date: LocalDate): Boolean {
val dayOfWeek = date.getDayOfWeek()
return dayOfWeek == DayOfWeek.SATURDAY ||
dayOfWeek == DayOfWeek.SUNDAY
}
fun timeBetween(
start: LocalTime, end: LocalTime
): Duration {
return Duration.between(start, end)
}
Das zweite Beispiel zeigt die Datumsformatierung. DateTimeFormatter aus org.threeten.bp funktioniert genauso wie in java.time.
import org.threeten.bp.LocalDateTime
import org.threeten.bp.format.DateTimeFormatter
fun formatTimestamp(dateTime: LocalDateTime): String {
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
return dateTime.format(formatter)
}
Das dritte Beispiel demonstriert die Arbeit mit ZonedDateTime und die Konvertierung zwischen Zeitzonen in ThreeTenABP.
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.ZoneId
fun convertTimeZone(
time: ZonedDateTime,
targetZone: ZoneId
): ZonedDateTime {
return time.withZoneSameInstant(targetZone)
}
Wenn Sie minSdk auf 26 erhöhen, können Sie ThreeTenABP entfernen und auf integriertes java.time umsteigen. Der Migrationsprozess umfasst mehrere Schritte und erfordert gründliche Tests.
Der erste Schritt ist der Austausch der Importe. Importe von org.threeten.bp werden zu java.time geändert. In den meisten Fällen stimmen die Klassennamen überein: LocalDate → java.time.LocalDate, ZonedDateTime → java.time.ZonedDateTime. Die Ausnahme ist DateTimeFormatter — in ThreeTenABP befindet es sich in org.threeten.bp.format, in java.time in java.time.format.
Der zweite Schritt ist das Entfernen der Initialisierung. Die Zeile AndroidThreeTen.init(this) wird nicht mehr benötigt, da java.time in das Android SDK integriert ist. Entfernen Sie den Aufruf aus Application.onCreate() und die Abhängigkeit aus build.gradle.
Der dritte Schritt ist das Ersetzen der Abhängigkeit durch Desugaring, wenn minSdk unter 26 bleibt. Fügen Sie isCoreLibraryDesugaringEnabled = true in compileOptions und die Abhängigkeit desugar_jdk_libs hinzu. Dies stellt sicher, dass java.time auf älteren APIs ohne ThreeTenABP funktioniert. Laut Google I/O (2023) ist Desugaring der bevorzugte Ansatz für neue Projekte.
// build.gradle — ThreeTenABP durch Desugaring ersetzen
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
// Entfernen: implementation "com.jakewharton.threetenabp:threetenabp:1.4.0"
// Hinzufügen:
"coreLibraryDesugaring"("com.android.tools:desugar_jdk_libs:2.1.4")
}
// AndroidThreeTen.init(this) aus Application entfernen
Häufig gestellte Fragen
Technisch gesehen — ja, aber es macht keinen Sinn. Wenn Desugaring verwendet wird, ist integriertes java.time bereits verfügbar. Die Verwendung beider Bibliotheken führt zu Code-Duplizierung und erhöhter APK-Größe. Wählen Sie einen Ansatz für Ihr Projekt.
Die Initialisierung lädt die IANA Time Zone Database aus Assets in den Speicher. Auf Standard-JDK ist tzdata über Classpath verfügbar, aber Android verwendet AssetManager. Die init()-Methode kopiert Daten in das Systemverzeichnis und macht sie für ZoneId verfügbar.
ThreeTenABP unterstützt API 14+ (Android 4.0 Ice Cream Sandwich und höher). Java 8-Kompatibilität ist erforderlich (sourceCompatibility und targetCompatibility in compileOptions). Auf API 26+ wird die Bibliothek nicht benötigt — verwenden Sie integriertes java.time.
Die Zeitzonen sind in der Bibliothek enthalten. Version 1.4.0 enthält tzdata 2021a. Zum Aktualisieren müssen Sie die ThreeTenABP-Version aktualisieren oder tzdata manuell in Assets ersetzen. Die neuesten tzdata-Versionen können aus dem IANA-Repository oder über ThreeTen-Backport bezogen werden.
Für Unit-Tests verwenden Sie AndroidThreeTen.init(context, zoneId) mit expliziter Zonenangabe. Für Robolectric-Tests — AndroidThreeTen.init(ApplicationProvider.getApplicationContext()). Für reine JVM-Tests ohne Android — verwenden Sie ThreeTen-Backport direkt ohne ThreeTenABP.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch