Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Permissões com Headless Fragment
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Rafael Araujo
August 25, 2017
Programming
3
210
Permissões com Headless Fragment
Slides do talk apresentado no Android Dev Conference 2017 (pt-br)
Rafael Araujo
August 25, 2017
Tweet
Share
More Decks by Rafael Araujo
See All by Rafael Araujo
Qualidade de código Android
orafaaraujo
0
45
Other Decks in Programming
See All in Programming
どんと来い、データベース信頼性エンジニアリング / Introduction to DBRE
nnaka2992
1
350
Codex CLI でつくる、Issue から merge までの開発フロー
amata1219
0
250
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
780
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
710
20260320登壇資料
pharct
0
140
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
1.2k
「効かない!」依存性注入(DI)を活用したAPI Platformのエラーハンドリング奮闘記
mkmk884
0
280
Migration to Signals, Signal Forms, Resource API, and NgRx Signal Store @Angular Days 03/2026 Munich
manfredsteyer
PRO
0
190
Everything Claude Code OSS詳細 — 5層構造の中身と導入方法
targe
0
160
AI-DLC 入門 〜AIコーディングの本質は「コード」ではなく「構造」〜 / Introduction to AI-DLC: The Essence of AI Coding Is Not “Code” but “Structure”
seike460
PRO
0
110
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
2
590
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
7
3.5k
Featured
See All Featured
BBQ
matthewcrist
89
10k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
160
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
170
How to train your dragon (web standard)
notwaldorf
97
6.6k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
200
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
10k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
440
The Pragmatic Product Professional
lauravandoore
37
7.2k
AI: The stuff that nobody shows you
jnunemaker
PRO
4
500
From π to Pie charts
rasagy
0
160
Agile that works and the tools we love
rasmusluckow
331
21k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Transcript
Permissões com Headless Fragment 1
Rafael Araujo Android Developer Sênior Campinas - SP, Brasil 2
Todos na mesma página... Android 6.0 (Marshmallow - API level
23) Recursos específicos em run time Segurança Responsabilidade do desenvolvedor garantir o recurso na hora correta 3
Tirando uma foto class MainCurrentWayActivity : AppCompatActivity() { override fun
onCreate(savedInstanceState: Bundle?) { findViewById(R.id.activity_main_camera) .setOnClickListener { takeAPic() } } fun takeAPic() {} } 4
Usuário clicou para tirar uma foto findViewById(R.id.activity_main_camera).setOnClickListener { val permissionCheck
= ContextCompat.checkSelfPermission(this, CAMERA) if (permissionCheck == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { ActivityCompat.requestPermissions(this, arrayOf(CAMERA), PERMISSION_RC) } } 5
Usuário clicou para tirar uma foto findViewById(R.id.activity_main_camera).setOnClickListener { val permissionCheck
= ContextCompat.checkSelfPermission(this, CAMERA) if (permissionCheck == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { ActivityCompat.requestPermissions(this, arrayOf(CAMERA), PERMISSION_RC) } } 6
Usuário clicou para tirar uma foto findViewById(R.id.activity_main_camera).setOnClickListener { val permissionCheck
= ContextCompat.checkSelfPermission(this, CAMERA) if (permissionCheck == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { ActivityCompat.requestPermissions(this, arrayOf(CAMERA), PERMISSION_RC) } } 7
Requisitando a permissão 8
Resultado da ação do usuário override fun onRequestPermissionsResult(requestCode: Int, permissions:
Arr...) { if (requestCode == PERMISSION_RC) { if (results[0] == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { if (shouldShowRequestPermissionRationale(permissions[0])) { showRetryMessage() } else { showConfigurationMessage() } } } } 9
Resultado da ação do usuário override fun onRequestPermissionsResult(requestCode: Int, permissions:
Arr...) { if (requestCode == PERMISSION_RC) { if (results[0] == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { if (shouldShowRequestPermissionRationale(permissions[0])) { showRetryMessage() } else { showConfigurationMessage() } } } } 10
Resultado da ação do usuário override fun onRequestPermissionsResult(requestCode: Int, permissions:
Arr...) { if (requestCode == PERMISSION_RC) { if (results[0] == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { if (shouldShowRequestPermissionRationale(permissions[0])) { showRetryMessage() } else { showConfigurationMessage() } } } } 11
Resultado da ação do usuário override fun onRequestPermissionsResult(requestCode: Int, permissions:
Arr...) { if (requestCode == PERMISSION_RC) { if (results[0] == PackageManager.PERMISSION_GRANTED) { takeAPic() } else { if (shouldShowRequestPermissionRationale(permissions[0])) { showRetryMessage() } else { showConfigurationMessage() } } } } 12
Caso usuário negar... 13
Alguns problemas Lógica na view Muito código Lidar com
muitos fluxos Boilerplate 14
Proposta? Headless Fragment! 15
Headless Fragment Fragments sem UI (sem inflar um XML) Reter
objetos grandes demais para o Bundle da Activity Lógica isolada da camada View Reutilizar em outras telas 16
Em arquiteturas VIEW VIEW MVP MVVM MODEL MODEL PRESENTER VIEW
MODEL 17
Em arquiteturas VIEW VIEW MVP MVVM MODEL MODEL PRESENTER VIEW
MODEL Headless Fragment Headless Fragment 18
Isolando o código View Headless Fragment 19
Isolando o código View Headless Fragment Permissão concedida? 20
Isolando o código View Headless Fragment Permissão concedida? Permitiu ou
Negou 21
Fácil reutilização View Model ViewModel Timeline View Model ViewModel Perfil
View Model ViewModel Chat 22
Fácil reutilização View Model ViewModel Permissão Câmera Timeline View Model
ViewModel Perfil View Model ViewModel Chat 23
Entendo o porque um Fragment onCreate() Inicio onResume() onPause() onAttach()
24
Requisitando a permissão ... requestPermissions() onResume() onPause() 25
Resultado da permissão ... requestPermissions() onResume() onPause() onRequestPermissionsResult() 26
Resultado da permissão ... requestPermissions() onResume() onPause() onRequestPermissionsResult() 27
Talk is cheap, show me the code! 28
Callbacks public interface PermissionListener { void onPermissionGranted(); void onPermissionDenied();
} 29
Activity class MainNewWayActivity : AppCompatActivity(), PermissionListener { override fun onCreate(savedInstanceState:
Bundle?) { findViewById(R.id.activity_main_camera).setOnClickListener { val helper: PermissionHelper = PermissionHelper() helper.requestPermissionIfNeeded(supportFragmentManager) } } override fun onPermissionGranted() { takeAPic() } override fun onPermissionDenied() { finish() } } 30
Activity class MainNewWayActivity : AppCompatActivity(), PermissionListener { override fun onCreate(savedInstanceState:
Bundle?) { findViewById(R.id.activity_main_camera).setOnClickListener { val helper: PermissionHelper = PermissionHelper() helper.requestPermissionIfNeeded(supportFragmentManager) } } override fun onPermissionGranted() { takeAPic() } override fun onPermissionDenied() { finish() } } 31
Activity class MainNewWayActivity : AppCompatActivity(), PermissionListener { override fun onCreate(savedInstanceState:
Bundle?) { findViewById(R.id.activity_main_camera).setOnClickListener { val helper: PermissionHelper = PermissionHelper() helper.requestPermissionIfNeeded(supportFragmentManager) } } override fun onPermissionGranted() { takeAPic() } override fun onPermissionDenied() { finish() } } 32
Headless Fragment class PermissionHelper : DialogFragment() { override fun onCreate(savedInstanceState:
Bundle?) { super.onCreate(savedInstanceState) isCancelable = false } } 33
Headless Fragment class PermissionHelper : DialogFragment() { override fun onCreate(savedInstanceState:
Bundle?) { super.onCreate(savedInstanceState) isCancelable = false } } 34
Configurando o Callback private lateinit var mListener: PermissionListener override fun
onAttach(context: Context?) { super.onAttach(context) if (context is PermissionListener) { mListener = context } } 35
Configurando o Callback private lateinit var mListener: PermissionListener override fun
onAttach(context: Context?) { super.onAttach(context) if (context is PermissionListener) { mListener = context } } 36
Configurando o Callback private fun onPermissionGranted() { dismiss() mListener.onPermissionGranted() }
private fun onPermissionDenied() { dismiss() mListener.onPermissionDenied() } 37
Método público private val PERMISSION_TAG = "PERMISSION_TAG" fun requestPermissionIfNeeded(fragmentManager: FragmentManager)
{ val fragment = fragmentManager.findFragmentByTag(PERMISSION_TAG) if (fragment == null) { show(fragmentManager, PERMISSION_TAG) } } 38
Requisitando a permissão private val PERMISSIONS = arrayOf(permission.CAMERA, permission.RECORD_AUDIO) private
val PERMISSION_RC = 100 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestPermissions(PERMISSIONS, PERMISSION_RC) } 39
Requisitando a permissão private val PERMISSIONS = arrayOf(permission.CAMERA, permission.RECORD_AUDIO) private
val PERMISSION_RC = 100 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestPermissions(PERMISSIONS, PERMISSION_RC) } 40
Resultado da permissão ... requestPermissions() onResume() onPause() onRequestPermissionsResult() 41
Flags de contole private var mCheckPermissionStatus: Boolean = false private
var mAcceptedAll: Boolean = false private var mShouldRetry: Boolean = false private var mExternalRequestRequired: Boolean = false 42
Flags de contole private var mCheckPermissionStatus: Boolean = false private
var mAcceptedAll: Boolean = false private var mShouldRetry: Boolean = false private var mExternalRequestRequired: Boolean = false 43
Flags de contole private var mCheckPermissionStatus: Boolean = false private
var mAcceptedAll: Boolean = false private var mShouldRetry: Boolean = false private var mExternalRequestRequired: Boolean = false 44
OnResume chamado após onCreate override fun onResume() { if (mCheckPermissionStatus
&& mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 45
OnResume chamado após onCreate override fun onResume() { if (mCheckPermissionStatus
&& mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 46
Requisitando a permissão 47
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 48
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 49
Reinicia todas as flags de controle private fun resetFlags() {
mCheckPermissionStatus = true mAcceptedAll = false mShouldRetry = false mExternalRequestRequired = false } 50
Reinicia todas as flags de controle private fun resetFlags() {
mCheckPermissionStatus = true mAcceptedAll = false mShouldRetry = false mExternalRequestRequired = false } 51
Reinicia todas as flags de controle private fun resetFlags() {
mCheckPermissionStatus = true mAcceptedAll = false mShouldRetry = false mExternalRequestRequired = false } 52
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 53
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 54
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 55
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 56
override fun onRequestPermissionsResult(requestCode: Int, permissions: Arr...) { resetFlags() for (i
in permissions.indices) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[i])) { mShouldRetry = true return } else { mExternalRequestRequired = true return } } } mAcceptedAll = true } 57
Resultado da permissão ... requestPermissions() onResume() onPause() onRequestPermissionsResult() 58
OnResume chamado após ação do usuário override fun onResume() {
if (mCheckPermissionStatus && mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 59
Todas permissão foram aceitas? override fun onResume() { if (mCheckPermissionStatus
&& mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 60
Alguma permissão foi negada override fun onResume() { if (mCheckPermissionStatus
&& mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 61
Negou sem "Não perguntar novamente" override fun onResume() { if
(mCheckPermissionStatus && mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 62
Tentar novamente através de uma dialog private fun showRetryDialog() {
alert("Para continuar é necessário aceitar as permissões") { titleResource = "Permissão recusada" positiveButton("OK") { requestPermissions(PERMISSIONS, PERMISSION_RC) } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 63
Recomeça o fluxo novamente private fun showRetryDialog() { alert("Para continuar
é necessário aceitar as permissões") { titleResource = "Permissão recusada" positiveButton("OK") { requestPermissions(PERMISSIONS, PERMISSION_RC) } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 64
Callback negativo para a View private fun showRetryDialog() { alert("Para
continuar é necessário aceitar as permissões") { titleResource = "Permissão recusada" positiveButton("OK") { requestPermissions(PERMISSIONS, PERMISSION_REQUEST_CODE) } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 65
Dialog de tentar novamente 66
Negou com "Não perguntar novamente" override fun onResume() { if
(mCheckPermissionStatus && mAcceptedAll) { onPermissionGranted() } else { if (mShouldRetry) { showRetryDialog() } else if (mExternalRequestRequired) { showAppSettingDialog() } } } 67
Enviando para Configurações do Aplicativo private fun showAppSettingDialog() { alert("Conceda
as permissões nas configurações do aplicativo") { titleResource = "Permissão necessária" positiveButton("OK") { showAppSettings() } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 68
Envia usuário para as configurações private fun showAppSettingDialog() { alert("Conceda
as permissões nas configurações do aplicativo") { titleResource = "Permissão necessária" positiveButton("OK") { showAppSettings() } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 69
Callback negativo para a Activity private fun showAppSettingDialog() { alert("Conceda
as permissões nas configurações do aplicativo") { titleResource = "Permissão necessária" positiveButton("OK") { showAppSettings() } negativeButton("Cancelar") { onPermissionDenied() } }.show() } 70
Permissões nas configurações 71
Fluxo completo 72
Além do apresentado... Parametrização Permissões e mensangens por parâmetro Dagger
Facilidade na injeção de demais classes Escopo por Activity RxJava para Callbacks Verificar conexão com Headless Fragment 73
/oRafaAraujo /androidDevConference2017 74
Slides WEB: slides.com/orafaeldearaujo/permissoes-com-headless-fragment 75
Obrigado! @orafaaraujo /in/rafaeldearaujo /orafaaraujo 76