Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

[Bug] O file provider não consegue compartilhar arquivos que não sejam imagens

Bom dia a todos

Na hora de abrir o arquivo em outro app com o file provider, quando é imagem vai normal, mas quando é outro tipo de arquivo, como áudio e pdf, no meu emulador (android 31) ele abre uma imagem aleatória e aparece essa mensagem mensagem no logcat:

Failed to ensure /data/system/shared_prefs: mkdir failed: EACCES (Permission denied)
Add DisplayResolveInfo component: ComponentInfo{com.google.android.apps.photos/com.google.android.apps.photos.pager.HostPhotoPagerActivity}, intent component: ComponentInfo{com.google.android.apps.photos/com.google.android.apps.photos.pager.HostPhotoPagerActivity}
START u0 {act=android.intent.action.VIEW dat=content://com.alura.concord.fileprovider/myFiles/Emoji 9 Marshmallow Yellow.png typ=image/png flg=0x3000001 cmp=com.google.android.apps.photos/.pager.HostPhotoPagerActivity} from uid 10160

Enquanto no meu celular(android 32), ele crasha e aparece essa mensagem:

Sending non-protected broadcast miui.intent.action.KEYCODE_EXTERNAL from system 1654:system/1000 pkg android
java.lang.Throwable
at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:13186)

outra mensagem:

supportMiPlayAudio
android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{com.milink.service/com.miui.miplay.audio.service.CoreService}
at android.app.ApplicationPackageManager.getServiceInfo(ApplicationPackageManager.java:562)
                                                                                                        at com.miui.miplay.audio.a.g.a(Unknown Source:20)

O que poderia estar causando esse tipo de bug?

Ps: a pasta onde está armazenada os arquivos está correta, o arquivo existe e consigo abrir normalmente (não está corrompido). E to usando a versão 34 do android no projeto

Vou deixar o código do Android Manifest abaixo:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />

    <application
        android:name=".ConcordApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Concord"
        tools:targetApi="31">

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.Concord"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.alura.concord.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

    </application>

</manifest>

arquivo xml do filepaths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="myFiles" path="temp/"/>
</paths>

O fileutils:

package com.alura.concord.media

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.webkit.MimeTypeMap
import androidx.core.content.FileProvider
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
import okio.use
import java.io.File
import java.io.InputStream

fun Context.openWith(mediaLink: String) {
    val file = File(mediaLink)
    val fileExtension = MimeTypeMap.getFileExtensionFromUrl(Uri.encode(file.path))
    val fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension) ?: "*/*"
    val contentUri: Uri = FileProvider.getUriForFile(
        this,
        "com.alura.concord.fileprovider",
        file,
    )
    val shareIntent = Intent().apply {
        action = Intent.ACTION_VIEW
        setDataAndType(contentUri, fileMimeType)
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    }
    startActivity(Intent.createChooser(shareIntent, "Abrir com"))
}
8 respostas

Percebi que o erro não tem haver com o tipo do arquivo e sim que apenas as 5 ultimas imagens mostram certo, acima deles não mostra a imagem clicada e sim mostra uma dessas ultimas 5 imagens.

código do navigation

package com.alura.concord.navigation

import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.alura.concord.extensions.showMessage
import com.alura.concord.media.getAllImages
import com.alura.concord.media.getNameByUri
import com.alura.concord.media.imagePermission
import com.alura.concord.media.openWith
import com.alura.concord.media.persistUriPermission
import com.alura.concord.media.saveOnInternalStorage
import com.alura.concord.media.verifyPermission
import com.alura.concord.ui.chat.MessageListViewModel
import com.alura.concord.ui.chat.MessageScreen
import com.alura.concord.ui.components.ModalBottomShareSheet
import com.alura.concord.ui.components.ModalBottomSheetFile
import com.alura.concord.ui.components.ModalBottomSheetSticker

internal const val messageChatRoute = "messages"
internal const val messageChatIdArgument = "chatId"
internal const val messageChatFullPath = "$messageChatRoute/{$messageChatIdArgument}"


fun NavGraphBuilder.messageListScreen(
    onBack: () -> Unit = {},
) {
    composable(messageChatFullPath) { backStackEntry ->
        backStackEntry.arguments?.getString(messageChatIdArgument)?.let { chatId ->
            val viewModelMessage = hiltViewModel<MessageListViewModel>()
            val uiState by viewModelMessage.uiState.collectAsState()
            val context = LocalContext.current

            val requestPermissionLauncher = rememberLauncherForActivityResult(
                ActivityResultContracts.RequestPermission()
            ) { isGranted: Boolean ->
                if (isGranted) {
                    viewModelMessage.setShowBottomSheetSticker(true)
                } else {
                    context.showMessage(
                        "Permissão não concedida, não será possivel acessar os stickers sem ela",
                        true
                    )
                }
            }
            LaunchedEffect(uiState.fileInDownload){
                uiState.fileInDownload?.let {fileInDownload ->
                    fileInDownload.inputStream?.let {inputStream ->
                        context.saveOnInternalStorage(
                            inputStream = inputStream,
                            fileName = fileInDownload.name,
                            onSucess = {filePath ->
                                viewModelMessage.finishDownload(
                                    messageId = fileInDownload.messageId,
                                    contentPath = filePath
                                )
                            }
                        )
                    }
                }
            }

            MessageScreen(
                state = uiState,
                onSendMessage = {
                    viewModelMessage.sendMessage()
                },
                onShowSelectorFile = {
                    viewModelMessage.setShowBottomSheetFile(true)
                },
                onShowSelectorStickers = {
                    if (context.verifyPermission(imagePermission())) {
                        requestPermissionLauncher.launch(imagePermission())
                    } else {
                        viewModelMessage.setShowBottomSheetSticker(true)
                    }
                },
                onDeselectMedia = {
                    viewModelMessage.deselectMedia()
                },
                onBack = {
                    onBack()
                },
                onContentDownload = { message ->
                    if (viewModelMessage.downloadInProgress()) {
                        viewModelMessage.startDownload(message)
                    } else {
                        context.showMessage(
                            "Aguarde o download terminar para baixar outro arquivo", true
                        )
                    }
                },
 

o resto posto em outra resposta

Parte 2 do código do navigation

               onShowFileOptions = { selectedMessage ->
                    viewModelMessage.setShowFileOptions(selectedMessage.id, true)
                }
            )

            if (uiState.showBottomSheetSticker) {

                val stickerList = mutableStateListOf<String>()

                context.getAllImages(onLoadImages = { images ->
                    stickerList.addAll(images)
                })

                ModalBottomSheetSticker(
                    stickerList = stickerList,
                    onSelectedSticker = {
                        viewModelMessage.setShowBottomSheetSticker(false)
                        viewModelMessage.loadMediaInScreen(path = it.toString())
                        viewModelMessage.sendMessage()
                    },
                    onBack = {
                        viewModelMessage.setShowBottomSheetSticker(false)
                    }
                )
            }

            val pickMedia = rememberLauncherForActivityResult(
                ActivityResultContracts.PickVisualMedia()
            ) { uri ->
                if (uri != null) {
                    context.persistUriPermission(uri)
                    viewModelMessage.loadMediaInScreen(uri.toString())
                } else {
                    Log.d("PhotoPicker", "No media selected")
                }
            }

            val pickFile = rememberLauncherForActivityResult(
                ActivityResultContracts.OpenDocument()
            ) { uri ->
                if (uri != null) {
                    context.persistUriPermission(uri)

                    val name = context.getNameByUri(uri)

                    uiState.onMessageValueChange(name.toString())
                    viewModelMessage.loadMediaInScreen(uri.toString())
                    viewModelMessage.sendMessage()
                } else {
                    Log.d("FilePicker", "No media selected")
                }
            }

            if (uiState.showBottomSheetFile) {
                ModalBottomSheetFile(
                    onSelectPhoto = {
                        pickMedia.launch(
                            PickVisualMediaRequest(
                                ActivityResultContracts.PickVisualMedia.ImageAndVideo
                            )
                        )
                        viewModelMessage.setShowBottomSheetFile(false)
                    },
                    onSelectFile = {
                        pickFile.launch(arrayOf("*/*"))
                        viewModelMessage.setShowBottomSheetFile(false)
                    },
                    onBack = {
                        viewModelMessage.setShowBottomSheetFile(false)
                    }
                )
            }


            if (uiState.showBottomShareSheet) {
                val mediaToOpen = uiState.selectedMessage.mediaLink

                ModalBottomShareSheet(
                    onOpenWith = {
                        context.openWith(mediaToOpen)
                    },
                    onShare = {

                    },
                    onSave = {

                    },
                    onBack = {
                        viewModelMessage.setShowBottomShareSheet(false)
                    }
                )
            }
        }
    }
}

internal fun NavHostController.navigateToMessageScreen(
    chatId: Long, navOptions: NavOptions? = null
) {
    navigate("$messageChatRoute/$chatId", navOptions)
}

código do View Model:

@HiltViewModel
class MessageListViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val messageDao: MessageDao,
    private val chatDao: ChatDao,
    private val downloadableFileDao: DownloadableFileDao,
) : ViewModel() {
    private val _uiState = MutableStateFlow(MessageListUiState())
    val uiState: StateFlow<MessageListUiState>
        get() = _uiState.asStateFlow()

    private var chatId: Long =
        requireNotNull(savedStateHandle.get<String>(messageChatIdArgument)?.toLong())

    init {
        loadDatas()

        _uiState.update { state ->
            state.copy(
                onMessageValueChange = {
                    _uiState.value = _uiState.value.copy(
                        messageValue = it
                    )

                    _uiState.value = _uiState.value.copy(
                        hasContentToSend = (it.isNotEmpty() || _uiState.value.mediaInSelection.isNotEmpty())
                    )
                },

                onMediaInSelectionChange = {
                    _uiState.value = _uiState.value.copy(
                        mediaInSelection = it
                    )
                    _uiState.value = _uiState.value.copy(
                        hasContentToSend = (it.isNotEmpty() || _uiState.value.messageValue.isNotEmpty())
                    )
                }
            )
        }
    }

    private fun loadDatas() {
        loadChatsInfos()
        loadMessages()
    }

    private fun loadMessages() {
        viewModelScope.launch {
            messageDao.getByChatId(chatId).collect { messages ->
                val mapMensagens = messages.map { searchedMessage ->
                    if (searchedMessage.author == Author.OTHER) {
                        loadMessageWithDownloadableFile(
                            searchedMessage.toMessageFile()
                        )
                    } else {
                        searchedMessage.toMessageFile()
                    }
                }

                _uiState.value = _uiState.value.copy(
                    messages = mapMensagens.filterNotNull()
                )
            }
        }
    }

    private suspend fun loadMessageWithDownloadableFile(
        searchedMessage: MessageWithFile,
    ): MessageWithFile? {
        return searchedMessage.idDownloadableFile?.let { contentId ->
            val downloadableFileEntity = downloadableFileDao.getById(contentId).first()
            searchedMessage.copy(
                downloadableFile = downloadableFileEntity?.toDownloadableFile()
            )
        }
    }

    private fun loadChatsInfos() {
        viewModelScope.launch {
            val chat = chatDao.getById(chatId).first()
            chat?.let {
                _uiState.value = _uiState.value.copy(
                    ownerName = chat.owner,
                    profilePicOwner = chat.profilePicOwner
                )
            }
        }
    }

    private fun saveMessage(
        userMessage: MessageEntity,
    ) {
        viewModelScope.launch {
            userMessage.let { messageDao.insert(it) }
        }
    }

    private fun cleanFields() {
        _uiState.value = _uiState.value.copy(
            messageValue = "",
            mediaInSelection = "",
            hasContentToSend = false
        )
    }

    fun sendMessage() {
        with(_uiState) {
            if (!value.hasContentToSend) {
                return
            }

            val userMessageEntity = MessageEntity(
                content = value.messageValue,
                author = Author.USER,
                chatId = chatId,
                mediaLink = value.mediaInSelection,
                date = getFormattedCurrentDate(),
            )
            saveMessage(userMessageEntity)
            cleanFields()
        }
    }

    fun loadMediaInScreen(
        path: String,
    ) {
        _uiState.value.onMediaInSelectionChange(path)
    }

    fun deselectMedia() {
        _uiState.value = _uiState.value.copy(
            mediaInSelection = "",
            hasContentToSend = false
        )
    }


    fun setShowBottomSheetSticker(value: Boolean) {
        _uiState.value = _uiState.value.copy(
            showBottomSheetSticker = value,
        )
    }

    fun setShowBottomSheetFile(value: Boolean) {
        _uiState.value = _uiState.value.copy(
            showBottomSheetFile = value,
        )
    }


Parte 2 do view Model:

    fun setShowBottomShareSheet(value: Boolean) {
        _uiState.value = _uiState.value.copy(
            showBottomShareSheet = value,
        )
    }


    fun setShowFileOptions(messageId: Long? = null, show: Boolean) {
        _uiState.value = _uiState.value.copy(
            showBottomShareSheet = show,
            selectedMessage = _uiState.value.messages.firstOrNull { it.id == messageId }
                ?: MessageWithFile()
        )
    }

    fun startDownload(messageWithDownload: MessageWithFile) {

        val updatedMessages = _uiState.value.messages.map { message ->
            if (message.id == messageWithDownload.id) {
                message.copy(
                    downloadableFile = message.downloadableFile?.copy(
                        status = DownloadStatus.DOWNLOADING
                    )
                )
            } else {
                message
            }
        }

        val fileInDownload = messageWithDownload.downloadableFile?.let {
            FileInDownload(
                messageId = messageWithDownload.id,
                url = it.url,
                name = it.name,
                inputStream = null
            )
        }

        fileInDownload?.let {
            _uiState.value = _uiState.value.copy(
                messages = updatedMessages,
                fileInDownload = fileInDownload
            )
            makeDonwload(fileInDownload)
        }
    }

    private fun makeDonwload(fileInDownload: FileInDownload) {
        viewModelScope.launch {
            DownloadService.makeDownloadByUrl(
                url = fileInDownload.url,
                onFinishedDownload = { inputStream ->
                    _uiState.value = _uiState.value.copy(
                        fileInDownload = fileInDownload.copy(
                            inputStream = inputStream
                        )
                    )
                }
            )
        }
    }


    fun finishDownload(messageId: Long, contentPath: String) {
        var messageWithoutContentDownload: MessageWithFile

        val menssagens = _uiState.value.messages.map { message ->
            if (message.id == messageId) {
                messageWithoutContentDownload = message.copy(
                    idDownloadableFile = 0,
                    downloadableFile = null,
                    mediaLink = contentPath,
                )
                updateSingleMessage(messageWithoutContentDownload.toMessageEntity())
                messageWithoutContentDownload
            } else {
                message
            }
        }

        _uiState.value = _uiState.value.copy(
            fileInDownload = null,
            messages = menssagens
        )
    }

    fun failureDownload(messageId: Long) {
        val updatedMessages = _uiState.value.messages.map { message ->
            if (message.id == messageId) {
                message.copy(
                    downloadableFile = message.downloadableFile?.copy(
                        status = DownloadStatus.ERROR
                    )
                )
            } else {
                message
            }
        }

        _uiState.value = _uiState.value.copy(
            messages = updatedMessages,
            fileInDownload = null
        )
    }

    private fun updateSingleMessage(messageEntity: MessageEntity) {
        viewModelScope.launch {
            messageDao.insert(messageEntity)
        }
    }


    fun downloadInProgress(): Boolean {
        return _uiState.value.fileInDownload == null
    }
}

Mexendo nos arquivos novamente, surgiu outro erro, que indica erro no conversor do Uri

ATAL EXCEPTION: main
Process: com.alura.concord, PID: 31242
java.lang.IllegalArgumentException: Failed to find configured root that contains /
    at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:825)
    at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:450)
    //é a função val contentUri: Uri = FileProvider.getUriForFile(...)
    at com.alura.concord.media.FileUtilsKt.openWith(FileUtils.kt:49)
    at com.alura.concord.navigation.MessageListScreenKt$messageListScreen$2$1$15.invoke(MessageListScreen.kt:183)
    at com.alura.concord.navigation.MessageListScreenKt$messageListScreen$2$1$15.invoke(MessageListScreen.kt:181)
    at com.alura.concord.ui.components.BottomSheetShareKt$ModalBottomShareSheet$6$1$1.invoke(BottomSheetShare.kt:44)
    at com.alura.concord.ui.components.BottomSheetShareKt$ModalBottomShareSheet$6$1$1.invoke(BottomSheetShare.kt:43)
    at com.alura.concord.ui.components.BottomSheetShareKt$BottomSheetShare$4$1$1.invoke(BottomSheetShare.kt:81)
    at com.alura.concord.ui.components.BottomSheetShareKt$BottomSheetShare$4$1$1.invoke(BottomSheetShare.kt:81)

Olá, Murilo!

Pelo que pude perceber, você está tendo problemas para compartilhar arquivos que não são imagens. Isso pode estar acontecendo por uma série de motivos, mas vamos tentar resolver juntos.

Primeiramente, notei que você está usando a permissão READ_MEDIA_IMAGES em seu AndroidManifest.xml. Essa permissão é específica para imagens, o que pode estar causando o problema ao tentar compartilhar outros tipos de arquivos. Tente substituir essa permissão por READ_EXTERNAL_STORAGE ou WRITE_EXTERNAL_STORAGE, que são permissões mais genéricas e permitem a leitura e escrita de qualquer tipo de arquivo no armazenamento externo.

Além disso, verifique se você está solicitando as permissões em tempo de execução. A partir do Android 6.0 (API 23), os usuários concedem permissões enquanto o aplicativo está em execução, não quando eles instalam o aplicativo. Isso pode fazer com que seu aplicativo falhe se você tentar realizar uma ação que requer uma permissão que você ainda não solicitou.

Outro ponto que vale a pena verificar é se o tipo MIME que você está passando para o setDataAndType() está correto. Você está usando a classe MimeTypeMap para obter o tipo MIME do arquivo, o que é uma boa prática. No entanto, o MimeTypeMap pode não ser capaz de determinar o tipo MIME de todos os arquivos, especialmente se eles tiverem extensões incomuns. Nesse caso, você pode tentar passar um tipo MIME genérico, como "*/*".

Por último, verifique se o arquivo que você está tentando compartilhar realmente existe e pode ser lido. Você pode fazer isso usando o método exists() e canRead() da classe File.

Aqui está um exemplo de como você pode modificar seu método openWith() para verificar essas condições:

fun Context.openWith(mediaLink: String) {
    val file = File(mediaLink)
    
    if (!file.exists() || !file.canRead()) {
        Log.e("FileUtils", "Arquivo não existe ou não pode ser lido: $mediaLink")
        return
    }
    
    val fileExtension = MimeTypeMap.getFileExtensionFromUrl(Uri.encode(file.path))
    val fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension) ?: "*/*"
    
    val contentUri: Uri = FileProvider.getUriForFile(
        this,
        "com.alura.concord.fileprovider",
        file,
    )
    
    val shareIntent = Intent().apply {
        action = Intent.ACTION_VIEW
        setDataAndType(contentUri, fileMimeType)
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
    }
    
    if (shareIntent.resolveActivity(packageManager) != null) {
        startActivity(Intent.createChooser(shareIntent, "Abrir com"))
    } else {
        Log.e("FileUtils", "Não há aplicativos capazes de abrir o arquivo: $mediaLink")
    }
}

Espero ter ajudado e bons estudos!

Oi Matheus, então eu fiz o que você falou, código abaixo:

fun Context.openWith(mediaLink: String) {
    val file = File(mediaLink)
    if (!file.exists() || !file.canRead()) {
        Log.e("FileUtils", "Arquivo não existe ou não pode ser lido: $mediaLink")
        return
    }
    val fileExtension = MimeTypeMap.getFileExtensionFromUrl(Uri.encode(file.path))
    val fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension) ?: "*/*"
    val contentUri: Uri = FileProvider.getUriForFile(
        this,
        "com.alura.concord.fileprovider",
        file,
    )
    val shareIntent = Intent().apply {
        action = Intent.ACTION_VIEW
        setDataAndType(contentUri, fileMimeType)
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    }
    if (shareIntent.resolveActivity(packageManager) != null) {
        startActivity(Intent.createChooser(shareIntent, "Abrir com"))
    } else {
        Log.e("FileUtils", "Não há aplicativos capazes de abrir o arquivo: $mediaLink")
    }
}

Depois de aplicar esse código, as 5 ultimas imagens mostram essa mensagem:

Não há aplicativos capazes de abrir o arquivo: /storage/emulated/0/Android/data/com.alura.concord/files/temp/Emoji 9 Marshmallow Red.png
Não há aplicativos capazes de abrir o arquivo: /storage/emulated/0/Android/data/com.alura.concord/files/temp/Emoji 9 Marshmallow Yellow.png
Não há aplicativos capazes de abrir o arquivo: /storage/emulated/0/Android/data/com.alura.concord/files/temp/Emoji 9 Marshmallow Red.png
Não há aplicativos capazes de abrir o arquivo: /storage/emulated/0/Android/data/com.alura.concord/files/temp/Emoji 9 Marshmallow Green.png

Enquanto imagens mais acima e outros tipos de arquivos mostram essa mensagem:

Arquivo não existe ou não pode ser lido: 

Eu acredito que o problema seja no código que eu esteja passando o link, algo no view model ou no navigation

E sobre a questão da permissão, é que a partir do Android SDK 33, alterou o tipo de permissao, antes poderia ser o android:name="android.permission.READ_EXTERNAL_STORAGE", mas agora precisa especificar o tipo do arquivo. Eu to só utilizando o do android:name="android.permission.READ_MEDIA_IMAGES", e mesmo colocando o android:name="android.permission.READ_MEDIA_AUDIO", não adiantou nada

Ps: link do projeto no github

solução!

O Junior Martins me respondeu no discord da alura e o problema era:

Eu atualizei as bibliotecas do aplicativo no build.gradle e por algum motivo isso fazia dar os bugs no app (talvez algum tipo de incompatibilidade, ou a maneira de rodar o código diferente) . Ao voltar as versões iguais ao do projeto, não tive mais esse tipo de problema