O documento apresenta o uso de Headless Fragments para isolar a lógica de permissões em Android em uma camada separada da view. O fragment sem interface permite requisitar permissões, tratar os resultados e notificar a activity de forma encapsulada. Isso remove boilerplate code da activity e facilita a reutilização da lógica em diferentes telas.
3. 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
4. Tirando uma foto
class MainCurrentWayActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
findViewById(R.id.activity_main_camera)
.setOnClickListener { takeAPic() }
}
fun takeAPic() {}
}
4
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)
}
}
5
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)
}
}
6
7. 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
16. 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
59. 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
60. Todas permissão foram aceitas?
override fun onResume() {
if (mCheckPermissionStatus && mAcceptedAll) {
onPermissionGranted()
} else {
if (mShouldRetry) {
showRetryDialog()
} else if (mExternalRequestRequired) {
showAppSettingDialog()
}
}
}
60
61. Alguma permissão foi negada
override fun onResume() {
if (mCheckPermissionStatus && mAcceptedAll) {
onPermissionGranted()
} else {
if (mShouldRetry) {
showRetryDialog()
} else if (mExternalRequestRequired) {
showAppSettingDialog()
}
}
}
61
62. Negou sem "Não perguntar novamente"
override fun onResume() {
if (mCheckPermissionStatus && mAcceptedAll) {
onPermissionGranted()
} else {
if (mShouldRetry) {
showRetryDialog()
} else if (mExternalRequestRequired) {
showAppSettingDialog()
}
}
}
62
63. 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
64. 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
65. 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
73. 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