Nós Temos Um Framework Em Mãos - YouTuber Android App - Parte 14
(2973) (4)
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
CategoriaEngenharia de Software
Autor(es)Vaughn Vernon
EditoraAlta Books
Edição1ª
Ano2024
Páginas160
Tudo bem?
Neste artigo vamos continuar com a série Android app para YouTubers.
Nesta parte 14 (penúltima) finalmente nós vamos utilizar nosso app framework para colocar um outro canal YouTube nele, se beneficiando ao menos das notificações sendo entregues:
Vamos, passo a passo, realizar as alterações de acordo com o que o "cliente" espera de nós.
Você vai notar que as mudanças serão todas estáticas, absolutamente nada de código dinâmico sendo alterado 👌.
Antes de prosseguir, saiba que:
A versão e-book (PDF 📙) do projeto completo está disponível somente para os inscritos da lista de e-mails 📧 do Blog.
Se você se inscrever ainda hoje é possível que o link do e-book esteja disponível na página de confirmação de sua inscrição na lista de e-mails do Blog.
A seguir os tópicos que estaremos abordando neste penúltimo conteúdo de todo o projeto de aplicativo Android para YouTubers:
- O que já temos até aqui:
- Qual canal YouTube?:
- Download e inicialização do projeto:
- Renomeando todo o projeto:
- Gerando e utilizando chaves e IDs de API:
- Estrutura global:
- Atualizações por tela:
- Atualizações para notificação push:
- Banco de dados;
- Resultado;
- GitHub no projeto;
- Próximo conteúdo.
O que já temos até aqui
Se você chegou no projeto somente agora, saiba que este não é o primeiro e nem mesmo o último artigo já publicado sobre essa proposta de aplicativo Android.
Todo o roteiro de construção do projeto está na listagem a seguir:
- Construa Um Aplicativo Android Completo Para YouTubers - Parte 1;
- Início do Lado Tático e Barra de Topo Personalizada - Parte 2;
- Criando e Configurando o Menu Principal - Parte 3;
- Criando a Estrutura Base Das Telas Com Lista - Parte 4;
- Construindo os Fragmentos de Conteúdo Local - Parte 5;
- Banco de Dados Local Com a Room API - Parte 6;
- Construindo a Tela e a Lógica de Último Vídeo - Parte 7;
- Desenvolvendo a Tela e a Lógica de PlayLists - Parte 8;
- Vinculando Telas ao Menu Principal - Parte 9;
- Configurando Por Completo o Sistema de Notificação Push - Parte 10;
- Configurando a YouTube Data API Com a Biblioteca Retrofit - Parte 11;
- Configurando o WorkManager Para Requisições em Background - Parte 12;
- Testes e Resultados no Projeto Finalizado - Parte 13;
- Nós Temos Um Framework Em Mãos - Parte 14 (você está aqui);
- Como e Onde Monetizar o Aplicativo Framework - Parte 15.
Para tirar o máximo proveito do projeto de aplicativo que foi desenvolvido...
... para isso é inteligente seguir cada um dos conteúdos na ordem apresentada na lista anterior.
Repositório
Para ter acesso a todos os códigos fonte do projeto já finalizado, entre no repositório GitHub dele em:
➙ GitHub do projeto de aplicativo Android para YouTuber.
Qual canal YouTube?
Vamos ser bem práticos.
O canal que foi escolhido para essa prova de "app framework" é um canal popular e que certamente ajuda na monetização de toda uma industria: a de vida saudável.
O canal é o Emagrecer de Vez.
Canal que tem inúmeros produtos a venda junto aos vídeos gratuitos que são liberados semanalmente.
Alias fica aqui a dica:
Muito provavelmente uma maneira rápida de monetizar esse nosso app framework é vendendo-o a canais sobre dieta e canais que falam sobre dinheiro, incluindo os canais de marketing digital.
Digo isso, pois os donos desses canais já tendem a ter menos sensibilidade (medo) quando o assunto é "investir".
E assim conseguem entender de maneira mais assertiva que esse aplicativo é sim um investimento em todo o business dele.
Por quê este canal?
Na verdade a busca foi por um canal que:
- Tivesse uma popularidade legal;
- Já monetizasse além do AdSense do YouTube. Ou seja, vendesse cursos e livros, por exemplo;
- Fosse de um mercado de massa (possíveis milhões de clientes somente no Brasil). Dieta, vida saudável, é sim mercado de massa;
- e Que não tivesse já pronto um app de notificações para seguidores do canal.
O canal foi escolhido por mim e o design (cores e ícones auxiliares) também.
Os rótulos todos eu obtive a partir do canal no YouTube.
É isso.
Ao final vamos ver como ficou todo o projeto.
Vamos às mudanças.
Download e inicialização do projeto
Vamos literalmente baixar o .zip do projeto no GitHub e depois abri-lo no Android Studio.
Baixando do GitHub
Acesse o repositório GitHub do projeto Android:
https://github.com/viniciusthiengo/aplicativo-android-para-canais-do-youtube.
Logo depois:
- Clique em "Code";
- Então clique em "Download ZIP".
Por fim, na área de aplicativos em seu ambiente de desenvolvimento, descompacte o ZIP.
Você terá algo como:
Abrindo no Android Studio
Com o Android Studio aberto:
- Clique em "Open an existing Android Studio project";
- Selecione o projeto "aplicativo-android-para-canais-do-youtube-master".
Aguarde até o final do carregamento do projeto em IDE.
Erro com o Git
Assim que o projeto for carregado por completo, provavelmente aparecerá um alerta de erro como a seguir:
Não devemos nos preocupar com erro de Git, pois este é um inteiro novo projeto que vai partir de nosso app framework.
Sendo assim, siga os passos:
- No pop-up de alerta de erro clique em "Configure";
- Na caixa de diálogo que se abrir selecione a única opção na lista "Version Control";
- Com a opção selecionada, agora clique no sinal de menos que há no fundo da lista;
- Agora clique em "Apply";
- Por fim clique em "Ok".
Done.
Problema de configuração Git resolvido.
Importante:
Ao final de suas versões de projeto cliente, somente coloque o app em repositório público se o cliente permitir (provavelmente ele não vai permitir, principalmente devido às chaves de API expostas).
Renomeando todo o projeto
Antes de entrar nos trechos mais delicados de renomeação de projeto.
Antes disso vamos primeiro renomear a pasta do projeto na área de aplicativos de seu ambiente de desenvolvimento.
É literalmente a pasta.
Primeiro feche o projeto e remova ele da lista de apps da tela inicial do Android Studio IDE.
Logo depois coloque como rótulo da pasta do projeto o nome "CanalEmagrecerDeVez":
Por fim, realize todo o processo de migração de projeto no Android Studio, acessando ele via opção "Open an existing Android Studio project".
Ignore os erros que vão aparecer, pois iremos agora iniciar as renomeações dentro de projeto e aos poucos, de acordo com as atualizações, eles vão "sucumbindo".
Root name
Com o aplicativo aberto no IDE e com a visualização de pacotes em modo "Android".
Nesta condição acesse o arquivo settings.gradle:
- Em rootproject.name coloque o valor "Canal Emagrecer de Vez";
- Por fim clique em "Sync Now" e aguarde a sincronização do projeto.
Rótulos de pacotes
No caso dos pacotes, primeiro:
- Coloque a visualização de pacotes em modo "Project";
- Expanda tudo até chegar ao primeiro filho direto do pacote "java";
- Selecione esse pacote raiz;
- Clique em "Show Options Menu" - aquela engrenagem ⚙ que fica ao topo direito da estrutura de pacotes;
- Então clique (desmarque) a opção "Compact Middle Packages".
Você vai perceber que a estrutura de pacotes será dividida por completo:
Então podemos partir para os pacotes raizes:
- Clique com o botão direito do mouse (ou dê Shift + F6) no pacote "canalviniciusthiengo";
- Acesse "Refactor" e clique em "Rename";
- No pop-up que se abrir clique em "Rename package";
- No novo pop-up que se abrir coloque em "Rename package (...)" o valor "youtubechannel";
- Então clique em "Refactor" e aguarde o processamento.
Agora o pacote "thiengo":
- Clique com o botão direito do mouse no pacote "thiengo";
- Acesse "Refactor" e clique em "Rename";
- No pop-up que se abrir clique em "Rename package";
- No novo pop-up que se abrir coloque em "Rename package (...)" o valor "emagrecerdevez";
- Então clique em "Refactor" e aguarde o processamento.
Nice!
Ainda temos um pacote "br" perdido em projeto. Pois o site oficial do canal (que deu origem à estrutura de pacotes que estamos construindo).
Esse site não tem o ".br", o domínio é apenas ".com": EmagrecerDeVez.com.
Sendo assim:
- Miniminize o pacote "youtubechannel";
- Clique neste pacote e arraste-o para dentro do pacote "com". Ele ficará como um pacote irmão de "br". O pacote "br" ficará vazio;
- No pop-up que se abrir, mantenha a opção "Move package (...)" marcada e clique em "Ok";
- No novo pop-up de "Warning" clique em "Yes";
- Agora, na caixa de diálogo de configuração de migração de pacote, clique em "Refactor";
- A caixa "Find" será acionada. Então clique em "Do Refactor" e aguarde o processamento;
- Por fim, clique com o botão direito do mouse no pacote "br" (agora vazio) e clique em "Delete";
- No pop-up que aparecer, apenas clique em "Delete";
Em termos de atualização de rótulos de estrutura: quase tudo finalizado.
Atualizando o Gradle
Abra o Gradle Nível de Aplicativo, ou build.gradle (Module: app).
No bloco defaultConfig modifique o valor de applicationId para emagrecerdevez.com.youtubechannel como a seguir:
...
android {
...
defaultConfig {
applicationId "emagrecerdevez.com.youtubechannel"
...
}
...
}
...
Sincronize o projeto.
Reconstrua o projeto
Com o projeto ainda aberto:
- Acesse o menu de topo e clique em "Build";
- Logo depois clique em "Clean Project";
- Ao final do processamento do clean acesse novamente "Build" e clique em "Rebuild Project".
Ainda no menu de topo:
- Clique em "File";
- Logo depois clique em "Invalidate Caches / Restart";
- No pop-up que se abrir clique em "Invalidate and Restart".
Ao final do processamento feche o projeto e remova ele da lista de apps da tela inicial do Android Studio.
Deletando arquivo
Entre na pasta do projeto, CanalEmagrecerDeVez, e delete o folder oculto .idea.
É possível que dentro de CanalEmagrecerDeVez ainda tenha arquivos e folders com o nome antigo do projeto.
Isso depende da versão do Android Studio que você estiver utilizando.
Se houverem arquivos e folders com o nome antigo do projeto, já neste ponto de renomeação de tudo...
... então delete-os também.
Por fim, acesse o Android Studio e abra o projeto novamente via "Open an existing Android Studio project".
Nova estrutura física
Foi demorado? Foi.
Porém agora você tem literalmente um novo projeto com um nome de pacote exclusivo, exatamente como pede a Google Play Store.
Nossa configuração, estrutura, final de pacotes renomeados ficou:
Compactando os pacotes:
- Clicando em "Show Options Menus";
- Depois clicando em "Compact Middle Packages".
Temos:
Done.
Neste ponto o seu projeto não mais deverá estar apresentando erros.
Gerando e utilizando chaves e IDs de API
Agora vamos às chaves de API e IDs que teremos que configurar em projeto para que seja possível:
- Obter dados do canal correto;
- e Também enviar notificações push.
Como dica:
Crie um novo Gmail para cada nova versão do app framework que você estiver criando.
Mesmo que o cliente já tenha um Gmail.
Crie um exclusivo para gerar todas as chaves e IDs do projeto e então entregue esse e-mail, e dados de acesso a ele, ao YouTuber cliente.
E por fim solicite que ele troque a senha do e-mail.
Canal
A URL do canal no YouTube é a seguinte: https://www.youtube.com/user/EmagrecerDeVez.
Com a URL de qualquer canal é possível obter o ID dele.
Assim:
- Entre em YouTube Channel ID;
- No campo "Youtube Channel URL, Video URL or username" coloque a URL do canal (que foi apresentada anteriormente);
- Clique em "Get YouTube Channel ID";
- Em "YOUTUBE CHANNEL ID, INFO & STATISTICS" você terá também o ID do canal:
- Copie o ID "UCGvEP26zVwqJusQDNAn0_Tw".
Classe de configuração
Agora em projeto acesse a classe de configuração YouTubeConfig (que está em /config).
Então atualize a constante CHANNEL_ID como a seguir:
...
abstract class Channel {
companion object {
...
const val CHANNEL_ID = "UCGvEP26zVwqJusQDNAn0_Tw"
...
}
}
...
OneSignal
Para gerar as chave e ID do Google Firebase e também o ID do OneSignal.
Para isto siga o passo a passo em Dados que são pré-requisito da parte 10 do projeto.
Siga o passo a passo até ao fim dessa seção da Parte 10.
Pois ao final dela você já terá em mãos:
- SERVER KEY do Firebase Cloud Messaging;
- SENDER ID do Firebase Cloud Messaging;
- ID de projeto OneSignal.
Classe de configuração
Agora acesse a classe de configuração OneSignalConfig (que está em /config).
Então atualize as constantes SERVER_KEY e SENDER_ID da classe interna Firebase e também a constante ID da classe interna App...
... atualize todas essas constantes com as chave e IDs gerados anteriormente:
...
abstract class Firebase {
companion object CloudMessage {
...
const val SERVER_KEY = "SDHNA..."
const val SENDER_ID = "okJIS..."
}
}
abstract class App {
companion object {
...
const val ID = "IUJJS..."
}
}
...
Gradle
Ainda é preciso atualizar o Gradle Nível de Aplicativo, ou build.gradle (Module: app), com o ID OneSignal.
Sendo assim, em manifestPlaceholders, coloque o ID de projeto OneSignal em onesignal_app_id como a seguir:
...
android {
...
defaultConfig {
...
manifestPlaceholders = [
onesignal_app_id: 'IUJJS...',
...
]
}
...
}
...
Então sincronize o projeto.
YouTube Data API
Aqui nós vamos precisar somente da chave de desenvolvedor Google.
Para isto siga o passo a passo em Geração de chave no Google Console da parte 11 do projeto.
Ao final desse passo a passo você terá em mãos uma Google Dev Key.
Classe de configuração
Agora acesse a classe de configuração YouTubeConfig.
Então atualize a constante GOOGLE_DEV com a chave de desenvolvedor Google que você gerou a pouco:
...
abstract class Key {
companion object {
...
const val GOOGLE_DEV = "GtHYtyO..."
}
}
...
Assim, com as configurações de chaves e IDs finalizadas, nós estamos prontos para literalmente atualizarmos os dados de canal no projeto de aplicativo Android.
Estrutura global
Nesta seção estaremos atualizando os pontos de projeto que atendem a todas as telas ou que não têm vinculo direto com alguma tela em específico (a Splash Screen, por exemplo).
É importante informar aqui que todos os códigos do projeto são passíveis de modificação e você não precisa de minha autorização para isso.
Um outro ponto importante é:
Estaremos atualizando somente as propriedades necessárias para que o canal Emagrecer de Vez seja fielmente representado em app.
Ou seja, as propriedades que não forem citadas nas posteriores atualizações do app neste conteúdo...
... essas propriedades continuarão com os exatos mesmos valores que já tinham quando o projeto foi baixado do GitHub.
É isso. Vamos às atualizações.
Ícones de abertura
Os nossos launcher app icon serão os seguintes:
Ícone retangular:
- /res/mipmap-mdpi/ic_launcher.png;
- /res/mipmap-hdpi/ic_launcher.png;
- /res/mipmap-xhdpi/ic_launcher.png;
- /res/mipmap-xxhdpi/ic_launcher.png;
- /res/mipmap-xxxhdpi/ic_launcher.png.
Ícone circular:
- /res/mipmap-mdpi/ic_launcher_round.png;
- /res/mipmap-hdpi/ic_launcher_round.png;
- /res/mipmap-xhdpi/ic_launcher_round.png;
- /res/mipmap-xxhdpi/ic_launcher_round.png;
- /res/mipmap-xxxhdpi/ic_launcher_round.png.
Realize o download de cada uma das versões de ícone de abertura e coloque-as em seus respectivos folders mipmap em projeto.
Para gerar todas as versões dos dois tipos de ícones de abertura eu utilizei o serviço gratuito Launcher icon generator.
Note que as imagens que não são ícones vetoriais de sistema. Eu as criei com o Adobe Fireworks.
Mas você pode utilizar qualquer software de edição de imagens. Ou até mesmo se juntar a um designer e com ele gerar as imagens rasterizadas necessárias em aplicativo.
Para ícones vetoriais de sistema vamos estar utilizando o Flaticon como fonte.
Splash Screen
Para a tela de abertura:
Vamos mudar as imagens e cor.
Imagens
Primeiro, as imagens têm que ser rasterizadas.
Imagens vetoriais não funcionam no modelo de tela de abertura que estamos utilizando.
Segue:
Imagem central:
- /res/drawable-mdpi/launcher_screen_logo.png;
- /res/drawable-hdpi/launcher_screen_logo.png;
- /res/drawable-xhdpi/launcher_screen_logo.png;
- /res/drawable-xxhdpi/launcher_screen_logo.png;
- /res/drawable-xxxhdpi/launcher_screen_logo.png.
Imagem de PoweredBy (desenvolvido por). Em seu caso, quando estiver atendendo a algum canal cliente, crie uma com o seu nome ou o nome da empresa que trabalha:
- /res/drawable-mdpi/powered_by.png;
- /res/drawable-hdpi/powered_by.png;
- /res/drawable-xhdpi/powered_by.png;
- /res/drawable-xxhdpi/powered_by.png;
- /res/drawable-xxxhdpi/powered_by.png.
Realize o download das imagens e coloque-as em seus respectivos folders drawable.
Cor de fundo
Vamos utilizar para cor de background na tela de abertura a mesma cor da StatusBar.
Assim, em /res/launcher_screen.xml, atualize a cor de background como a seguir:
...
<item android:drawable="@color/colorStatusBar" />
...
Nome do app
No arquivo /res/values/strings.xml atualize o nome do aplicativo como a seguir:
...
<string name="app_name">
Canal Emagrecer De Vez
</string>
...
Primary e accent colors
No arquivo /res/values/colors.xml atualize as cores das propriedades a seguir:
...
<color name="colorPrimary">#FFFFFF</color>
<color name="colorPrimaryDark">#FFFFFF</color>
<color name="colorAccent">#6DAA00</color>
...
Background de conteúdo
Ainda em /res/values/colors.xml atualize a propriedade de cor de background de conteúdo, atualize como a seguir:
...
<color name="colorScreenBackground">#98C738</color>
...
Família de fontes
No projeto original nós temos uma fonte que é diferente da Roboto (está que é padrão Android).
A fonte "Quicksand Variable":
Para o canal Emagrecer de Vez vamos utilizar uma fonte que lembra a família de fontes utilizada na descrição do banner principal do canal:
Vamos utilizar a fonte "Varela Round".
Faça o download dela:
Depois coloque-a no folder /res/font do projeto.
Tema de título
Agora precisamos atualizar o tema de título para utilizar a nova fonte.
Em /res/values/styles.xml atualize o valor de android:fontFamily no tema AppTheme.Title como a seguir:
...
<style name="AppTheme.Title">
...
<item name="android:fontFamily">@font/varela_round_regular</item>
...
</style>
...
Topo
Para o topo:
Temos novas cores, rótulos e imagem.
Cores
Em /res/values/colors.xml atualize as cores das propriedades a seguir:
...
<!-- Topo -->
<color name="colorStatusBar">#6DAA00</color>
<color name="colorTopIcon">#FFFFFF</color>
<color name="colorTopWave">#6FA800</color>
<color name="colorTopText">#FFFFFF</color>
...
Você vai perceber que estaremos trabalhando em maioria com tons de verde.
Isso, pois:
- É uma das principais cores do canal, junto ao laranja;
- Lembra "vida saudável", "alimentação saudável".
Rótulos
Em /res/values/strings.xml atualize as propriedades a seguir com os respectivos valores definidos:
...
<!-- Topo -->
<string name="channel_name">
Emagrecer De Vez
</string>
<string name="channel_desc">
Saúde, emagrecimento e estilo de vida saudável
na prática.
</string>
<string name="channel_thumb_content_desc">
Thumb do canal YouTube Emagrecer De Vez.
</string>
<string name="channel_toast_alert">
É preciso ter o aplicativo do YouTube instalado
para acessar o canal Emagrecer De Vez.
</string>
...
Família de fontes
Com a nova família de fontes para títulos já presente em projeto, podemos atualizar o TextView tv_channel_name do layout de topo.
Em /res/layout/top_signature.xml atualize a fonte do TextView de título como a seguir:
...
<TextView
android:id="@+id/tv_channel_name"
...
android:fontFamily="@font/varela_round_regular"
... />
...
Logo
Por fim, para o topo, temos a imagem do canal que ficará também no topo do app:
Imagem que deverá ter as suas cinco versões respeitando os 65dp x 65dp:
- /res/drawable-mdpi/channel_logo.png (65px x 65px);
- /res/drawable-hdpi/channel_logo.png (97.5px x 97.5px);
- /res/drawable-xhdpi/channel_logo.png (130px x 130px);
- /res/drawable-xxhdpi/channel_logo.png (195px x 195px);
- /res/drawable-xxxhdpi/channel_logo.png (260px x 260px).
Realize o download das imagens e coloque cada uma em seu respectivo folder drawable.
Para gerar as várias versões de imagens retangulares (como a da logo do canal) você pode utilizar o serviço gratuito Generic icon generator quando já estiver com a maior imagem (xxxhdpi: 260px x 260px) das versões em mãos.
Tem que estar com a maior imagem em mãos para não ter problemas de pixelagem.
Menu
Para o menu:
Temos novas cores, rótulos e ícones vetoriais.
Cores
Em /res/values/colors.xml atualize as cores das propriedades a seguir:
...
<!-- Bottom Menu -->
<color name="colorMenuSeparatorLine">#557EB700</color>
<color name="colorMenuBackground">@android:color/transparent</color>
<color name="colorMenuItemBackground">@android:color/transparent</color>
<color name="colorMenuItemSelected">#FFFFFF</color>
<color name="colorMenuItemNotSelected">#608C00</color>
...
Rótulos
Em /res/values/strings.xml atualize as propriedades a seguir com os respectivos valores definidos:
...
<!-- Menu -->
<string name="item_menu_last_video">
Vídeo
</string>
<string name="item_menu_social_networks">
Redes
</string>
<string name="item_menu_play_lists">
PlayLists
</string>
<string name="item_menu_exclusive_groups">
Tribo
</string>
<string name="item_menu_about_channel">
Sobre
</string>
<string name="item_menu_books">
Livros
</string>
<string name="item_menu_courses">
Cursos
</string>
<string name="item_menu_business">
Comercial
</string>
...
Ícones
Em relação aos dados padrões que vêm no app framework...
... em relação a esses todos, os ícones vetoriais de menu foram trocados.
Assim temos:
Para a opção Vídeo, ic_video_player.xml:
Para a opção Redes, ic_social_networks.xml:
Para a opção PlayLists, ic_playlist_color.xml:
Para a opção Tribo, ic_tribe_color.xml:
Para a opção Livros, ic_book_cover_color.xml:
Para a opção Cursos, ic_courses_color.xml:
Para a opção Sobre o dono do canal, ic_about.xml:
Para a opção Comercial, ic_business.xml:
Todos são ícones vetoriais.
Sendo assim, realize o download de cada um e os coloque no folder /res/drawable.
Dados fixos
Por fim os dados fixos que preencherão a lista de itens que estará vinculada ao RecyclerView do menu.
Acesse a classe persistência MenuItemsData e coloque no método getItems() a seguinte nova configuração de dados:
...
fun getItems( res: Resources )
= listOf(
MenuItem(
id = R.id.last_video,
label = res.getString( R.string.item_menu_last_video ),
icon = R.drawable.ic_video_player,
isSelected = MenuItemStatus.SELECTED
),
MenuItem(
id = R.id.social_networks,
label = res.getString( R.string.item_menu_social_networks ),
icon = R.drawable.ic_social_networks
),
MenuItem(
id = R.id.play_lists,
label = res.getString( R.string.item_menu_play_lists ),
icon = R.drawable.ic_playlist_color
),
MenuItem(
id = R.id.exclusive_groups,
label = res.getString( R.string.item_menu_exclusive_groups ),
icon = R.drawable.ic_tribe_color
),
MenuItem(
id = R.id.books,
label = res.getString( R.string.item_menu_books ),
icon = R.drawable.ic_book_cover_color
),
MenuItem(
id = R.id.courses,
label = res.getString( R.string.item_menu_courses ),
icon = R.drawable.ic_courses_color
),
MenuItem(
id = R.id.about_channel,
label = res.getString( R.string.item_menu_about_channel ),
icon = R.drawable.ic_about
),
MenuItem(
id = R.id.business,
label = res.getString( R.string.item_menu_business ),
icon = R.drawable.ic_business
)
)
...
Done.
Podemos ir às telas de projeto.
Atualizações por tela
Aqui vamos às atualizações específicas de cada uma das telas do canal que teremos em app.
Por "coincidência" 😁 teremos os mesmos tipos de telas já presentes na versão inicial do framework.
Último vídeo
A tela de "último vídeo" disponibilizado em canal terá cores e dados fixos diferentes do padrão:
Cores
No arquivo /res/values/colors.xml atualize as propriedades a seguir com os valores definidos:
...
<color name="colorContentTitle">#FFFFFF</color>
<color name="colorContentText">#FFFFFF</color>
<color name="colorContentLink">#FFFFFF</color>
<!-- Video player -->
<color name="colorVideoPlayerBackground">#000000</color>
<color name="colorVideoPlayerForeground">#99000000</color>
<color name="colorVideoPlayerIcon">#FFFFFF</color>
<!-- Bloco YouTube -->
<color name="colorVideoPlayerYBBackground">#77AE00</color>
<color name="colorVideoPlayerYBText">#FFFFFF</color>
<!-- Bloco comentário -->
<color name="colorVideoPlayerCBBackground">#77AE00</color>
<color name="colorVideoPlayerCBText">#FFFFFF</color>
...
Dados fixos
Na classe persistência LastVideoData (em /data/fixed) coloque a seguinte nova definição de dados no método getInitialVideo():
...
fun getInitialVideo()
= LastVideo(
uid = "4SkFqsXDSjU",
title = "Minha História Até Agora | Rodrigo " +
"Polesso e o Emagrecer De Vez",
description = "Eu comi atum em lata e ervilha " +
"durante quase 1 ano... Neste vídeo " +
"conto mais sobre minha história pessoal, " +
"como tudo começou, um pouco mais sobre " +
"quem é Rodrigo Polesso."
).apply {
thumbUrl = ""
}
...
Primeira tela: atualizada!
Redes
A tela de Redes sociais e sites disponibilizados em canal terá cores, rótulos e dados fixos diferentes do padrão:
Cores
No arquivo /res/values/colors.xml atualize as propriedades a seguir com os valores definidos:
...
<!-- Item de lista -->
<color name="colorListItemBackground_RippleStart">#8CC200</color>
<color name="colorListItemBackground_RippleEnd">#6DAB00</color>
<color name="colorListItemStroke">#8CC200</color>
<color name="colorListItemText">#FFFFFF</color>
<color name="colorListItemLinealIcon">#5A8B00</color>
<color name="colorListItemNoDataIcon">#5A8B00</color>
...
Note que adicionamos uma nova propriedade de cor: colorListItemLinealIcon.
Isso, pois diferente dos valores padrões de nosso app framework, aqui os ícones de telas com listas...
... todos esses ícones terão a mesma cor:
Sendo assim ainda falta atualizar o estilo de ícones de lista para que todos tenham a mesma cor.
Em /res/values/styles.xml atualize o tema AppTheme.ListItemIcon adicionando o atributo android:tint exatamente como a seguir:
...
<style name="AppTheme.ListItemIcon">
...
<item name="android:tint">@color/colorListItemLinealIcon</item>
</style>
...
Agora vamos direto aos ícones, pois como ocorreu para a tela de "Último vídeo":
Para a tela de Redes nós não temos alterações nas propriedades String em /res/values/strings.xml.
Ícones
O canal Emagrecer de Vez tem cinco itens que entram como opções em Redes.
São:
- Três redes sociais;
- Um blog;
- e Um PodCast.
Vamos utilizar ícones vetoriais que lembram cada uma das opções, redes e sites. Não iremos utilizar diretamente os ícones logo de cada entidade:
Para a conta Instagram, ic_instagram_color.xml:
Para a conta Facebook, ic_facebook_color.xml:
Para a conta YouTube, ic_youtube_color.xml:
Para o Blog, ic_blog_color.xml:
Para o PodCast, ic_podcast_color.xml:
Realize o download dos ícones anteriores e coloque-os no folder /res/drawable.
Dados fixos
Na classe persistência SocialNetworksData (em /data/fixed) coloque a seguinte nova definição de dados no método getNetworks():
...
fun getNetworks()
= listOf(
SocialNetwork(
network = "Instagram",
accountName = "/EmagrecerDeVezOficial",
appUri = "",
webUri = "https://www.instagram.com/emagrecerdevezoficial/",
logo = R.drawable.ic_instagram_color
),
SocialNetwork(
network = "Facebook",
accountName = "/EmagrecerDeVez",
appUri = "",
webUri = "https://www.facebook.com/emagrecerdevez",
logo = R.drawable.ic_facebook_color
),
SocialNetwork(
network = "YouTube",
accountName = "/EmagrecerDeVez",
appUri = "",
webUri = "https://www.youtube.com/user/EmagrecerDeVez",
logo = R.drawable.ic_youtube_color
),
SocialNetwork(
network = "Blog",
accountName = "EmagrecerDeVez.com",
appUri = "",
webUri = "https://emagrecerdevez.com/",
logo = R.drawable.ic_blog_color
),
SocialNetwork(
network = "PodBean",
accountName = "/TriboFortePodCast",
appUri = "",
webUri = "https://tribofortepodcast.podbean.com/",
logo = R.drawable.ic_podcast_color
)
)
...
PlayLists
Devido às "definições comuns de lista" já colocadas na seção sobre a tela de Redes...
... devido a isso, a partir daqui, para telas que contém lista de itens, haverá em maioria apenas atualizações pontuais de dados fixos e ícones.
E vamos começar pela tela de PlayLists do canal:
Ícone
O ícone vetorial de cada PlayList será exatamente o mesmo ícone da opção de menu para acesso às PlayLists.
Que neste ponto do projeto você já deve te-lo em /res/drawable:
Ícone de cada PlayList do canal, ic_playlist_color.xml:
Dados fixos
Depois de acessar a área de PlayLists do canal...
... na "unha" coloque no método getInitialPlayLists(), da classe persistência PlayListsData (em /data/fixed), cada uma das PlayLists, como a seguir:
...
fun getInitialPlayLists()
= mutableListOf(
PlayList(
title = "Vitaminas & Minerais",
uid = "PL0ZwP-OIgrSzufKF5490GguTQRd_oVCu1"
),
PlayList(
title = "Resultados REAIS",
uid = "PL0ZwP-OIgrSx4Ei-fYpvMEIU9iBJsHLNH"
),
PlayList(
title = "Receitas",
uid = "PL0ZwP-OIgrSxAKMI5DHje7IvuuDDgD-hr"
),
PlayList(
title = "Ao Vivo",
uid = "PL0ZwP-OIgrSzjbgFl3Q7CliZKiCbWY5U3"
),
PlayList(
title = "Alimentação FORTE",
uid = "PL0ZwP-OIgrSymEKBIC1essT3X4yJFumPQ"
),
PlayList(
title = "Tudo Sobre JEJUM INTERMITENTE",
uid = "PL0ZwP-OIgrSxUe8XeBZnU0YV_FU2hzJ3s"
),
PlayList(
title = "Outros",
uid = "PL0ZwP-OIgrSxEZqQKUZiM6iXaWycpWp-9"
),
PlayList(
title = "Outros",
uid = "PL0ZwP-OIgrSyHIVlqTpLpdiEG3I8mI9KH"
),
PlayList(
title = "Na Mídia",
uid = "PL0ZwP-OIgrSzKymCUMMm3Y5KyhDnIrIgo"
),
PlayList(
title = "Mitos Quebrados",
uid = "PL0ZwP-OIgrSybfj94wTmrWSjTePA6-6Gj"
),
PlayList(
title = "Podcasts Da \"Tribo Forte\"",
uid = "PL0ZwP-OIgrSzMDzEliYMJdChoizYCT_N-"
),
PlayList(
title = "Sério Causas Do Gano De Peso",
uid = "PL0ZwP-OIgrSx3d5bbx2LLWnKjJ2UDNKU3"
)
)
...
E sim. Tem duas PlayLists que têm exatamente o mesmo título: "Outros".
...
PlayList(
title = "Outros",
uid = "PL0ZwP-OIgrSxEZqQKUZiM6iXaWycpWp-9"
),
PlayList(
title = "Outros",
uid = "PL0ZwP-OIgrSyHIVlqTpLpdiEG3I8mI9KH"
),
...
Está assim no canal, então vamos seguir assim.
Tribo
Para o canal Emagrecer de Vez temos na verdade uma tribo e não grupos como definido por padrão nos códigos fonte do aplicativo framework:
Rótulos
Em /res/values/strings.xml adicione os novos valores das propriedades String a seguir:
...
<!-- GroupsFragment -->
<string name="groups_content_title">
Tribo exclusiva
</string>
<string name="groups_desc">
A Tribo Forte é um movimento nacional de saúde e
boa forma com o mais confiável portal de conteúdo
privilegiado do Brasil para a construção e
manutenção de um estilo de vida saudável que visa
emagrecimento, saúde e bem-estar, tudo fundamentado
inteiramente na absoluta melhor ciência disponível
hoje no mundo.
</string>
<string name="groups_toast_alert">
É preciso o aplicativo de navegador Web para acessar
no \"%s\" a tribo exclusiva \"%s\".
</string>
...
Não mude o rótulo do fragmento, ele continuará com o nome GroupsFragment.
Ícone
Como em PlayLists, o ícone vetorial de item de lista tribo será o mesmo que o ícone da opção de menu desta tela:
Ícone de item de tribo, ic_tribe_color.xml:
Caso ainda não tenha feito, realize o download do ícone anterior e coloque-o no folder /res/drawable.
Dados fixos
Na classe persistência GroupsData (em /data/fixed), mais precisamente no método getGroups(), coloque os seguintes novos dados:
...
fun getGroups()
= listOf(
Group(
place = "Portal",
name = "Tribo Forte",
webUri = "https://triboforte.com.br/",
logo = R.drawable.ic_tribe_color
)
)
...
Livros
Vamos agora às atualizações na tela de listagem de livros do canal:
Ícones
Aqui os ícones vetoriais não serão em formato de livro e sim em um formato que lembra o tipo de assunto do livro:
Ícone do livro "Este Não É Mais Um Livro De Dieta", ic_book_este_nao_e_mais_um_livro_de_dieta.xml:
Ícone do livro "Emagrecer De Vez", ic_book_emagrecer_de_vez.xml:
Ícone do livro "50 Receitas Para Emagrecer De Vez", ic_book_50_receitas_para_emagrecer_de_vez.xml:
Ícone do livro "Hipertrofia Muscular - As respostas que você sempre quis saber", ic_book_hipertrofia_muscular_as_respostas_que_voce_sempre_quis_saber.xml:
Realize o download dos ícones anteriores e coloque-os no folder /res/drawable.
Dados fixos
Na classe persistência BooksData (também em /data/fixed), no método getBooks(), coloque os seguintes novos dados:
...
fun getBooks()
= listOf(
Book(
title = "Este Não É Mais Um Livro De Dieta",
categories = listOf( "Dieta", "Emagrecer", "Bem-estar" ),
webPage = "http://estenaoemaisumlivrodedieta.com.br/",
cover = R.drawable.ic_book_este_nao_e_mais_um_livro_de_dieta
),
Book(
title = "Emagrecer De Vez",
categories = listOf( "Dieta", "Emagrecer" ),
webPage = "https://livro.emagrecerdevez.com/emagrecer-de-vez-o-livro-9/",
cover = R.drawable.ic_book_emagrecer_de_vez
),
Book(
title = "50 Receitas Para Emagrecer De Vez",
categories = listOf( "Dieta", "Emagrecer", "Receitas" ),
webPage = "http://desafio3meses.com/50-receitas-para-emagrecer-de-vez/",
cover = R.drawable.ic_book_50_receitas_para_emagrecer_de_vez
),
Book(
title = "Hipertrofia Muscular - As respostas que você sempre quis saber",
categories = listOf( "Hipertrofia", "Musculação" ),
webPage = "https://emagrecerdevez.com/hipertrofia/",
cover = R.drawable.ic_book_hipertrofia_muscular_as_respostas_que_voce_sempre_quis_saber
)
)
...
Cursos
Agora as atualizações na tela de listagem de cursos do canal:
Rótulo
Em /res/values/strings.xml atualize a propriedade String a seguir:
...
<string name="complement_amount_videos">
%d vídeo aulas
</string>
...
Somente retiramos o emoji de vídeo (🎥) que vinha por padrão no início da String.
Ícones
Como em Livros, aqui os ícones vetoriais terão cada um o formato que lembre o tipo de assunto de seu respectivo curso:
Ícone do curso "Código Emagrecer De Vez", ic_course_codigo_emagrecer_de_vez.xml:
Ícone do curso "RÁPIDO30 - Programa de Emagrecimento Acelerado", ic_course_rapido30_programa_de_emagrecimento_acelerado.xml:
Ícone do curso "Tribo Forte", ic_course_tribo_forte.xml:
Realize o download dos ícones anteriores e coloque-os no folder /res/drawable.
Dados fixos
Na classe persistência CoursesData (em /data/fixed), no método getCourses(), coloque os seguintes novos dados:
...
fun getCourses()
= listOf(
Course(
title = "Código Emagrecer De Vez",
categories = listOf( "Dieta", "Emagrecer", "Bem-estar" ),
amountVideos = 31,
webPage = "https://codigoemagrecerdevez.com.br/",
cover = R.drawable.ic_course_codigo_emagrecer_de_vez
),
Course(
title = "RÁPIDO30 - Programa de Emagrecimento Acelerado",
categories = listOf( "Dieta", "Emagrecer" ),
amountVideos = 16,
webPage = "https://rapido30.com.br/",
cover = R.drawable.ic_course_rapido30_programa_de_emagrecimento_acelerado
),
Course(
title = "Tribo Forte",
categories = listOf( "Dieta", "Emagrecer", "Bem-estar", "Estilo de vida" ),
amountVideos = 174,
webPage = "https://triboforte.com.br/",
cover = R.drawable.ic_course_tribo_forte
)
)
...
Comercial
Assim vamos à atualização da última tela com lista de itens, a tela de contatos comerciais:
Rótulos
Em /res/values/strings.xml atualize as propriedades String a seguir com os valores definidos:
...
<!-- BusinessContactFragment -->
<string name="business_contacts_content_title">
Precisa de ajuda ou tem alguma proposta?
</string>
<string name="business_contacts_desc">Nossa
equipe de suporte 5 estrelas está de prontidão
para te ajudar da melhor forma possível! 🙂
\n\nSe você tiver dúvidas, sugestões, etc ou precisar
de auxílio com os produtos do Emagrecer De Vez,
ficaremos muito felizes em te ajudar. Por favor
envie um email para contato@emagrecerdevez.com
que responderemos muito em breve.
</string>
<string name="business_contact_toast_alert">
É preciso um aplicativo de \"%s\" para poder entrar em
contato pelo \"%s\".
</string>
...
Ícones
Como ícones vetoriais de cada item de lista teremos:
Ícone do contato via e-mail, ic_mail_color.xml:
Ícone do contato via blog, ic_blog.xml:
Ícone do contato via Facebook Messenger, ic_facebook_messenger_color.xml:
Realize o download dos ícones anteriores e coloque-os no folder /res/drawable.
Dados fixos
Na classe persistência BusinessContactData (também no pacote /data/fixed), no método getBusinessContacts(), coloque os seguintes novos dados:
...
fun getBusinessContacts()
= listOf(
BusinessContact(
place = "E-mail",
contact = "contato@emagrecerdevez.com",
webUri = "mailto:contato@emagrecerdevez.com?Subject=Contato comercial - Thiengo",
logo = R.drawable.ic_mail_color
),
BusinessContact(
place = "Blog",
contact = "EmagrecerDeVez.com",
webUri = "https://emagrecerdevez.com/contato/",
logo = R.drawable.ic_blog
),
BusinessContact(
place = "Facebook Messenger",
contact = "Emagrecer de Vez",
webUri = "https://www.messenger.com/t/emagrecerdevez",
logo = R.drawable.ic_facebook_messenger_color
)
)
...
Sobre o canal
Por fim temos a tela sobre, que tem somente texto:
Vamos mudar somente as Strings estáticas.
Rótulos
Em /res/values/strings.xml atualize as propriedades a seguir:
...
<!-- AboutChannelFragment -->
<string name="about_channel_content_title">
Conheça um pouco da minha história
</string>
<string name="about_channel_full_desc">Eu
comi atum em lata e ervilha durante quase 1 ano...
\n\nNo vídeo que vou disponibilizar para você aqui
conto mais sobre minha história pessoal,
como tudo começou, um pouco mais sobre quem é Rodrigo
Polesso.
\n\nComento sobre o porquê de eu ter começado a estudar
o mundo, a ciência nutricional, minhas tentativas de
emagrecimento, minhas infinitas dietas em busca da boa
forma, como me alimentava e como isso tudo foi mudando
depois...
\n\nUm dia eu olhei para o espelho e vi uma pessoa acima
do peso, inchada e deprimida e aí foi a hora de começar
uma mudança que nunca parou.
\n\nNo vídeo conto por cima minha história desde 2009
até 2020. Espero que curta, já que te considero um amigo
intimo já, né? hehehe
\n\n<b>🎥 Vídeo da minha história:</b> https://www.youtube.com/watch?v=4SkFqsXDSjU
\n\nForte abraço,
\n\nRodrigo.
\n\n
</string>
...
É isso mesmo que você percebeu:
Se o usuário do app realmente quiser saber sobre a vida do proprietário do canal será preciso acessar o vídeo indicado em texto (apenas tocando no link do vídeo).
Atualizações para notificação push
No caso das notificações nós iremos mudar poucas coisas.
Rótulo
Em /res/values/strings.xml atualize a propriedade String a seguir:
...
<string name="notification_verbose_description">
Notificação de novos vídeos sobre dieta saudável e
estilo de vida que são liberados no canal YouTube
Emagrecer De Vez.
</string>
...
Ícone
Diferente do app framework, aqui teremos um ícone vetorial somente para notificações push.
Ícone para push messages, ic_push_notification.xml:
Realize o download do ícone e coloque-o no folder /res/drawable.
Banco de dados
Caso você já tenha testado em seu ambiente de desenvolvimento o app framework.
Então para testar a versão do aplicativo que você fez para algum cliente YouTuber (ou para você) é prudente atualizar a versão de banco de dados.
Atualize na classe ChannelDatabase, no pacote /data/dynamic, a propriedade version como a seguir:
...
@Database(
...,
version = 22
)
...
Acrescente +1 ao valor atual de version. Era 21 aqui, assim colocamos 22.
Resultado
Executando a nova versão de nosso app framework e passando por todas as telas, temos:
Tela de abertura de aplicativo. | Tela de Último vídeo liberado em canal. |
Tela das redes e sites do canal. | Tela de PlayLists canal. |
Tela de Tribo exclusiva do canal. | Tela com os Livros do canal. |
Tela com os Cursos do canal. | Tela Sobre o autor do canal. |
Tela com os Contatos comerciais do canal. | Notificação de novo vídeo. |
Notificação em bandeja de notificações. | Notificação expandida. |
Lembrando que:
Apenas abordamos neste conteúdo os dados que precisaram ser modificados devido ao novo canal em app.
Algumas propriedades continuaram com os exatos mesmos valores. Sendo assim elas não foram apresentadas aqui.
Outro ponto importante:
As imagens, vetoriais ou rasterizadas, que não mais são utilizadas (vieram junto ao app framework).
Você deve sim remover todas essas imagens do aplicativo.
Mesmo que seja pouca coisa, o APK final será menor e... não faz sentido manter em app de cliente dados que não têm haver com ele (com o canal dele).
GitHub no projeto
Como com o projeto app framework, o aplicativo de exemplo que utilizamos aqui do canal Emagrecer de Vez também está disponível em repositório público:
➙ GitHub do projeto de aplicativo Android do canal YouTube Emagrecer de Vez.
Próximo conteúdo
Depois de ter utilizado o app framework, podemos seguramente partir para o último conteúdo desta série.
Onde abordaremos até mesmo dicas para monetizar o aplicativo framework.
Segue o link para acesso ao próximo conteúdo:
➙ Como e Onde Monetizar o Aplicativo Framework - Parte 15.
Então é isso.
Por agora, descanse um pouco 🎧. Tome um café ☕ 🍮 🍫. E...
... te vejo na parte final, Parte 15 do projeto.
Se houverem dúvidas ou dicas deste 14º conteúdo do aplicativo, então deixe nos comentários que logo eu lhe respondo.
Não esqueça de conhecer também o meu canal no YouTube (caso você ainda não conheça) e...
... não deixe de se inscrever na 📩 lista de e-mails para também garantir a versão em PDF não somente deste projeto de aplicativo Android, mas também de cada novo "conteúdo mini-curso".
Abraço.
Comentários Facebook