Share
Embed
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
Transcript
55 slides
-
Ao infinito e além! Novidades do Jetpack para profissionais Android.
✨ Walmyr Carvalho Founder @ Kusudama, Mobile Technical Leader @ idwall Google Developer Expert, Android @walmyrcarvalho -
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. -
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 -
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. -
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. -
Um ano de Android Jetpack! Como foi a trajetória do
projeto até agora? -
Pergunta: Quem aí já usa alguma coisa do Jetpack nos
próprios projetos para Android? -
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! -
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 -
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 -
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 -
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. ❤✨ -
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 -
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! -
Android Jetpack - Site Documentação oficial e mais detalhes sobre
o Jetpack developers.android.com/jetpack -
Android Jetpack - YouTube Lista de vídeos com vários talks
sobre as APIs do Jetpack bit.do/android-jetpack-youtube -
Bacana! E o que temos de novidades no Jetpack desde
o seu lançamento? -
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 -
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 ⚠ -
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: -
LiveData e Lifecycles + Coroutines (alpha) ⚠ class MyViewModel: ViewModel()
{ init { viewModelScope.launch { // Coroutine that will be canceled // when the ViewModel is cleared. } } } -
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) } } } -
LiveData e Lifecycles + Coroutines (alpha) ⚠ val user: LiveData<User>
= liveData { val data = database.loadUser() // loadUser is a suspend function. emit(data) } -
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)) } } -
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)) } } } -
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 } } -
<!-- 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 -
@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 -
// Optional, but highly recommended values val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) Security (alpha) ⚠ -
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) ⚠ -
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) ⚠ -
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) ⚠ -
val sharedPreferences = EncryptedSharedPreferences .create( fileName, masterKeyAlias, context, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
) val sharedPrefsEditor = sharedPreferences.edit() Security (alpha) ⚠ -
// 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) ⚠ -
// 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) ⚠ -
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) ⚠ -
val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log
in using your biometric credential") .setNegativeButtonText("Cancel") .build() Biometrics (alpha) ⚠ -
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) ⚠ -
… 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) ⚠ -
Android Jetpack - Site Documentação oficial e mais detalhes sobre
o Jetpack developers.android.com/jetpack -
Android Jetpack - YouTube Lista de vídeos com vários talks
sobre as APIs do Jetpack bit.do/android-jetpack-youtube -
Android Dev BR Maior comunidade lusófona de Android no Slack,
com quase de 6.000 membros! /❤✨ slack.androiddevbr.org -
Muito obrigado! Se tiver qualquer dúvida ou sugestão, pode falar
comigo. ❤ @walmyrcarvalho /walmyrcarvalho [email protected]