Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ao infinito e além! Novidades do Jetpack para p...

Ao infinito e além! Novidades do Jetpack para profissionais Android.

This talk was held during DevCamp 2019, that happened on August 16th, in Campinas, São Paulo, Brazil.

I gave a 40min talk about what's new on the Android Jetpack APIs and libraries, how can we benefit ourselves using these latest new resources and what's the future of Jetpack for Android developers.

The content is in pt-BR.

More info: https://www.devcamp.com.br/edicoes-anteriores/devcamp-2019/

Walmyr Carvalho

August 16, 2019
Tweet

More Decks by Walmyr Carvalho

Other Decks in Technology

Transcript

  1. Ao infinito e além! Novidades do Jetpack para profissionais Android.

    ✨ Walmyr Carvalho Founder @ Kusudama, Mobile Technical Leader @ idwall Google Developer Expert, Android @walmyrcarvalho
  2. Trabalho com desenvolvimento Android há 9 anos e sou um

    Google Developer Experts de Android no Brasil há 3 anos. Além disso, estou muito próximo da comunidade nacional de Android, sendo organizador do GDG São Paulo, Kotlin Meetup São Paulo e Android Dev BR, a maior comunidade brasileira de Android do mundo, com mais de 5700 pessoas!
 
 Também apoio o empreendedorismo nacional, sendo mentor de Android e mobile no Google Developers Launchpad Accelerator e na ACE Startups.
  3. Já ajudei a evoluir produtos mobile para empresas como Loggi,

    99, Cielo, CI&T, Hotel Urbano e Globo Esporte, durante mais de 9 anos de carreira como especialista em Android. Fonte: Google Play
  4. Nesse ano fundei a Kusudama, um estúdio de desenvolvimento e

    design de produtos digitais para Android e iOS, que tem como seu objetivo criar experiências que tratem seus usuários com respeito dentro do universo mobile.
  5. Recentemente me juntei ao grande time da idwall como Mobile

    Technical Leader, com o objetivo de criar a próxima plataforma de identidade digital brasileira no mobile, além de soluções para empresas que buscam aumentar a confiança na identificação dos seus usuários.
  6. O Android Jetpack é um conjunto de ferramentas, bibliotecas e

    boas práticas criado pelo Google, com o objetivo de ajudar profissionais Android a criarem aplicações com maior qualidade!
  7. Android KTX AppCompat Auto Benchmark Multidex Security Test TV Wear

    OS by Google Data Binding Lifecycles LiveData Navigation Paging Room ViewModel WorkManager CameraX Download Manager Media & Playback Notifications Multidex Permissions Preferences Sharing Slices Animation & transitions Emoji Fragment Layout Palette ViewPager2 Compose ConstraintLayout 2.0 Biometrics
  8. Android KTX AppCompat Auto Benchmark Multidex Security Test TV Wear

    OS by Google Data Binding Lifecycles LiveData Navigation Paging Room ViewModel WorkManager CameraX Download Manager Media & Playback Notifications Multidex Permissions Preferences Sharing Slices Animation & transitions Emoji Fragment Layout Palette ViewPager2 Compose Base Arquitetura Comportamento UI ConstraintLayout 2.0 Biometrics
  9. Android KTX AppCompat Auto Benchmark Multidex Security Test TV Wear

    OS by Google Data Binding Lifecycles LiveData Navigation Paging Room ViewModel WorkManager CameraX Download Manager Media & Playback Notifications Multidex Permissions Preferences Sharing Slices Animation & transitions Emoji Fragment Layout Palette ViewPager2 Compose Base Arquitetura Comportamento UI AndroidX ConstraintLayout 2.0 Biometrics
  10. O Jetpack foi anunciado há 1 ano lá no Google

    I/O ’18, e desde então o Google vem trabalhado em uma série de boas novidades para esse conjunto, sempre trabalhando bem próximo de empresas e da comunidade. ❤✨
  11. De acordo com o Google, 80% dos top 1.000 apps

    no Google Play já estão usando Jetpack, o que é um número bem impressionante e mostra o impacto do projeto na comunidade Android em geral! Fonte: bit.do/whats-new-jetpack
  12. Infelizmente hoje não vou conseguir me aprofundar sobre todas as

    bibliotecas e APIs que o Jetpack tem, pois é muito conteúdo para pouco tempo! 
 Mas já existe uma série de materiais legais sobre o assunto, principalmente por parte do Google!
  13. Android Jetpack - YouTube Lista de vídeos com vários talks

    sobre as APIs do Jetpack bit.do/android-jetpack-youtube
  14. Android KTX AppCompat Auto Benchmark Multidex Security Test TV Wear

    OS by Google Data Binding Lifecycles LiveData Navigation Paging Room ViewModel WorkManager CameraX Download Manager Media & Playback Notifications Multidex Permissions Preferences Sharing Slices Animation & transitions Emoji Fragment Layout Palette ViewPager2 Compose Base Arquitetura Comportamento UI AndroidX ConstraintLayout 2.0 Biometrics
  15. Android KTX AppCompat Auto ⚠ Benchmark ⚠ Multidex Security ⚠

    Test TV Wear OS by Google Data Binding Lifecycles ⚠ LiveData ⚠ Navigation ✅ Paging Room ViewModel ⚠ WorkManager ✅ CameraX ⚠ Download Manager Media & Playback Notifications Multidex Permissions Preferences Sharing Slices Animation & transitions Emoji Fragment Layout Palette ViewPager2 ⚠ Compose ⚠ Base Arquitetura Comportamento UI AndroidX ConstraintLayout 2.0 ⚠ Biometrics ⚠
  16. Bastante coisa nova! Vale lembrar que grande parte das novidades

    ainda se encontra em estágios de desenvolvimento alpha e beta! ⚠
 
 Vamos dar uma olhada:
  17. LiveData e Lifecycles + Coroutines (alpha) ⚠ class MyViewModel: ViewModel()

    { init { viewModelScope.launch { // Coroutine that will be canceled // when the ViewModel is cleared. } } }
  18. LiveData e Lifecycles + Coroutines (alpha) ⚠ class MyFragment: Fragment()

    { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewLifecycleOwner.lifecycleScope.launch { val params = TextViewCompat.getTextMetricsParams(textView) val precomputedText = withContext(Dispatchers.Default) { PrecomputedTextCompat.create(longTextContent, params) } TextViewCompat.setPrecomputedText(textView, precomputedText) } } }
  19. LiveData e Lifecycles + Coroutines (alpha) ⚠ val user: LiveData<User>

    = liveData { val data = database.loadUser() // loadUser is a suspend function. emit(data) }
  20. LiveData e Lifecycles + Coroutines (alpha) ⚠ val user: LiveData<Result>

    = liveData { emit(Result.loading()) try { emit(Result.success(fetchUser()) } catch(ioException: Exception) { emit(Result.error(ioException)) } }
  21. LiveData e Lifecycles + Coroutines (alpha) ⚠ class MyViewModel: ViewModel()

    { private val userId: LiveData<String> = MutableLiveData() val user = userId.switchMap { id -> liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) { emit(database.loadUserById(id)) } } }
  22. LiveData e Lifecycles + Coroutines (alpha) ⚠ class UserDao: Dao

    { @Query("SELECT * FROM User WHERE id = :id") fun getUser(id: String): LiveData<User> } class MyRepository { fun getUser(id: String) = liveData<User> { val disposable = emitSource( userDao.getUser(id).map { Result.loading(it) } ) // Fetch user, save, etc } }
  23. <!-- Important: disable debuggable for accurate performance results --> <application

    android:debuggable="false" tools:ignore="HardcodedDebugMode" tools:replace="android:debuggable"/> Benchmark (alpha) ⚠ module/src/androidTest/AndroidManifest.xml
  24. @RunWith(AndroidJUnit4::class) class MyBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test

    fun benchmarkSomeWork() = benchmarkRule.measureRepeated { doSomeWork() } } Benchmark (alpha) ⚠ module/src/androidTest/java/<package>/MyBenchmark.kt
  25. // Optional, but highly recommended values val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC

    val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) Security (alpha) ⚠
  26. val fileToRead = "my_sensitive_data.txt" lateinit var byteStream: ByteArrayOutputStream val encryptedFile

    = EncryptedFile.Builder( File(context.getFilesDir(), fileToRead), context, masterKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() Security (alpha) ⚠
  27. try { encryptedFile.openFileInput().use { fileInputStream -> try { byteStream =

    ByteArrayOutputStream() var nextByte = fileInputStream.read() while (nextByte != -1) { byteStream.write(nextByte) nextByte = fileInputStream.read() } val fileContents = byteStream.toByteArray() } catch (ex: Exception) { // Error occurred opening raw file for reading. } finally { fileInputStream.close() } }) } catch (ex: IOException) { // Error occurred opening encrypted file for reading. } Security (alpha) ⚠
  28. val fileToWrite = "my_other_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(context.getFilesDir(), fileToWrite),

    context, masterKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() // Write to a file. try { val outputStream: FileOutputStream? = encryptedFile.openFileOutput() outputStream?.apply { write("MY SUPER SECRET INFORMATION" .toByteArray(Charset.forName("UTF-8"))) flush() close() } } catch (exception: IOException) { // Error occurred opening file for writing. } Security (alpha) ⚠
  29. // Setup a SavedStateHandle on a ViewModel val vm =

    ViewModelProvider(this, SavedStateVMFactory(this)) .get(SavedStateViewModel::class.java) // Adding the SavedStateHandle on ViewModel constructor class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() { ... } ViewModel com SavedState (alpha) ⚠
  30. // A classe SavedStateHandle tem métodos helpers // que ajudam

    a lidar com o map de chave-valor: // // - get(String key) // - contains(String key) // - remove(String key) // - set(String key, T value) // - keys() ViewModel com SavedState (alpha) ⚠
  31. private val executor = Executor { } override fun onCreate(savedInstanceState:

    Bundle?) { // Prompt appears when user clicks "Log in" val biometricLoginButton = findViewById<Button>(R.id.biometric_login) biometricLoginButton.setOnClickListener { showBiometricPrompt() } } Biometrics (alpha) ⚠
  32. val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log

    in using your biometric credential") .setNegativeButtonText("Cancel") .build() Biometrics (alpha) ⚠
  33. val biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() { 


    override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) { super.onAuthenticationError(errorCode, errorMessage) 
 Toast.makeText(context, "Authentication error: $errorMessage", Toast.LENGTH_SHORT) .show() }
 … Biometrics (alpha) ⚠
  34. … override fun onAuthenticationSucceeded(result:BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) val authenticatedCryptoObject: BiometricPrompt.CryptoObject =

    result.getCryptoObject() } override fun onAuthenticationFailed() { super.onAuthenticationFailed() 
 Toast.makeText(context, "Authentication failed”, Toast.LENGTH_SHORT).show() } biometricPrompt.authenticate(promptInfo) Biometrics (alpha) ⚠
  35. Android Jetpack - YouTube Lista de vídeos com vários talks

    sobre as APIs do Jetpack bit.do/android-jetpack-youtube
  36. Android Dev BR Maior comunidade lusófona de Android no Slack,

    com quase de 6.000 membros! /❤✨ slack.androiddevbr.org