Nós Temos Um Framework Em Mãos - YouTuber Android App - Parte 14

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Nós Temos Um Framework Em Mãos - YouTuber Android App - Parte 14

Nós Temos Um Framework Em Mãos - YouTuber Android App - Parte 14

Vinícius Thiengo
(269) (2)
Go-ahead
"É preciso encarar todo retrocesso, fracasso ou dificuldade como provações ao longo do caminho, como sementes plantadas para a colheita futura. Nenhum momento é desperdiçado se você presta atenção nas lições contidas em cada experiência."
Robert Greene
Kotlin Android
Capa do livro Mapas Android de Alta Qualidade - Masterização Android
TítuloMapas Android de Alta Qualidade - Masterização Android
CategoriasAndroid, Kotlin, Masterização, Especialização
AutorVinícius Thiengo
Edição
Ano2020
Capítulos11
Páginas166
Acessar Livro
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

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:

Banner do aplicativo Android do canal YouTube Emagrecer de Vez

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

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:

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.

Canal YouTube Emagrecer de Vez

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".

Download do projeto Android YouTuber App no GitHub

Por fim, na área de aplicativos em seu ambiente de desenvolvimento, descompacte o ZIP.

Você terá algo como:

Pasta do projeto Android quando descompactado

Abrindo no Android Studio

Com o Android Studio aberto:

  • Clique em "Open an existing Android Studio project";

Tela inicial do Android Studio IDE

  • 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:

Invalid VCS root mapping

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";

Preferências de versão de controle

  • Com a opção selecionada, agora clique no sinal de menos que há no fundo da lista;

Botão para remover controle de versão de projeto Android

  • 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.

Removendo app da lista inicial de apps no Android Studio IDE

Logo depois coloque como rótulo da pasta do projeto o nome "CanalEmagrecerDeVez":

Pasta do projeto com o rótulo correto, 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";

Mudando o nome root do projeto

  • 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;

Show Options Menu

  • Então clique (desmarque) a opção "Compact Middle Packages".

Desmarcando a opção Compact Middle Packages

Você vai perceber que a estrutura de pacotes será dividida por completo:

Estrutura física do projeto no Android Studio IDE

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";

Renomeando o pacote do projeto

  • No pop-up que se abrir clique em "Rename package";

Pop-up de confirmação de renomeamento de pacote

  • No novo pop-up que se abrir coloque em "Rename package (...)" o valor "youtubechannel";

Confirmando o novo nome de pacote

  • 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";

Pop-up de escolha de como será a realocação de pacote em projeto

  • No novo pop-up de "Warning" clique em "Yes";

Pop-up de confirmação de realocação de pacote em projeto

  • Agora, na caixa de diálogo de configuração de migração de pacote, clique em "Refactor";

Caixa de diálogo de configuração de migração de pacote

  • A caixa "Find" será acionada. Então clique em "Do Refactor" e aguarde o processamento;

Tela find para confirmar a refatoração de posicionamento de pacote

  • 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";

Pop-up de remoção de pacote vazio

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";

Limpando o projeto

  • 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";

Invalidando e restartando cache do Android Studio

  • No pop-up que se abrir clique em "Invalidate and Restart".

Pop-up de confirmação de invalidação de cache

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.

Folder .idea em projeto

É 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:

Estrutura física final de projeto (com pacotes divididos)

Compactando os pacotes:

  • Clicando em "Show Options Menus";
  • Depois clicando em "Compact Middle Packages".

Temos:

Estrutura física final de projeto (com pacotes compactados)

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);

Solicitando ID de canal em YouTube Channel ID

  • Clique em "Get YouTube Channel ID";
  • Em "YOUTUBE CHANNEL ID, INFO & STATISTICS" você terá também o ID do canal:

Obtendo ID de canal em YouTube Channel ID

  • 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:

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:

Ícone retangular de abertura de aplicativo Android

Ícone circular:

Ícone circular de abertura de aplicativo Android

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:

Splash Screen do Android para o canal Emagrecer de Vez

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:

Imagem central Splash Screen

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:

Imagem de fundo Splash Screen

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":

Fonte Quicksand Variable em título

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:

Família de fontes do banner do canal Emagrecer de Vez no YouTube

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:

Topo do app Android de Emagrecer de Vez

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:

Logo do canal YouTube do app

Imagem que deverá ter as suas cinco versões respeitando os 65dp x 65dp:

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.

Para o menu:

Menu principal do aplicativo Android

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:

Ícone vetorial para a opção Vídeo

Para a opção Redes, ic_social_networks.xml:

Ícone vetorial para a opção Redes

Para a opção PlayLists, ic_playlist_color.xml:

Ícone vetorial para a opção PlayLists

Para a opção Tribo, ic_tribe_color.xml:

Ícone vetorial para a opção Tribo

Para a opção Livros, ic_book_cover_color.xml:

Ícone vetorial para a opção Livros

Para a opção Cursos, ic_courses_color.xml:

Ícone vetorial para a opção Cursos

Para a opção Sobre o dono do canal, ic_about.xml:

Ícone vetorial para a opção Sobre

Para a opção Comercial, ic_business.xml:

Ícone vetorial para a opção Comercial

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:

Tela de Último vídeo

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:

Tela de Redes sociais e sites

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:

Ícones vetoriais de lista com 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:

Ícone vetorial para a conta Instagram

Para a conta Facebook, ic_facebook_color.xml:

Ícone vetorial para a conta Facebook

Para a conta YouTube, ic_youtube_color.xml:

Ícone vetorial para a conta YouTube

Para o Blog, ic_blog_color.xml:

Ícone vetorial para o Blog

Para o PodCast, ic_podcast_color.xml:

Ícone vetorial para o PodCast

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:

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:

Ícone vetorial de cada PlayList do canal

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:

Tela com a Tribo do canal

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:

Ícone vetorial de item de tribo

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:

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 vetorial do livro Este Não É Mais Um Livro De Dieta

Ícone do livro "Emagrecer De Vez", ic_book_emagrecer_de_vez.xml:

Ícone vetorial do livro Emagrecer De Vez

Ícone do livro "50 Receitas Para Emagrecer De Vez", ic_book_50_receitas_para_emagrecer_de_vez.xml:

Ícone do livro 50 Receitas Para Emagrecer De Vez

Ícone do livro "Hipertrofia Muscular - As respostas que você sempre quis saber", ic_book_hipertrofia_muscular_as_respostas_que_voce_sempre_quis_saber.xml:

Ícone vetorial do livro Hipertrofia Muscular - As respostas que você sempre quis saber

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:

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 vetorial do curso Código Emagrecer De Vez

Ícone do curso "RÁPIDO30 - Programa de Emagrecimento Acelerado", ic_course_rapido30_programa_de_emagrecimento_acelerado.xml:

Ícone vetorial do curso RÁPIDO30 - Programa de Emagrecimento Acelerado

Ícone do curso "Tribo Forte", ic_course_tribo_forte.xml:

Ícone vetorial do curso Tribo Forte

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:

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 vetorial do contato via e-mail

Ícone do contato via blog, ic_blog.xml:

Ícone vetorial do contato via blog

Ícone do contato via Facebook Messenger, ic_facebook_messenger_color.xml:

Ícone vetorial do contato via Facebook Messenger

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:

Tela Sobre do canal

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:

Ícone vetorial para push messages

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 abertura de aplicativo.

Tela de Último vídeo liberado em canal

Tela de Último vídeo liberado em canal.

Tela das redes e sites do canal

Tela das redes e sites do canal.

Tela de PlayLists canal

Tela de PlayLists canal.

Tela de Tribo exclusiva do canal

Tela de Tribo exclusiva do canal.

Tela com os Livros do canal

Tela com os Livros do canal. 

Tela com os Cursos do canal

Tela com os Cursos do canal.

Tela Sobre o autor do canal

Tela Sobre o autor do canal.

Tela com os Contatos comerciais do canal

Tela com os Contatos comerciais do canal.

Notificação de novo vídeo

Notificação de novo vídeo.

Notificação em bandeja de notificações

Notificação em bandeja de notificações.

Notificação expandida

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:

➙ Parte 15 [FINAL]... em edição 📑🖋.

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.

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Definindo Fontes em Trechos Não Triviais do AndroidDefinindo Fontes em Trechos Não Triviais do AndroidAndroid
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI AndroidAndroid
Live Templates Para Otimização de Tempo no Android StudioLive Templates Para Otimização de Tempo no Android StudioAndroid
Porque e Como Utilizar Vetores no AndroidPorque e Como Utilizar Vetores no AndroidAndroid

Compartilhar

Comentários Facebook

Comentários Blog (2)

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...
Thyago Neves (1) (0)
20/08/2020
Muito bom, obrigado por continuar fornecendo esse excelente conteúdo Thiengo????

Confesso que sempre me senti confortável em programar Android com o Java, e por isso me senti um pouco desconfortável quando você começou a postar os artigos usando Kotlin, acabei procrastinando um pouco os estudos da linguagem, mas um "projeto" como esse é bem prático, me ajudou bastante a entender melhor como o Kotlin funciona. Só preciso de um computador novo agora pra praticar rs.
Responder
Vinícius Thiengo (0) (0)
21/08/2020
Thyago,

Excelente que você vem curtindo os conteúdos.

Kotlin é bem tranquilo, você vai logo perceber.

É isso.

Surgindo dúvidas, pode enviar.

Bons estudos.

Abraço.
Responder