Como usar o ThreeTenABP no projeto Android

Aug 12 2016

Estou fazendo esta pergunta porque sou novo em Java e Android e procurei por horas tentando descobrir isso. A resposta veio de uma combinação de respostas relacionadas, então decidi documentar o que aprendi para qualquer outra pessoa que possa estar tendo dificuldades. Ver resposta.

Estou usando o Android Studio 2.1.2 e minha configuração Java é a seguinte:

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

Respostas

200 kael Aug 12 2016 at 23:36

Atenção: esta resposta, embora tecnicamente correta, agora está desatualizada

Suporte de desugaring Java 8+ API agora disponível via Android Gradle Plugin 4.0.0+

(Veja também a resposta de Basil Bourque abaixo )

O desenvolvimento na Biblioteca ThreeTenABP está sendo encerrado. Considere mudar para o plugin Android Gradle 4.0, java.time. *, E seu recurso de remoção de biblioteca principal nos próximos meses.

Para ativar o suporte para essas APIs de idioma em qualquer versão da plataforma Android, atualize o plug-in Android para 4.0.0 (ou superior) e inclua o seguinte no arquivo build.gradle do seu 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'
}

Resposta Original

Primeira descoberta: por que você precisa usar ThreeTenABP em vez de java.time , ThreeTen-Backport ou mesmo Joda-Time

Esta é uma versão realmente curta do PROCESSO MUITO LONGO de definição de um novo padrão. Todos esses pacotes são praticamente a mesma coisa: bibliotecas que fornecem funcionalidade de manipulação de tempo boa e moderna para Java. As diferenças são sutis, mas importantes.

A solução mais óbvia seria usar o java.timepacote embutido , uma vez que esta é a nova forma padrão de lidar com horários e datas em Java. É uma implementação da JSR 310 , que foi uma nova proposta padrão para tratamento de tempo baseada na biblioteca Joda-Time .

No entanto, java.timefoi introduzido no Java 8 . O Android até o Marshmallow é executado em Java 7 ("Android N" é a primeira versão a apresentar os recursos da linguagem Java 8). Portanto, a menos que seu objetivo seja apenas o Android N Nougat e superior, você não pode confiar nos recursos da linguagem Java 8 (não tenho certeza se isso é 100% verdadeiro, mas é assim que eu entendo). Então java.timeestá fora.

A próxima opção pode ser Joda-Time , já que JSR 310 foi baseado em Joda-Time. No entanto, como indica o readme do ThreeTenABP , por uma série de razões, Joda-Time não é a melhor opção.

Em seguida, vem o ThreeTen-Backport , que faz back-ports de grande parte (mas não todas) da funcionalidade do Java 8 java.timepara o Java 7. Isso é bom para a maioria dos casos de uso, mas, conforme indicado no leiame do ThreeTenABP , tem problemas de desempenho com o Android.

Portanto, a última opção aparentemente correta é ThreeTenABP .

Segunda descoberta: Ferramentas de construção e gerenciamento de dependências

Já que compilar um programa - especialmente um que usa várias bibliotecas externas - é complexo, Java quase invariavelmente usa uma "ferramenta de construção" para gerenciar o processo. Make , Apache Ant , Apache Maven e Gradle são ferramentas de construção usadas com programas Java (veja esta postagem para comparações). Conforme observado mais adiante, Gradle é a ferramenta de compilação escolhida para projetos Android.

Essas ferramentas de construção incluem gerenciamento de dependência. Apache Maven parece ser o primeiro a incluir um repositório de pacotes centralizado. A Maven introduziu o Repositório Central Maven , que permite funcionalidade equivalente a php composercom Packagist e Ruby gemcom rubygems.org. Em outras palavras, o Repositório Central Maven é para o Maven (e o Gradle) o que o Packagist é para o compositor - uma fonte definitiva e segura para pacotes versionados.

Terceira descoberta: Gradle lida com dependências em projetos Android

No topo da minha lista de tarefas está ler os documentos do Gradle aqui , incluindo seus e-books gratuitos. Se eu tivesse lido essas semanas atrás quando comecei a aprender Android, certamente saberia que o Gradle pode usar o Repositório Central Maven para gerenciar dependências em projetos Android. Além disso, conforme detalhado nesta resposta StackOverflow, a partir do Android Studio 0.8.9, o Gradle usa o Maven Central Repository implicitamente por meio do JCenter do Bintray, o que significa que você não precisa fazer nenhuma configuração extra para configurar o repo - você apenas lista o dependências.

Quarta descoberta: as dependências do projeto estão listadas em [project dir] /app/build.gradle

Novamente, óbvio para aqueles que têm alguma experiência no uso do Gradle em Java, mas demorei um pouco para descobrir isso. Se você vir pessoas dizendo "Oh, apenas adicione compile 'this-or-that.jar'" ou algo semelhante, saiba que compileé uma diretiva naquele arquivo build.gradle que indica dependências de tempo de compilação. Esta é a página oficial do Gradle sobre gerenciamento de dependências.

Quinta descoberta: ThreeTenABP é gerenciado por Jake Wharton, não por ThreeTen

Mais uma questão que passei muito tempo tentando resolver. Se você procurar o ThreeTen no Maven Central, verá apenas pacotes para threetenbp, não threetenabp. Se você for ao repositório github do ThreeTenABP , verá aquela compile 'this-or-that'linha infame na seção Download do Readme.

Quando acessei este repositório github pela primeira vez, não sabia o que aquela linha de compilação significava e tentei executá-la em meu terminal (com uma falha óbvia e previsível). Frustrado, não voltei a ele até muito depois de descobrir o resto e, finalmente, perceber que é uma linha do Repo Maven apontando para o com.jakewharton.threetenabprepo, em oposição ao org.threetenrepo. É por isso que pensei que o pacote ThreeTenABP não estava no repositório Maven.

Resumo: Fazendo funcionar

Agora tudo parece muito fácil. Você pode obter funções modernas de manipulação de tempo em um projeto Android, certificando-se de que seu [project folder]/app/build.gradlearquivo tenha a implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'linha em sua dependenciesseção:

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

Adicione também à classe Application:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}
8 BasilBourque May 05 2020 at 07:35

A resposta aceita por Kael está correta. Além disso, mencionarei algumas coisas e apresentarei um diagrama sobre como obter a funcionalidade java.time .

java.time integrado ao Android 26+

Se o objetivo for Android 26 ou posterior, você encontrará uma implementação de JSR 310 ( classes java.time ) empacotada com Android. Não há necessidade de adicionar ThreeTenABP .

APIs quase idênticas

Só para esclarecer, ThreeTenABP para Android é uma adaptação da biblioteca ThreeTen-Backport que traz a maior parte da funcionalidade java.time para Java 6 e Java 7 . Este back-port compartilha quase uma API idêntica com java.time .

Suponha que agora você tenha como alvo o Android anterior a 26, então você usa ThreeTenABP . Posteriormente, você pode eventualmente abandonar o suporte para essas versões anteriores do Android, para usar as classes java.time empacotadas com o Android. Quando isso acontece, você precisa fazer algumas alterações em sua base de código, exceto (a) importinstruções de comutação e (b) alterar todas as chamadas feitas org.threeten.bp.DateTimeUtilspara usar os novos métodos de conversão que foram adicionados às antigas classes de data e hora legadas ( Date, GregorianCalendar) .

O processo de transição de ThreeTenABP para java.time deve ser suave e quase indolor.

Quando usar qual estrutura

Aqui está um gráfico que mostra as três estruturas e indica quando usar cada uma em quais cenários.

➥ Atualização: o Android Gradle Plugin 4.0.0+ traz uma nova 4ª opção, desugar de API para disponibilizar um subconjunto de funcionalidade java.time não originalmente integrado ao Android anterior. Veja o topo da resposta principal de Kael.


Sobre java.time

A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como java.util.Date, Calendar, e SimpleDateFormat.

Para saber mais, consulte o tutorial Oracle . E pesquise no Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para as classes java.time .

Você pode trocar objetos java.time diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou posterior. Não há necessidade de cordas, não há necessidade de java.sql.*classes. Hibernate 5 e JPA 2.2 suportam java.time .

Onde obter as classes java.time?

5 RichardKamere Aug 19 2019 at 00:02

Adicione o seguinte em seu arquivo gradle de compilação no Android Studio.

implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'

Crie a classe Application e inicialize-a assim:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}