<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ian Oliveira]]></title><description><![CDATA[I'm Mobile Software Engineer & Community Manager.]]></description><link>https://ianoliveira.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 12:02:53 GMT</lastBuildDate><atom:link href="https://ianoliveira.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Como iniciei na Programação do Zero: Um Guia para Iniciantes]]></title><description><![CDATA[Introdução
Já pensou em criar seus próprios aplicativos, sites ou até jogos, mas não sabe por onde começar?
Fala, galera! Tudo bem com vocês? Espero que sim.No momento em que escrevo este artigo, estou a caminho de outro país (Lima, Peru) para partic...]]></description><link>https://ianoliveira.dev/como-iniciei-na-programacao-do-zero-um-guia-para-iniciantes</link><guid isPermaLink="true">https://ianoliveira.dev/como-iniciei-na-programacao-do-zero-um-guia-para-iniciantes</guid><category><![CDATA[carreira]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Thu, 04 Sep 2025 18:16:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734390411695/016e71fe-6bd0-4ad1-8514-8ed8430462cf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introducao"><strong>Introdução</strong></h2>
<p>Já pensou em criar seus próprios aplicativos, sites ou até jogos, mas não sabe por onde começar?</p>
<p>Fala, galera! Tudo bem com vocês? Espero que sim.<br />No momento em que escrevo este artigo, estou a caminho de outro país (Lima, Peru) para participar de um evento do Google sobre comunidades. Durante essa viagem, decidi compartilhar um pouco da minha história com a tecnologia e mostrar como iniciei <strong>do absoluto zero</strong>.</p>
<p>Eu só tinha um computador velho com Windows 7 e um sonho. 🥺</p>
<h2 id="heading-o-que-e-programacao-e-por-que-aprender"><strong>O que é programação e por que aprender?</strong></h2>
<p>Programação de computadores nada mais é do que mandar no computador e pedir pra ele fazer coisas pra você, o computador de fato só entende zero e um, já ouviu falar que os computadores são burros? Então isso é bem verdade.</p>
<p>Mas Ian, como eu peço para ele fazer o que eu quero? Como me comunico com ele? Sim, e aí entram as linguagens de programação: elas são a forma com que você escreve um comando e o computador entende isso e conversa com você. Com elas você pode escrever ou criar programas que rodam no computador ou qualquer dispositivo inteligente.</p>
<p>Por exemplo, o aplicativo do facebook no seu celular foi escrito em uma linguagem de programação chamada <a target="_blank" href="https://kotlinlang.org/"><strong>kotlin</strong></a>, o programa Microsoft office do seu computador foi escrito em uma linguagem chamada .NET.</p>
<p>A programação hoje está em todos os lugares, em forma de software ou programas. Está nos aviões, carros autônomos, celulares, caixa de supermercados, consultórios etc em todos os lugares.</p>
<p>O mundo hoje não evolui mas sem tecnologia, eu nao consigo imaginar com seria se nao existisse por exemplo o (Ifood, Uber, aplicativos de viagem, bancos online etc), por exemplo faz 5 anos que nao vou mais em lotérica ou banco presencialmente pagar contas hahaha, sim era um saco ficar esperando em filas gigantescas só pra pagar uma conta de energia ou internet.</p>
<p>Por isso eu acredito que esse mundo é o presente e futuro. Cada vez se necessita de profissionais capacitados nessa área, seja em engenharia de software ou áreas relacionadas.</p>
<h2 id="heading-beneficios-da-area-de-tecnologia"><strong>Benefícios da área de tecnologia</strong></h2>
<p><strong>Trabalho remoto :</strong> Quando eu entrei pra área de programação eu nunca pensei que isso existiria, sério. 🙀</p>
<p>Com desenvolvimento de software ou áreas relacionadas (marketing digital, design, Scrum master etc) é possível você atuar da sua casa (Home office) ou em qualquer outro lugar do planeta terra. Vc só precisa de duas coisas, <strong>internet e um computador</strong>.</p>
<p>Isso é bem maravilhoso, hoje posso ter qualidade de vida e tempo com a minha família, o que é incrível.</p>
<p><strong>Altas demandas no mercado de trabalho (nacional e internacional):</strong></p>
<p>Como eu falei o mundo hoje não sobrevive sem tecnologia e internet, cada vez mais as pessoas estão dependentes da tecnologia pois ela traz facilidade para as nossas vidas. É muito bom pagar contas da sua casa ou receber um pix, pedir comida ou comprar passagens no conforto do seu lar não é mesmo?</p>
<p>Cada dia mais as empresas e os governos estão adotando tecnologia, o futuro será tecnológico sem dúvidas rsrs é aí que o mercado só cresce. e a medida que cresce faltam vagas e mais vagas. Sim, falta gente capacitada e experiente no mercado.</p>
<p>Outra coisa incrível é que o código que você faz no brasil é o mesmo código que o cara da china faz, ou seja esse mercado é global o que possibilita você no brasil, lá da cidade do interior prestar serviços para empresas estrangeiras e ganhar em moeda forte como dólar por exemplo.</p>
<p>Em um cenário em que o dólar bateu $6.30 nesses últimos dias, você pode até ficar rico fazendo isso, sério imagina ganhar 5k de dólar convertendo para real dar uns 30 mil reais o que e 1% da renda dos mais ricos do país.</p>
<blockquote>
<p><strong><em>Para chegar nesse nível, sim aprenda inglês. Essa é uma das minhas principais metas do ano.</em></strong></p>
</blockquote>
<p><strong>Possibilidade de criar projetos pessoais ou empreender:</strong> Uma das coisas mais incríveis no mundo de desenvolvimento de software é a possibilidade de você criar produtos que resolvam problemas das pessoas e usar isso para ganhar muito dinheiro.</p>
<p>Foi isso que o Mark Zuckerberg fez ao criar o facebook, ele criou um software que resolvia um problema real e acabou que deu muito certo.</p>
<p>Explore ao seu redor e veja quais as suas dificuldades e problemas, o que daria pra resolver com programação seja criando um aplicativo ou sistema da web.</p>
<p>Recentemente eu vi uma história de um garoto de 17 anos que fez 1 milhão de dólares apenas com um aplicativo que usa inteligência artificial. Ele criou um app que tira foto da comida e diz quantas calorias tem para o usuário, o que é bem legal se você segue uma dieta à risca.</p>
<p>Assista <a target="_blank" href="https://www.youtube.com/watch?v=t0U3UREdjmo&amp;t=24s">aqui</a> o case dele. Vale a pena para se inspirar. ✨</p>
<h2 id="heading-minha-historia-como-comecei-nesse-mundo-tech"><strong>Minha história: como comecei nesse mundo tech</strong></h2>
<p><strong>O Início:</strong></p>
<p>Iniciei minha jornada no mundo da programação em 2014 estudando no curso técnico de informática em uma escola pública da minha cidade no interior do piauí, foi ali onde vi as primeiras linhas de código e sim foi algo extraordinário e apaixonante à primeira vista.</p>
<p>Um pouco antes em 2013, encerrando o ensino fundamental não tinha nem noção do que queria seguir na vida rsrsrs informática e computadores na época era algo pra mim ainda de difícil acesso pois era bem caro e meus pais não podiam comprar.</p>
<p>Por sorte no mesmo ano meu irmão tinha conseguido um notebook velho com o meu tio em uma troca, foi ali onde me interessei com computadores e informática pois tinha pego um computador pela primeira vez, e achei algo fantástico pois antes eu só via nas revistas da veja os computadores e ficava com vontade de possuir um.</p>
<p>Naquele mesmo ano de 2013, eu falei pra mãe:</p>
<p>Mãe proximo ano vou fazer fazer curso tecnico de informatica integrado ao ensino médio, me bote lá rsrsr porque não aproveitar a oportunidade e fazer as duas coisas juntas ensino médio + curso técnico, até o momento só curtia ir pra escola de manhã e a única vaga que a mãe conseguiu foi a tarde, não hesitei e mesmo assim eu fui hahaha, foi difícil nos primeiros dias mas depois me acostumei e até achei legal estudar no turno da tarde.</p>
<p>Iniciei o curso achando que ia aprender a mexer em <strong>word</strong>, <strong>excel</strong>, powerpoint alias quem nunca pensou isso, não conhecia nada de programação, sem saber o que era.</p>
<p>A realidade foi que vi as primeiras linhas de código e foi ali que já tinha a perfeita certeza que queria seguir carreira em desenvolvimento de software.</p>
<p>Foram 3 anos de curso, entre 2014 a 2016. No primeiro ano eu aprendi lógica de programação e toda a base de algoritmos, estruturas de dados.</p>
<p>A tecnologia que o professor usou para mostrar a lógica de programação foi o <a target="_blank" href="https://sourceforge.net/projects/visualg30/">VisualG</a> com portugol.</p>
<p>O <strong>VisuAlg</strong> é uma ótima ferramenta para quem quer começar a aprender programação, especialmente porque usa uma linguagem simples, baseada no português estruturado. Ele é muito indicado para iniciantes porque permite praticar lógica de programação sem se preocupar com sintaxes complexas de linguagens mais avançadas.</p>
<p>Lembro que meu primeiro código foi um simples ‘<strong>Olá, Mundo</strong>’, e isso me deixou empolgado!</p>
<p>Depois desse dia eu fui inserido em um novo mundo, onde eu podia me divertir criando pequenos scripts e dando vida a eles.</p>
<p>Nas horas vagas eu via aulas complementares às do curso no youtube, passava as manhãs assistindo cursos de algoritmos e praticava bastante em casa, eu só queria aprender mais e mais.</p>
<p>Lembro que fiquei tão animado que passei as férias estudando Java, Html, Css e Javascript, já queria entrar no segundo ano de curso sabendo o máximo que podia.</p>
<p><strong>Segundo ano ensino médio e de curso:</strong></p>
<p>Acabou que no segundo ano de curso em 2015 o professor ensinou a linguagem <a target="_blank" href="https://www.python.org/">Python</a> com o framework Django, o que foi incrível. Fiquei apaixonado pela tecnologia, comecei a estudá- la mais a fundo em casa e entender como tudo funcionava.</p>
<p>O meu professor do ensino médio era expert em django e então após as aulas eu sempre mostrava pra ele o que eu estava construindo e também aproveitava para tirar dúvidas, com isso ele viu meu potencial e meses depois ele me chamou para ajudá-lo em um projeto de um sistema web, foi ai onde eu fiz meu primeiro freela e pude ganhar algum dinheirinho com programação. Com isso fui virando muito amigo dele e nos falamos até hoje.</p>
<p><em>Um abraço Jefferson se tiver lendo esse artigo 🙏 ✨</em></p>
<p><strong>Terceiro ano ensino médio:</strong></p>
<p>No último ano de curso em 2016 foi ensinado a linguagem Java, e nessa mesma época eu já sabia que queria seguir com a área de programação, então fiz o Enem para tentar faculdade na área.</p>
<p>Aqui na minha cidade os cursos que tinha eram Ciência da Computação na faculdade pública ou Sistemas de Informação na privada.</p>
<p>Nessa mesma época eu comecei a prestar serviços de freelancer desenvolvendo para web com Python e Django, era o que eu tinha aprendido no curso que mais me chamou atenção na época.</p>
<p>Então decidi focar nessa stack e tentar conseguir mais projetos.</p>
<p>Tentei também aprender um pouco de desenvolvimento de apps android mas por conta que tinha um pc muito ruinzinho e não dava conta de compilar o projeto no android studio então abandonei isso e fiquei só na web mesmo e segui nisso.</p>
<p>Por sorte meu antigo professor de python que antes tinha visto minhas habilidades me chamou pra ajudar em um projeto web para um cliente de advocacia da cidade.</p>
<p>Eu fiquei maravilhado pois essa foi a minha primeira oportunidade de fazer parte de uma empresa de desenvolvimento de software, sim meu professor era sócio de uma empresa juntamente com alguns colegas.</p>
<p>Trabalhei com ele alguns meses nesse projeto, foi daí que recebi meu primeiro salário como programador web, até hoje eu lembro foi <strong>300 reais</strong> haha o primeiro mês. eu lembro que quando recebi essa grana fiquei muito entusiasmado com o futuro e pensei é realmente possível fazer grana com programação e e aqui que vou ficar. 🤑</p>
<p>Infelizmente o projeto não foi entregue com sucesso, eu não lembro bem o motivo mas sei que ainda recebi dois meses que atuei no projeto e ainda trabalhei mais outro de graça rsrs. So queria aprender mais e mais.</p>
<p>Apesar de não ter dado certo, eu sou grato por essa oportunidade, ganhei experiência o que é mais importante.</p>
<p>E daí mais à frente eu Fiz o enem pois estava decidido a cursar ciência da computação na UESPI a estadual do piauí, graça a Deus eu passei e em 2017 iniciei na graduação.</p>
<p>Nesse mesmo ano eu tentei fundar uma empresa com um outro amigo da igreja que prestasse serviços freelancer de desenvolvimento web aqui na minha cidade.</p>
<p>Tínhamos criados alguns produtos como sistemas de igrejas e de clínicas, websites e consultorias. Tentamos também vender algumas soluções como sistema de mapeamento de UBS e controle de estoque para a prefeitura, mas acabou que tentamos por um bom tempo negociar o que não deu certo a venda de nenhum deles, tínhamos feitos MVP e tudo mas infelizmente não deu.</p>
<p>De novo, tudo o que sobrou foi a experiência no meio de várias tentativas e falhas, tentativas e falhas. 🤣</p>
<p>Passamos 2017 e 2018 tentando emplacar a empresa mas sem muito sucesso, éramos ruim de vendas hahaha So sabiamos programar mas vender não era nosso forte.</p>
<p><strong>Período de Faculdade:</strong></p>
<p>Em 2018 eu estava no terceiro período da faculdade já indo pro quarto, naquela época o curso era integral o que dificultava eu ter tempo pra focar no negócio que eu estava montando e então decidir desistir de empreender com o meu colega e não colocar mais a nossa software house pra frente.</p>
<p>Tinha decidido focar mais na faculdade, estudar um pouco mais e tentar aplicar para algumas vagas para ser funcionário de uma empresa de fato, visto que tentar montar o próprio negócio naquela época não rolou.</p>
<p>Na faculdade nos primeiros períodos o que mais eu via era cálculo, álgebra e física, sim eu era péssimo nessas matérias, por diversas vezes eu pensei em desistir do curso para focar em outras coisas mas Deus me ajudou e continuei firme, eu tive que pagar calculo || duas vezes e física 3x hahah pensa no desafio grande emplacar isso .</p>
<p>Aqui quero tirar que computação é só para inteligentes, eu era péssimo em cálculo mas o que me ajudou a chegar lá foi a pesistencia e muito estudo.</p>
<p>Ainda em 2018 eu decidi desenvolver tecnologias novas, queria aprender desenvolvimento de aplicativos móveis. Sim voltar em uma meta antiga, então comecei aprender Kotlin para android, comprei um curso na udemy e arrumei outro notebook melhorzinho mas ainda velho.</p>
<p>Acho que foi a primeira vez que tinha comprado algo lá, peguei o boleto e fui no banco pagar depois da faculdade, sim nessa época internet banking eu ainda não tinha acesso, então sempre quando tinha contas ia no banco pagar, pegar uma fila gigante 😭 mas era o que eu queria, tinha fome de conhecimento e estava ansioso pelo o curso.</p>
<p><strong>A chegada do Flutter.</strong></p>
<p>Ainda em março 2018 eu estava em uma comunidade do telegram de devs android e lá alguém postou um <a target="_blank" href="https://www.tecmundo.com.br/software/127691-google-lanca-flutter-beta-unificar-criacao-apps-para-android-ios.htm">link</a> de uma notícia do tecmundo onde falava o seguinte “<strong>Google lança Flutter Beta para unificar criação de apps para Android e iOS</strong>”</p>
<p>A Google lançou durante a MWC 2018 a primeira versão beta do Flutter, sua plataforma de desenvolvimento para criação de apps para Android e iOS. A empresa explica que, com o Flutter, é possível desenvolver apps e games para as duas principais plataformas mobile do mundo simultaneamente, sem que isso implique de qualquer maneira no desempenho ou na funcionalidade desses apps.</p>
<p>Eu li isso e pensei que seria incrível, pra que desenvolver com kotlin apenas para android se posso usar o Flutter para ambas as plataformas 😏</p>
<p>Então decidi pesquisar mais sobre no youtube e de cara vi alguns vídeos tutoriais onde pessoas faziam coisas legais com o framework o que me chamou muito atenção.</p>
<p>Então baixei o sdk do <a target="_blank" href="https://flutter.dev/">Flutter</a> e decidi testar eu mesmo e vi que era bem simples construir interfaces do que com kotlin e android nativo.</p>
<p>Foi aí que decidi largar os estudos em android nativo kotlin e foquei apenas flutter, e lhe digo foi a melhor decisão que pude tomar! 🩵</p>
<p>Há alguns meses eu já tinha desenvolvido o primeiro aplicativo e publiquei na loja. Foi incrível, o primeiro aplicativo que você publica na loja é algo marcante. Eu lembro que levei 2 dias pra fazer-lo e outro pra enviar a loja do android.</p>
<p><strong>2019</strong></p>
<p>Continuei estudando Flutter e até que em 2019 decidi criar conteúdo e palestrar sobre Flutter em meetups de tecnologia.</p>
<p>Um dos momentos mais marcantes foi quando participei do maior evento de computação do meu estado como palestrante do <a target="_blank" href="https://www.piauinoticias.com/educa%C3%A7%C3%A3o/71395-enucompi-recebe-400-inscritos-e-tem-minicurso-de-aluno-da-uespi.html">Enucomp 2019</a>, como flutter era extremamente novo acabou que foi pra mais de 100 pessoas inscritas na palestra o que foi incrível!</p>
<p>Nunca pensei que fosse palestrar para mais de 100 pessoas. Naquele dia eu realmente tive certeza que estava no caminho certo.</p>
<p>Por causa desse evento acabei sendo chamado para o time do <a target="_blank" href="https://flutterando.com.br/">Flutterando</a> a maior comunidade de flutter na época, o que foi incrível, lá conheci outros experts em flutter.</p>
<p>Ainda em 2019 eu fundei a comunidade local de flutter do estado chamada de <a target="_blank" href="https://www.instagram.com/flutter_piaui/?hl=en">Flutter Piauí</a> e começamos a fazer vários meetups e eventos na cidade pra divulgar a ferramenta.</p>
<p>Foi dai que começou minha paixão por comunidades de tecnologia e virei community manager.</p>
<p><strong>2020 a 2023 — Pandemia 😷</strong></p>
<p>Em 2020 eu ainda estava na faculdade, se nao me engano 5 período onde veio a pandemia o que foi bem ruim, lembro que todo mundo teve que ficar trancado dentro de suas casas sem poder sair, foi aí que os eventos online ganharam fama e eu comecei a palestrar de forma online sobre flutter ao mesmo tempo que estudava todo dia coisas novas sobre o framework.</p>
<p>Nessa época me envolvi muitos com eventos e comunidades online. Fui compartilhando conhecimentos com quem eu podia.</p>
<p>Nessa mesma época eu acabei arrumando minha primeira vaga como desenvolvedor Flutter Júnior na empresa de um dos colegas da comunidade chamada Fteam.</p>
<p>Flutter tava em completa ascensão mas ter bons desenvolvedores na época era ainda bem difícil e como eu já tava me preparando desde de 2018 eu entrei lá e comecei atuar sendo terceirizado a diversas empresas e projetos e isso me fez crescer muito rapidamente.</p>
<p>Passei 3 anos e meio nessa empresa onde eu agradeço de coração pela a oportunidade pois lá realmente eu cresci e conheci pessoas muitos boas que até hoje são meus amigos.</p>
<p>Em seguida, continuei fazendo eventos, me envolvendo com a comunidade e viajando bastante, conheci muita gente legal e estados!</p>
<p>Aqui na minha cidade ainda em 2022 fundei o <a target="_blank" href="https://gdg.community.dev/gdg-parnaiba/"><strong>GDG Parnaiba</strong></a> uma comunidade apoiada pelo o Google e isso me levou a uma viagem pra Colômbia e agora Peru, também a conhecer os escritórios do Google No Brasil tanto em SP como em BH.</p>
<p><strong>2024 e 2025</strong></p>
<p>Nos últimos dois anos estou trabalhando em plena era da IA estou trabalhando nos meus próprios aplicativos como desenvolvedor solor e em alguns produtos que usam IA na empresa onde eu Atuo Hoje. O que é incrível 🤩</p>
<p>Estou bem feliz com tudo que está acontecendo. Obrigado Deus!</p>
<h2 id="heading-passo-a-passo-para-iniciar-na-programacao-do-zero"><strong>Passo a passo para iniciar na programação do zero</strong></h2>
<h2 id="heading-passo-1-defina-seus-objetivos"><strong>Passo 1: Defina seus objetivos</strong></h2>
<p>Antes de começar, reflita:</p>
<ul>
<li><p><strong>Você quer aprender programação por hobby, para mudar de carreira ou para resolver um problema específico?</strong></p>
</li>
<li><p><strong>Qual área mais te atrai: desenvolvimento web, aplicativos móveis, backend, frontend, ciência de dados, IA ou outra?</strong></p>
</li>
</ul>
<p>Saber aonde você quer chegar é essencial. Se sua meta é realmente seguir carreira, isso já é o suficiente para te motivar a buscar cada vez mais conhecimento.</p>
<p>Quando eu comecei, não sabia exatamente qual área iria seguir. Só tinha uma certeza: queria ser desenvolvedor. Comecei na web com Django e, anos depois, descobri minha verdadeira paixão: o <strong>Desenvolvimento Mobile.</strong></p>
<p>💡 <strong>Dica:</strong> apenas comece. Teste várias áreas, descubra o que gosta mais e depois foque nisso.</p>
<h2 id="heading-passo-2-aprenda-os-fundamentos-algoritmos-e-logica-de-programacao"><strong>Passo 2: Aprenda os fundamentos, Algoritmos e Lógica de Programação</strong></h2>
<blockquote>
<p><em>“Você pode praticar arremessos oito horas por dia, mas se sua técnica estiver errada, tudo o que você se tornará será muito bom em arremessar da maneira errada. Pratique os fundamentos e o nível de tudo o que você fizer vai subir.” — Michael Jordan</em></p>
</blockquote>
<p>Se você quer ser programador, precisa dominar os fundamentos. Eles são a base de tudo.</p>
<p>Em 2014, no meu curso técnico, meu professor explicou o que são algoritmos:<br />👉 <em>“Algoritmos são uma sequência de passos lógicos que levam à resolução de problemas.”</em></p>
<p>Essa frase ficou gravada em mim até hoje. 🥺</p>
<p>Pode parecer lento no começo, mas aprender lógica é o melhor investimento da sua jornada. Ela te prepara para resolver problemas complexos, aumenta sua confiança e te dá independência para criar soluções.</p>
<h3 id="heading-por-que-os-fundamentos-sao-importantes"><strong>Por que os fundamentos são importantes?</strong></h3>
<ul>
<li><p><strong>Construção de uma base sólida:</strong> assim como uma casa, sem fundação qualquer estrutura desmorona.</p>
</li>
<li><p><strong>Conhecimento transferível:</strong> os conceitos básicos funcionam em qualquer linguagem de programação.</p>
</li>
<li><p><strong>Resolução de problemas:</strong> mais do que escrever código, você aprende a pensar de forma lógica.</p>
</li>
<li><p><strong>Evitar erros comuns:</strong> fundamentos te ensinam boas práticas desde cedo.</p>
</li>
</ul>
<h2 id="heading-passo-3-escolha-sua-primeira-linguagem-de-programacao"><strong>Passo 3: Escolha sua primeira linguagem de programação</strong></h2>
<p>Depois de dominar algoritmos, é hora de escolher uma linguagem.</p>
<p>Algumas opções recomendadas:</p>
<ul>
<li><p><strong>Python:</strong> simples, versátil e ótimo para iniciantes.</p>
</li>
<li><p><strong>JavaScript:</strong> ideal para criar sites e projetos web.</p>
</li>
<li><p><strong>Dart:</strong> perfeito para quem quer desenvolver aplicativos com Flutter.</p>
</li>
</ul>
<p>Minha primeira linguagem foi <strong>Python</strong>, apresentada no curso técnico. Hoje, com experiência, recomendo Python, JavaScript ou Java como ótimos pontos de partida.</p>
<p>➡️ <strong>Importante:</strong> escolha uma, foque até ganhar segurança e só depois explore outras. Como dizia meu professor: <em>“A primeira linguagem é a mais difícil. Depois, todas ficam mais fáceis.”</em></p>
<h2 id="heading-passo-4-use-recursos-acessiveis-e-gratuitos"><strong>Passo 4: Use recursos acessíveis e gratuitos</strong></h2>
<p>Você não precisa gastar muito para começar. Algumas opções:</p>
<ul>
<li><p>Codecademy</p>
</li>
<li><p>Cursos no YouTube e materiais abertos na internet.</p>
</li>
</ul>
<h2 id="heading-passo-5-pratique-com-projetos-pequenos"><strong>Passo 5: Pratique com projetos pequenos</strong></h2>
<p>Aprender programação é como aprender um idioma: você só melhora praticando.</p>
<p>💡 Sugestões de projetos iniciais:</p>
<ul>
<li><p>Criar uma calculadora simples.</p>
</li>
<li><p>Desenvolver um jogo da forca.</p>
</li>
<li><p>Fazer um site pessoal com HTML, CSS e JS.</p>
</li>
</ul>
<p>Esses projetos parecem simples, mas ensinam muito.</p>
<h2 id="heading-passo-6-participe-de-comunidades-e-busque-ajuda"><strong>Passo 6: Participe de comunidades e busque ajuda</strong></h2>
<p>A jornada é muito mais leve quando você não está sozinho.</p>
<p>Participe de fóruns, grupos e comunidades em algumas plataformas como Telegram, Whatsapp e discord.</p>
<p>Trocar experiências acelera seu aprendizado e te mostra que todo mundo erra no começo e isso é normal.</p>
<h2 id="heading-passo-7-participe-de-eventos-de-tecnologia"><strong>Passo 7: Participe de eventos de tecnologia</strong></h2>
<p>Acredite em mim: envolva-se com a comunidade local de desenvolvedores. Aprenda com outros desenvolvedores: participar de eventos de tecnologia, palestrar e contribuir com conteúdos pode expô-lo a uma variedade de ideias, tecnologias e abordagens diferentes.</p>
<p>Isso pode enriquecer seu conhecimento e ampliar sua perspectiva sobre a indústria de desenvolvimento de software.</p>
<p>Conheça novas pessoas e faça networking nos eventos, pois isso pode abrir portas para novos contatos e oportunidades valiosas em sua carreira.</p>
<h2 id="heading-dicas-extras-para-manter-a-motivacao"><strong>Dicas extras para manter a motivação</strong></h2>
<ul>
<li><p>Tenha paciência com seus erros: eles fazem parte do processo.</p>
</li>
<li><p>Estabeleça metas pequenas e comemore suas vitórias.</p>
</li>
<li><p>Se possível, estude com amigos ou participe de bootcamps.</p>
</li>
</ul>
<p>Use a IA como guia, não como muleta, IA pode explicar conceitos, sugerir código, resumir documentações mas não substitui a prática: você só aprende de verdade escrevendo, testando e errando pois foi assim que eu aprendi.</p>
<p>Aprenda a pensar antes de pedir à IA, <strong>e</strong>screva sua lógica, tente resolver e só depois peça ajuda assim você entende a solução, em vez de só copiar/colar código.</p>
<h2 id="heading-conclusao"><strong>Conclusão ✅</strong></h2>
<p>Qualquer pessoa pode aprender programação não importa idade, formação ou de onde vem. O principal ponto é gostar pois não é facil e quando se ama o que faz o processo fica bem legal.</p>
<p>Eu mesmo já pensei em desistir várias vezes. Fui ruim em matemática, reprovei em cálculo na faculdade, mas continuei. O que me manteve foi <strong>persistência</strong>.</p>
<p>Tecnologia hoje é presente e o futuro então sim é uma área muito boa para se construir carreira.</p>
<p>Se eu consegui aprender do zero, você também pode. O mais importante é <strong>dar o primeiro passo</strong>.</p>
<p>Espero que você tenha gostado! Se tiver alguma dúvida ou contribuição, deixe nos comentários ou me mande nas redes sociais!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos ou assine a neswletter 🚀</p>
<h2 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h2>
<p><a target="_blank" href="https://www.github.com/iang12">GitHub</a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/">LinkedIn</a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/">Instagram</a> | <a target="_blank" href="https://twitter.com/ianoliveirag12">Twitter</a> | <a target="_blank" href="https://medium.com/@ianoliveirag12/como-iniciei-na-programa%C3%A7%C3%A3o-do-zero-um-guia-para-iniciantes-1e93c1261c06">Medium</a></p>
]]></content:encoded></item><item><title><![CDATA[Usando a Siri para executar atalhos no seu aplicativo Flutter através do Apple shortcuts]]></title><description><![CDATA[Fala galera, tudo blz? Hoje vamos aprender como integrar o seu app Flutter ao assistente do iOS a Siri. Recentemente precisei desenvolver um novo recurso em um aplicativo que estou trabalhando e a funcionalidade era exatamente pedir pra siri através ...]]></description><link>https://ianoliveira.dev/usando-a-siri-para-executar-atalhos-no-seu-aplicativo-flutter-atraves-do-apple-shortcuts</link><guid isPermaLink="true">https://ianoliveira.dev/usando-a-siri-para-executar-atalhos-no-seu-aplicativo-flutter-atraves-do-apple-shortcuts</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Siri]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 19 May 2025 13:12:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/AGRtDoZlpYw/upload/38448acd2075d465afa3635f52c1e2ea.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala galera, tudo blz? Hoje vamos aprender como integrar o seu app Flutter ao assistente do iOS a Siri. Recentemente precisei desenvolver um novo recurso em um aplicativo que estou trabalhando e a funcionalidade era exatamente pedir pra siri através de voz que ativasse algo no meu aplicativo.</p>
<p>Essa comunicação é algo bem legal e venho aqui ensinar tudo isso pra vocês.</p>
<p>Ao integrar os Atalhos da Siri, seu aplicativo pode destacar suas principais funcionalidades, oferecendo aos usuários maneiras novas e interativas de interagir com ele — uma estratégia simples, porém eficaz, para se manter à frente da concorrência.</p>
<h1 id="heading-o-que-sao-apple-shortcuts-ou-atalhos">O que são Apple Shortcuts ou Atalhos</h1>
<p>Segundo o <a target="_blank" href="https://developer.apple.com/shortcuts/">site</a> da apple: Um <em>atalho</em> é uma maneira rápida de realizar uma ou mais tarefas com seus aplicativos economizando tempo em ações repetitivas, como definir alarmes ou lembretes. O aplicativo <strong>Atalhos</strong> permite que você crie seus próprios atalhos com várias etapas. Por exemplo, crie um atalho para "Tempo de Surfe" que exibe o relatório de surfe, informa o horário previsto para a praia e inicia sua playlist de músicas de surfe.</p>
<p>Os Shortcuts ficam disponíveis assim que o aplicativo é instalado no iOS e podem ser executados no Spotlight, na tela Inicial, no aplicativo Atalhos ou até mesmo usando a voz com a <strong>Siri</strong> que é o que vamos fazer hoje.</p>
<p>E para fazermos o nosso aplicativo Flutter comunicar com os Atalhos do iOS vamos usar algo chamado <a target="_blank" href="https://developer.apple.com/documentation/AppIntents">App Intents</a> que oferece funcionalidades para integrar profundamente as ações e o conteúdo do seu aplicativo com as experiências do sistema em todas as plataformas, incluindo Siri, Spotlight, widgets, controles e muito mais.</p>
<h1 id="heading-utilizando-as-intents-no-flutter-com-o-package-intelligence">Utilizando as Intents no Flutter <strong>com o package</strong> Intelligence</h1>
<h3 id="heading-1-adicionando-a-dependencia-em-seu-projeto">1 — Adicionando a dependência em seu projeto</h3>
<p>Vamos começar adicionando a dependência ao nosso arquivo <code>pubspec.yaml.</code></p>
<p>Instale o pacote a partir da linha de comando com o Flutter</p>
<pre><code class="lang-bash">$ flutter pub add intelligence
</code></pre>
<p>Ou adicione <code>intelligence</code> diretamente em seu <code>pubspec.yaml</code> e execute <code>flutter pub get</code> no momento da criação desse artigo ele está na versão <strong>0.2.0.</strong></p>
<pre><code class="lang-dart">dependencies:
  intelligence: ^<span class="hljs-number">0.2</span><span class="hljs-number">.0</span>
</code></pre>
<p>Agora, no seu código Dart, você pode importar o package:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:intelligence/intelligence.dart'</span>;
</code></pre>
<h3 id="heading-2-vamos-criar-um-novo-aplicativo-flutter-para-o-nosso-exemplo-de-hoje">2 - Vamos criar um novo aplicativo Flutter para o nosso exemplo de hoje.</h3>
<pre><code class="lang-bash">flutter create flutter_siri_example
</code></pre>
<p>Após o nosso projeto criado vamos fazer a configuração na parte nativa do iOS, então abra a pasta <code>ios</code> no <strong>Xcode</strong> clicando com o botão direito no vsCode.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747316853995/56c60ac9-355b-4021-8781-14092a0117c8.png" alt class="image--center mx-auto" /></p>
<p>Agora você precisa definir a versão mínima do iOS para 16.0 no Xcode para o projeto, veja a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747316562362/b5d98f0b-eebc-4eeb-8611-a8a4cc6ea545.png" alt class="image--center mx-auto" /></p>
<p>Após feito isso vamos integrar os comandos que queremos que a siri interprete em nosso aplicativo.</p>
<p>Abra o Xcode e crie uma novo arquivo Swift. Vamos usar o exemplo padrão do Flutter de app contador e adicionar dois comandos, um para <strong>incrementar</strong> e outro para <strong>resetar</strong> o valor.</p>
<p>Crie o arquivo <code>IncrementeIntent.Swift</code> no Xcode, veja o exemplo abaixo e código que você precisa escrever.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747576729848/559326cf-3217-4c70-825e-89a98c88d672.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> AppIntents
<span class="hljs-keyword">import</span> intelligence

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">IncrementIntent</span>: <span class="hljs-title">AppIntent</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> title: <span class="hljs-type">LocalizedStringResource</span> = <span class="hljs-string">"Aumentar contador"</span>
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> openAppWhenRun: <span class="hljs-type">Bool</span> = <span class="hljs-literal">true</span>

  @<span class="hljs-type">MainActor</span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">perform</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; some <span class="hljs-type">IntentResult</span> {
    <span class="hljs-type">IntelligencePlugin</span>.notifier.push(<span class="hljs-string">"increment"</span>)
    <span class="hljs-keyword">return</span> .result()
  }
}
</code></pre>
<p>Vamos criar nossa segunda Intent onde vai interpretar o comando de reset do valores do contador.</p>
<p>Crie um arquivo chamado <code>RefreshIntent.Swfit</code> conforme a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747576907353/6448a7b8-23b3-4b1d-9efb-4a454b8db102.png" alt="Xcode" class="image--center mx-auto" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> AppIntents
<span class="hljs-keyword">import</span> intelligence

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">RefreshIntent</span>: <span class="hljs-title">AppIntent</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> title: <span class="hljs-type">LocalizedStringResource</span> = <span class="hljs-string">"Atualizar contador"</span>
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> openAppWhenRun: <span class="hljs-type">Bool</span> = <span class="hljs-literal">true</span>

  @<span class="hljs-type">MainActor</span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">perform</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; some <span class="hljs-type">IntentResult</span> {
    <span class="hljs-type">IntelligencePlugin</span>.notifier.push(<span class="hljs-string">"refresh"</span>)
    <span class="hljs-keyword">return</span> .result()
  }
}
</code></pre>
<p>Em seguida vamos criar último arquivo para interpretar as strings dos comandos e acionar a Intent correta declarado acima apenas falando uma frase específica para a Siri.</p>
<p>Veja o exemplo abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747577125756/8c665676-aefa-4883-bc16-db2bc3f88e7a.png" alt="Xcode" class="image--center mx-auto" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> AppIntents

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">AllAppShortcuts</span>: <span class="hljs-title">AppShortcutsProvider</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> appShortcuts: [<span class="hljs-type">AppShortcut</span>] {
       <span class="hljs-keyword">return</span> [
            <span class="hljs-type">AppShortcut</span>(
                intent: <span class="hljs-type">IncrementIntent</span>(),
                phrases: [
                    <span class="hljs-string">"Incrementar número no \(.applicationName)"</span>,
                    <span class="hljs-string">"Adicionar número no \(.applicationName)"</span>,
                    <span class="hljs-string">"Aumentar número no \(.applicationName)"</span>,

                ]
            ),
            <span class="hljs-type">AppShortcut</span>(
                intent: <span class="hljs-type">RefreshIntent</span>(),
                phrases: [
                    <span class="hljs-string">"Resetar contador no \(.applicationName)"</span>
                ]
            ),
        ]
    }
}
</code></pre>
<h3 id="heading-agora-o-lado-do-flutter">Agora o lado do Flutter 💙</h3>
<p>No lado do Flutter na nossa página principal vamos chamar o método para escutar se o aplicativo foi aberto pela a Siri e interpretando os comandos.</p>
<pre><code class="lang-dart"> <span class="hljs-keyword">void</span> _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  <span class="hljs-keyword">void</span> _refreshCounter() {
    setState(() {
      _counter = <span class="hljs-number">0</span>;
    });
  }

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> initState() {
    <span class="hljs-keyword">super</span>.initState();
    _initSiri();
  }

  <span class="hljs-keyword">void</span> _initSiri() {
    <span class="hljs-keyword">if</span> (Platform.isIOS) {
      Intelligence().selectionsStream().listen(_trackSiri);
    }
  }

  <span class="hljs-keyword">void</span> _trackSiri(<span class="hljs-built_in">String</span> selection) {
    log(<span class="hljs-string">'Siri Command triggered: <span class="hljs-subst">$selection</span>'</span>);
    <span class="hljs-keyword">switch</span> (selection) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'increment'</span>:
        _incrementCounter();
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'refresh'</span>:
        _refreshCounter();
        <span class="hljs-keyword">break</span>;

      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">break</span>;
    }
  }
</code></pre>
<p>O código acima é responsável por ouvir os comandos passados para a Siri e acionar os métodos corretos que no nosso caso são dois em nosso app.</p>
<p><code>_incrementCounter</code> e <code>_refreshCounter</code> o resto do código você pode consultar no link do repositório <a target="_blank" href="https://github.com/iang12/flutter_siri_example">aqui</a>.</p>
<h1 id="heading-rodando-e-testando-o-aplicativo">Rodando e testando o aplicativo</h1>
<p>Execute o aplicativo no simulador do iOS e ative a Siri com a opção mostrada abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747657076652/775b1054-ba85-4c10-9f40-b97c8188b94f.png" alt="Vs Code" class="image--center mx-auto" /></p>
<p>Quando a Siri detectar pela primeira vez o comando de voz, pode ser que o iOS peça para adicionar o comando no app Atalhos do iOS mas nos meus testes teve vez que foi automático mas se aparecer apenas clique em <strong>Ativar</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747658897621/5e5eb5ef-bbd2-4210-93d5-160fa368fe47.png" alt="Apple Shortcuts no iOS" class="image--center mx-auto" /></p>
<p>Veja o link do video do aplicativo de demonstração em funcionamento abaixo: 👇🏻</p>
<p><a target="_blank" href="https://drive.google.com/file/d/1CddUVKZt8iCdSNgNx7Z_oLPSNrGQOk5C/view?usp=sharing">https://drive.google.com/file/d/1CddUVKZt8iCdSNgNx7Z_oLPSNrGQOk5C/view?usp=sharing</a></p>
<h1 id="heading-conclusao"><strong>Conclusão ✅</strong></h1>
<p>Bom foi isso, os atalhos da Siri podem automatizar diversas tarefas, como iniciar aplicativos, enviar mensagens, definir lembretes e deixar nossos apps muito mais inteligentes e legais. O céu é o limite ✨</p>
<p>Você pode consultar o código de exemplo no <a target="_blank" href="https://github.com/iang12/flutter_siri_example">github</a>.</p>
<p>Obrigado por ler até aqui. 😁</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre desenvolvimento móvel 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>Github</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Gerando termos de uso e política de privacidade para aplicativos]]></title><description><![CDATA[Fala, mobile devs! 👨🏻‍💻
Hoje vou ensinar vocês a gerar os Termos de Uso ou a Política de Privacidade para nossos aplicativos de forma automatizada e simples.
Toda vez que vamos publicar um app nas lojas, enfrentamos a mesma chatice: é necessário i...]]></description><link>https://ianoliveira.dev/gerando-termos-de-uso-e-politica-de-privacidade-para-aplicativos</link><guid isPermaLink="true">https://ianoliveira.dev/gerando-termos-de-uso-e-politica-de-privacidade-para-aplicativos</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Android]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 12 May 2025 20:40:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747078795680/54a78116-df2b-46c8-9e44-40d3ddd3ddcb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, mobile devs! 👨🏻‍💻</p>
<p><strong>Hoje vou ensinar vocês a gerar os Termos de Uso ou a Política de Privacidade para nossos aplicativos de forma automatizada e simples.</strong></p>
<p>Toda vez que vamos publicar um app nas lojas, enfrentamos a mesma chatice: é necessário informar o link dos nossos termos ou da política de privacidade.</p>
<p>A boa notícia é que encontrei um site muito útil que tem me ajudado bastante com isso, e resolvi vir aqui compartilhar com vocês.</p>
<p>O site se chama: <a target="_blank" href="https://www.privacypolicytemplate.net/">https://www.privacypolicytemplate.net/</a></p>
<p>No exemplo de hoje vamos gerar nossas politicas de privacidade mas no site tem termos também.</p>
<h2 id="heading-o-que-e-politica-de-privacidade"><strong>O que e politica de privacidade</strong>?</h2>
<p>É um documento legal que detalha como um site coleta, armazena, compartilha e vende dados sobre seus visitantes. Esses dados geralmente incluem itens como nome, endereço, data de nascimento, estado civil, histórico médico e comportamento do consumidor do usuário.</p>
<h1 id="heading-criando-nossos-termos">Criando nossos termos</h1>
<p>O primeiro passo é acessar o <a target="_blank" href="https://www.privacypolicytemplate.net/">site</a> e clique em <strong>App</strong> e em seguida você sera redirecionado para o site <a target="_blank" href="https://app.termsfeed.com/">https://app.termsfeed.com/</a></p>
<p>Veja a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747079098491/f4bcf56d-8bd7-4ba8-b514-497b38decf18.png" alt class="image--center mx-auto" /></p>
<p>Em seguida coloque o nome do aplicativo e os dados que ele vai solicitando no passo a passo.</p>
<p>Veja o exemplo: 👇🏻</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747078498151/dae7684e-f298-46d7-a632-4c7bd949347b.png" alt class="image--center mx-auto" /></p>
<p>Se eu aplicativo coletar dados pessoais do usuário apenas vá marcando quais: 👇🏻</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747078586782/53f710e1-e644-4687-a93e-84038459dbf5.png" alt class="image--center mx-auto" /></p>
<p>O <strong>quarto</strong> passo é colocar o email ou qualquer outro contato para receber dúvidas sobre sua politica de privacidade.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747079627342/26dc114c-dcc0-404c-9b1c-b419262e7acb.png" alt class="image--center mx-auto" /></p>
<p>E para finalizar clique na segunda opção para conseguir criar gratuitamente sua politica de privacidade para seu aplicativo. 👇🏻</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747079761539/479f9403-5487-4241-bb4f-7e7f0853c741.png" alt class="image--center mx-auto" /></p>
<p>No <strong>sexto</strong> e último passo ele pede o email pra lhe enviar o link da politica criada para seu app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747078616515/29afa094-a363-4eaa-ab66-4407e70ea447.png" alt class="image--center mx-auto" /></p>
<p>Agora no Google Play console insira a URL da sua politica de privacidade e seja feliz:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747081413626/b750cdf6-9d76-4379-a9d7-a1ad9e972ee0.png" alt class="image--center mx-auto" /></p>
<p>Na Apple também👇🏻</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747081495547/1ec24070-0e64-47ea-b2c4-a4b16652c556.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusao"><strong>Conclusão</strong></h1>
<p>Bom, nos meus projetos pessoais eu sempre uso esse site e tem me ajudado bastante! ✨</p>
<p>Obrigado por ler até aqui. 🎉</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir aplicativos incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre engenharia de software 📲 🚀</p>
<h2 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h2>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Observabilidade no Flutter com Open Telemetry e Elastic APM]]></title><description><![CDATA[O que é Observabilidade?
Observabilidade (ou o11y ) nos permite entender um sistema de fora, permitindo-nos fazer perguntas sem conhecer o funcionamento interno desse sistema, baseado apenas nas suas saídas externas, como logs, métricas e traces.
Com...]]></description><link>https://ianoliveira.dev/observabilidade-no-flutter-com-open-telemetry-e-elastic-apm</link><guid isPermaLink="true">https://ianoliveira.dev/observabilidade-no-flutter-com-open-telemetry-e-elastic-apm</guid><category><![CDATA[elasticsearch]]></category><category><![CDATA[Crashlytics]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Tue, 22 Apr 2025 20:33:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745326651907/a6d02063-7b87-4e78-a927-b9f36898ec25.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-o-que-e-observabilidade"><strong>O que é Observabilidade?</strong></h1>
<p>Observabilidade (ou <strong>o11y</strong> ) nos permite entender um sistema de fora, permitindo-nos fazer perguntas sem conhecer o funcionamento interno desse sistema, baseado apenas nas suas saídas externas, como <strong>logs</strong>, <strong>métricas</strong> e <strong>traces.</strong></p>
<p><em>Com isso podemos solucionar e lidar facilmente com problemas novos (ou seja, "desconhecidos").</em></p>
<p>Ela oferece monitoramento de desempenho de ponta a ponta, permitindo que as organizações monitorem todo o ciclo de vida de uma aplicação, desde as interações do usuário no front-end até os processos de back-end.</p>
<p>Se você está apenas começando com esse tema, as postagens abaixo ajudarão você a se aprofundar um pouco mais:</p>
<ul>
<li><p><a target="_blank" href="https://storiesfromtheherd.com/unpacking-observability-a-beginners-guide-833258a0591f"><strong>Desvendando a Observabilidade:</strong></a> Um guia para iniciantes</p>
</li>
<li><p><a target="_blank" href="https://medium.com/dzerolabs/observability-journey-understanding-logs-events-traces-and-spans-836524d63172"><strong>Logs, Events, Traces, and Spans</strong></a> : Os Fundamentos</p>
</li>
</ul>
<h1 id="heading-o-que-e-open-telemetry"><strong>O que</strong> <strong>é Open Telemetry?</strong></h1>
<p>OpenTelemetry (OTel) segundo o <a target="_blank" href="https://opentelemetry.io/">site</a>: <strong>é uma coleção de APIs, SDKs e ferramentas. Use-o para instrumentar, gerar, coletar e exportar dados de telemetria (métricas, logs e rastros) para ajudar você a analisar o desempenho e o comportamento do seu software.</strong></p>
<p>É também um framework de código aberto para instrumentação de código, e muitos dos principais fornecedores de ferramentas de observabilidade o suportam.</p>
<p>Ele é independente de fornecedor, então, se você optar por trocar sua ferramenta de coleta de dados para uma nova de fornecedor diferente, não será prejudicado pois isso significa que ele não está vinculado a nenhum fornecedor específico de monitoramento ou observabilidade.</p>
<p>A ferramenta que eu uso atualmente para coletar os dados se chama <a target="_blank" href="https://www.elastic.co/pt/observability/application-performance-monitoring">Elastic APM</a> e vou falar um pouco dela mais tarde mas você pode usar qualquer outra de sua preferência.</p>
<p>Antes de começar a usar o OpenTelemetry , é importante entender alguns conceitos básicos, como <strong>Spans</strong> e <strong>Traces</strong>.</p>
<p>A instrumentação de código com a OpenTelemetry é suportada por muitas linguagens de programação populares como o exemplo abaixo:</p>
<p><a target="_blank" href="https://opentelemetry.io/docs/languages/"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745322222244/83b73586-1989-4623-a01e-62161ef9c3a0.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-instrumentacao-manual-vs-automatica"><strong>Instrumentação manual vs. automática</strong></h2>
<p>Existem duas formas de instrumentar uma aplicação com o OpenTelemetry: manual e automática. No caso do Flutter, como ainda não há um SDK oficial, utilizamos a instrumentação manual.</p>
<p>Já em outras stacks, é possível usar a instrumentação automática, que oferece um conjunto de módulos predefinidos e prontos para uso. Com isso, é possível coletar dados de telemetria com pouca ou nenhuma necessidade de alterações no código.</p>
<h1 id="heading-o-que-e-elastic-apm-application-performance-monitoring">O que é Elastic APM (Application Performance Monitoring)</h1>
<p>É uma solução de observabilidade oferecida pelo Elastic para para instrumentalizar e observar aplicações backend ou frontend. Com ela é possível monitorar o desempenho de aplicações em tempo real coletando dados sobre como sua aplicação está se comportando — por exemplo:</p>
<ul>
<li><p>Quanto tempo as requisições levam para serem processadas.</p>
</li>
<li><p>Onde estão os gargalos (funções lentas, chamadas de banco de dados demoradas, etc.).</p>
</li>
<li><p>Quais erros estão acontecendo e com que frequência.</p>
</li>
<li><p>Como os serviços estão interagindo em uma arquitetura distribuída (ex: microserviços).</p>
</li>
</ul>
<p>Ele possui integração com as principais ferramentas do mercado e inclusive com a Open telemetry.</p>
<p>Agora vamos adicionar nossa aplicação ao elastic, veja o passo a passo abaixo:</p>
<p><strong>1 -</strong> No painel do Elastic no canto superior direito clique em <strong>Add data:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745330599159/92a98e17-8cfb-4378-95e7-a4f84b598d4f.png" alt class="image--center mx-auto" /></p>
<p><strong>2 -</strong> Depois selecione <strong>Application</strong> e <strong>Open Telemetry:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745330530839/2207296e-dfe5-46c5-8dc9-e8216b2116f7.png" alt class="image--center mx-auto" /></p>
<p><strong>3 -</strong> E por último mais abaixo selecione <strong>Open Telemetry</strong> novamente:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745330303079/9ab5ff45-f235-4c7c-ba79-4e492bb86c4a.png" alt class="image--center mx-auto" /></p>
<p>A variável <strong>OTEL_EXPORTER_OTLP_ENDPOINT</strong> contém o endpoint para coleta dos dados da sua aplicação e vamos usá-la mais tarde.</p>
<h1 id="heading-conceitos-chave-do-opentelemetry">Conceitos-Chave do OpenTelemetry</h1>
<p><mark>Os exemplos abaixo estão na linguagem Dart.</mark></p>
<h3 id="heading-1-tracer">1. <strong>Tracer</strong></h3>
<ul>
<li><p>O objeto principal e um ponto de entrada para criar <strong><em>spans</em></strong>. Um <a target="_blank" href="https://medium.com/dzerolabs/observability-journey-understanding-logs-events-traces-and-spans-836524d63172"><strong>Trace</strong></a> é composto por uma árvore de Spans e oferece uma visão holística do seu sistema.</p>
</li>
<li><p>Você pega ele com algo tipo:</p>
</li>
</ul>
<pre><code class="lang-dart">    <span class="hljs-keyword">final</span> tracer = tracerProvider.getTracer(<span class="hljs-string">'meu-serviço'</span>);
</code></pre>
<p>Você pode também ter vários <strong>traces</strong> e um pra cada contexto e assim organizar melhor os dados no Elastic, filtrar por tipo de operação ou subsistema, ter granularidade no controle.</p>
<p>Veja o exemplo abaixo:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> apiTracer = tracerProvider.getTracer(<span class="hljs-string">'api-tracer'</span>);
<span class="hljs-keyword">final</span> uiTracer = tracerProvider.getTracer(<span class="hljs-string">'ui-tracer'</span>);
</code></pre>
<p>No seu app Flutter, <strong>na maioria dos casos, você pode usar apenas um</strong> <code>Tracer</code> global que já é o suficiente. Se no futuro seu app crescer muito e tiver múltiplos módulos/libraries com integração separada, aí pode fazer sentido separar <code>Tracers</code></p>
<p>Apesar de você <strong>poder ter vários tracers</strong>, o que realmente importa são os <strong>spans e atributos</strong> que você gera.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> span = tracer.startSpan(<span class="hljs-string">'api.chamada.login'</span>);
span.setAttribute(<span class="hljs-string">'feature'</span>, <span class="hljs-string">'login'</span>);
span.setAttribute(<span class="hljs-string">'http.url'</span>, <span class="hljs-string">'/auth/login'</span>);
</code></pre>
<h3 id="heading-2-span">2. <strong>Span</strong></h3>
<ul>
<li><p>Representa uma <strong>unidade de trabalho</strong> (ex: carregar dados, enviar mensagem, fazer login…). <strong>Spans</strong> contêm <strong>Eventos</strong> , logs estruturados (JSON) que descrevem ocorrências pontuais durante aquele período e podem ser usados para:</p>
<ul>
<li><p>Medir tempo de tela</p>
</li>
<li><p>Performance de chamadas de APIs</p>
</li>
<li><p>Acompanhamento de eventos e jornada do usuário</p>
</li>
</ul>
</li>
<li><p>Combine com <code>try/catch</code> pra capturar erros:</p>
<pre><code class="lang-dart">  <span class="hljs-keyword">final</span> span = tracer.startSpan(<span class="hljs-string">"fazer-login"</span>);
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> login();
  } <span class="hljs-keyword">catch</span> (e) {
    span.setStatus(StatusCode.error, description: e.toString());
  } <span class="hljs-keyword">finally</span> {
    span.end();
  }
</code></pre>
</li>
<li><p>Um Span pode ter:</p>
<ul>
<li><p><strong>Nome</strong> (<code>operation-flutter</code>) O nome do microsserviço que está sendo executado ou uma chamada de função.</p>
</li>
<li><p><strong>Tempo de início/fim</strong></p>
</li>
<li><p><strong>Atributos</strong> (ex: status, erro, nome do usuário) Lista de pares de chave-valor usados ​​para agregação ou filtragem de dados de rastreamento (por exemplo, identificador do cliente, nome do host do processo). Usados ​​para descrever e contextualizar o trabalho realizado em um Span.</p>
</li>
<li><p><strong>Hierarquia</strong> (spans filhos)</p>
</li>
<li><p><strong>Eventos</strong> : Strings com registro de data e hora compostas por registro de data e hora, nome e atributos opcionais usadas para descrever e contextualizar o trabalho realizado em um período.</p>
</li>
</ul>
</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> span = tracer.startSpan(<span class="hljs-string">"carregar-dados"</span>);
<span class="hljs-comment">// faz algo</span>
span.end();
</code></pre>
<p>Para enriquecer com atributos use o <code>span.setAttribute(...)</code> para dar contexto:</p>
<pre><code class="lang-dart">  <span class="hljs-keyword">void</span> _spanWithAttribute() {
    <span class="hljs-keyword">final</span> span = tracer.startSpan(
      <span class="hljs-string">'GET /resource/catalog'</span>,
      kind: SpanKind.client,
    );
    span.setAttribute(Attribute.fromString(<span class="hljs-string">'http.method'</span>, <span class="hljs-string">'GET'</span>));
    span.setAttribute(Attribute.fromString(<span class="hljs-string">'http.url'</span>, <span class="hljs-string">'your http url'</span>));
    <span class="hljs-comment">//faça algo</span>
    span.end();
  }
</code></pre>
<h3 id="heading-3-traces">3. <strong>Traces</strong></h3>
<ul>
<li><p>É como o OpenTelemetry conecta vários spans (inclusive em diferentes serviços).</p>
</li>
<li><p>Permite criar um <em>span filho</em> ligado ao <em>span pai</em>:</p>
</li>
</ul>
<pre><code class="lang-dart">Context.current.withSpan(parentSpan).execute(() {
  <span class="hljs-keyword">final</span> child = tracer.startSpan(<span class="hljs-string">"operação-filho"</span>);
  child.end();
});
</code></pre>
<h3 id="heading-4-tracerprovider">4. <strong>TracerProvider</strong></h3>
<ul>
<li><p>Gerencia os tracers e controla como eles se comportam. Nele você configurar:</p>
<ul>
<li><p>Processadores de span (ex: batch ou simples)</p>
</li>
<li><p>Exportadores (pra onde os dados vão: console, Elastic, etc)</p>
</li>
<li><p>Metadata sobre o app (nome do serviço, versão…)</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-5-exporter">5. <strong>Exporter</strong></h3>
<ul>
<li><p>Responsável por <strong>enviar os dados dos spans</strong> pro backend (Elastic, Zipkin, Jaeger, etc).</p>
</li>
<li><p>Ex: <code>CollectorExporter</code>, <code>ConsoleExporter</code>, ou <code>SlsExporter</code>.</p>
</li>
</ul>
<h3 id="heading-6-span-processor">6. <strong>Span Processor</strong></h3>
<p>Eles são responsáveis por <strong>processar e exportar os spans</strong> assim que eles são criados (ou finalizados).</p>
<ul>
<li><p><code>SimpleSpanProcessor</code>: exporta logo após o <code>.end()</code> imediatamente</p>
</li>
<li><p><code>BatchSpanProcessor</code>: agrupa vários e exporta em lote (mais eficiente e indicado para produção)</p>
</li>
<li><p>Recomendado: sempre usar <code>BatchSpanProcessor</code> no app real.</p>
</li>
<li><p>Exibir no console (<code>SimpleSpanProcessor</code> com <code>ConsoleExporter</code>)</p>
</li>
</ul>
<p>Você <strong>pode registrar vários ao mesmo tempo</strong>:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> tracerProvider = TracerProviderBase(
  processors: [
    BatchSpanProcessor(exporterElastic),
    SimpleSpanProcessor(ConsoleExporter()),
  ],
);
</code></pre>
<p>Neste caso:</p>
<ul>
<li><p>Um envia os dados pra sua ferramenta que vai receber os dados que nesse caso usamos o <a target="_blank" href="https://www.elastic.co/observability/application-performance-monitoring">Elastic APM</a></p>
</li>
<li><p>Outro imprime os spans no console para debug localmente</p>
</li>
</ul>
<h3 id="heading-7-resource">7. <strong>Resource</strong></h3>
<ul>
<li><p>Metadados sobre o app: nome, versão, ambiente (dev/prod), etc.</p>
</li>
<li><p>Isso ajuda a identificar o app no painel de observabilidade.</p>
</li>
</ul>
<pre><code class="lang-dart">Resource([
  Attribute.fromString(<span class="hljs-string">"service.name"</span>, <span class="hljs-string">"meu_app"</span>),
  Attribute.fromString(<span class="hljs-string">"deployment.environment"</span>, <span class="hljs-string">"dev"</span>),
])
</code></pre>
<h3 id="heading-8-metrics-e-logs-futuramente-no-flutter">8. <strong>Metrics e Logs (Futuramente no Flutter)</strong></h3>
<ul>
<li><p>OpenTelemetry também suporta <strong>métricas</strong> e <strong>logs estruturados</strong>, mas a maior parte do suporte em Flutter ainda é centrada em <em>traces</em> (spans).</p>
</li>
<li><p>A comunidade tá evoluindo isso aos poucos em relação ao package que usamos.</p>
</li>
</ul>
<h1 id="heading-utilizando-o-package-do-open-telemetry-no-flutter">Utilizando o package do open telemetry no Flutter</h1>
<p><strong>1— Adicionando a dependência em seu projeto</strong></p>
<p>Vamos começar adicionando a dependência ao nosso arquivo <strong><em>pubspec.yaml.</em></strong></p>
<p>Instale o pacote a partir da linha de comando com o Flutter:</p>
<pre><code> $ flutter pub add opentelemetry
</code></pre><p>Ou adicione <code>opentelemetry</code> diretamente em seu <code>pubspec.yaml</code> e execute <code>flutter pub get</code> no momento da criação desse post ele está na versão <strong>0.18.10 .</strong></p>
<pre><code class="lang-dart">dependencies:
 opentelemetry: ^<span class="hljs-number">0.18</span><span class="hljs-number">.10</span>
</code></pre>
<p>Agora, no seu código Dart, você pode importar o package:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/api.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/sdk.dart'</span>;
</code></pre>
<p><strong>2 -</strong> Para inicializar o SDK vamos criar um arquivo chamado <strong><em>telemetry_initializer.dart</em></strong> <em>veja como ficou abaixo:</em></p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/api.dart'</span> <span class="hljs-keyword">as</span> otel_api;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/sdk.dart'</span> <span class="hljs-keyword">as</span> otel_sdk;

<span class="hljs-keyword">late</span> otel_api.Tracer tracer;

Future&lt;<span class="hljs-keyword">void</span>&gt; initTelemetry() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> exporter = otel_sdk.CollectorExporter(
    <span class="hljs-built_in">Uri</span>.parse(
      <span class="hljs-string">'https://&lt;seu-endpoint&gt;/v1/traces'</span>, <span class="hljs-comment">// 👈 não esqueça de incluir o /v1/traces!</span>
    ),
    headers: {
      <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer &lt;sua-api-key&gt;'</span>,
      <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
    },
  );

  <span class="hljs-keyword">final</span> simpleProcessor = otel_sdk.SimpleSpanProcessor(exporter);
  <span class="hljs-keyword">final</span> batchProcessor = otel_sdk.BatchSpanProcessor(exporter);

  <span class="hljs-keyword">final</span> tracerProvider = otel_sdk.TracerProviderBase(
    processors: [batchProcessor, simpleProcessor],
    resource: otel_sdk.Resource([
      otel_api.Attribute.fromString(<span class="hljs-string">'service.name'</span>, <span class="hljs-string">'main'</span>),
      otel_api.Attribute.fromString(<span class="hljs-string">'service.version'</span>, <span class="hljs-string">'1.0.0'</span>),
      otel_api.Attribute.fromString(<span class="hljs-string">'deployment.environment'</span>, <span class="hljs-string">'dev'</span>),
    ]),
  );

  otel_api.setTracerProvider(tracerProvider);

  tracer = tracerProvider.getTracer(<span class="hljs-string">'flutter-app'</span>);
}
</code></pre>
<p>Acima, importamos o TraceProviderBase, que é o ponto inicial do open telemetry, ele fornece acesso ao Tracer, a classe responsável pela criação de spans.</p>
<p>Além disso, especificamos o uso do BatchSpanProcessor ele agrupa spans e os envia em massa.</p>
<h2 id="heading-isolando-a-regra-da-coleta-de-erros-com-o-padrao-service-errorreporterservicedart"><strong>Isolando a regra da coleta de erros com o padrão Service (</strong>error_reporter_service.dart)</h2>
<p>A finalidade da camada de serviço, por outro lado, é encapsular a lógica de negócios em um único local para promover a reutilização de código e a separação de interesses.</p>
<p>Basicamente seria isolar uma tarefa específica em um outro objeto sendo assim assumindo uma responsabilidade muito estreita de realizar alguma atividade útil.</p>
<p>Então, vamos criar um serviço para integrar apenas a coleta de erros ao seu projeto Flutter e gerenciar os relatórios de erros. 👇🏻</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'dart:isolate'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/foundation.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/api.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:opentelemetry/sdk.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ErrorReporterService</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> initialize() {
    FlutterError.onError = (FlutterErrorDetails details) {
      _report(
        details.exception,
        details.stack ?? StackTrace.empty,
        <span class="hljs-string">'FLUTTER_ERROR'</span>,
      );
    };

    Isolate.current.addErrorListener(_isolateErrorListener);
  }

  <span class="hljs-keyword">static</span> Future&lt;<span class="hljs-keyword">void</span>&gt; _report(
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace stack,
    <span class="hljs-built_in">String</span> tag,
  ) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">final</span> tracer = globalTracerProvider.getTracer(<span class="hljs-string">'flutter-my-app'</span>);
    <span class="hljs-keyword">final</span> span = tracer.startSpan(<span class="hljs-string">'error: <span class="hljs-subst">$tag</span>'</span>);

    span.setStatus(StatusCode.error, exception.toString());
    span
      ..addEvent(<span class="hljs-string">'date'</span>, timestamp: DateTimeTimeProvider().now)
      ..setStatus(StatusCode.error, exception.toString())
      ..recordException(
        exception,
        stackTrace: stack,
        attributes: [
          Attribute.fromString(
            <span class="hljs-string">'exception.type'</span>,
            exception.runtimeType.toString(),
          ),
          Attribute.fromString(<span class="hljs-string">'exception.message'</span>, exception.toString()),
          Attribute.fromString(<span class="hljs-string">'exception.stacktrace'</span>, stack.toString()),
          Attribute.fromString(<span class="hljs-string">'error.tag'</span>, tag),
        ],
      );

    span.end();

    debugPrint(<span class="hljs-string">'Erro capturado: <span class="hljs-subst">$exception</span>'</span>);
    debugPrintStack(label: tag, stackTrace: stack);
  }

  <span class="hljs-keyword">static</span> SendPort <span class="hljs-keyword">get</span> _isolateErrorListener {
    <span class="hljs-keyword">return</span> RawReceivePort((pair) <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">List</span> errorAndStacktrace = pair;
      <span class="hljs-keyword">final</span> exception = errorAndStacktrace[<span class="hljs-number">0</span>];
      <span class="hljs-keyword">final</span> stackTrace = errorAndStacktrace[<span class="hljs-number">1</span>] <span class="hljs-keyword">as</span> StackTrace;
      <span class="hljs-keyword">await</span> _report(exception, stackTrace, <span class="hljs-string">'ISOLATE'</span>);
    }).sendPort;
  }

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> reportExternalFailure(
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace? stack,
    <span class="hljs-built_in">String?</span> label,
  ) {
    <span class="hljs-keyword">if</span> (stack != <span class="hljs-keyword">null</span> &amp;&amp; label != <span class="hljs-keyword">null</span>) {
      _report(exception, stack, <span class="hljs-string">'EXTERNAL_FAILURE: <span class="hljs-subst">$label</span>'</span>);
    }
  }
}
</code></pre>
<ul>
<li><code>Isolate.current.addErrorListener(_isolateErrorListener)</code>: adiciona um ouvinte de erros para isolados (ou seja, quando múltiplos threads estão rodando em paralelo no app), garantindo que erros ocorridos fora do thread principal sejam capturados e reportados.</li>
</ul>
<h2 id="heading-exemplo-de-uso-do-errorreportservice"><strong>Exemplo de uso do</strong> ErrorReportService</h2>
<p>Essa abordagem centraliza a manipulação de exceções e falhas no aplicativo, garante que erros sejam capturados e enviados para monitoramento via Elastic APM, e oferece flexibilidade para criar diferentes tipos de erros com pouca repetição de código.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/foundation.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../service/crashlytics_service.dart'</span>;

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Failure</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Exception</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> errorMessage;

  Failure({
    StackTrace? stackTrace,
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    <span class="hljs-keyword">this</span>.errorMessage = <span class="hljs-string">''</span>,
  }) {
    <span class="hljs-comment">// Loga a stack trace apenas no modo debug para evitar poluição de logs em produção.</span>
    <span class="hljs-keyword">if</span> (stackTrace != <span class="hljs-keyword">null</span> &amp;&amp; kDebugMode) {
      debugPrintStack(label: label, stackTrace: stackTrace);
    }

    <span class="hljs-comment">// Reporta o erro ao service se houver exception</span>
    ErrorReport.externalFailureError(exception, stackTrace, label);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UnknownError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Failure</span> </span>{
  UnknownError({
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace? stackTrace,
  }) : <span class="hljs-keyword">super</span>(
          stackTrace: stackTrace,
          label: label,
          exception: exception,
          errorMessage:
              <span class="hljs-string">'Unknown Error'</span>, <span class="hljs-comment">// Passa a mensagem diretamente para a classe base</span>
        );
}
</code></pre>
<h2 id="heading-possiveis-extensoes"><strong>Possíveis extensões</strong></h2>
<p>Se no futuro você quiser criar outras subclasses de <code>Failure</code> para diferentes tipos de erros, será muito fácil. Por exemplo, você pode criar uma classe <code>NetworkError</code> para representar erros relacionados à rede, e utilizar o mesmo padrão de construção.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NetworkError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Failure</span> </span>{
  NetworkError({
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace? stackTrace,
  }) : <span class="hljs-keyword">super</span>(
          stackTrace: stackTrace,
          label: label,
          exception: exception,
          errorMessage: <span class="hljs-string">'Network Error'</span>,
        );
}
</code></pre>
<h3 id="heading-visualizando-os-dados-no-elastic-apm">Visualizando os dados no Elastic APM:</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745333354965/59e43069-0266-4652-a17f-4624c3331dfb.png" alt class="image--center mx-auto" /></p>
<p>Abaixo na aba <strong>Traces</strong> veremos todos os erros coletados do nosso aplicativo, se você clicar nele verá vários dados e insights sobre ocorrido:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745333555242/1ef03ead-9567-49f3-a527-8e3a7028b780.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusao"><strong>Conclusão</strong></h1>
<p>Bom é isso 😎.</p>
<p>Neste artigo, você aprendeu como configurar e preparar nossos aplicativos Flutter para serem usados ​​com o padrão da Open Telemetry o que é incrível pois é uma ferramenta robusta para coletar e analisar dados.</p>
<p>Aqui está o código do <a target="_blank" href="https://github.com/iang12/flutter_open_telemetry_example">projeto</a> de exemplo no github. 🔗</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> <strong>(X)</strong> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[O melhor momento para iniciar na programação é hoje! (PARE DE PROCRASTINAR)]]></title><description><![CDATA[Se você já pensou em aprender a desenvolver software, mas sempre adiou por falta de tempo, recursos ou simplesmente por achar difícil, este artigo é para você. Nunca houve um momento melhor para iniciar a programação do que agora em 2025. O acesso ao...]]></description><link>https://ianoliveira.dev/o-melhor-momento-para-iniciar-na-programacao-e-hoje-pare-de-procrastinar</link><guid isPermaLink="true">https://ianoliveira.dev/o-melhor-momento-para-iniciar-na-programacao-e-hoje-pare-de-procrastinar</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[programação]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Wed, 26 Mar 2025 13:20:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742994908994/d53c2ba2-c7fd-4f29-b9ba-44b03b3ea5a5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Se você já pensou em aprender a desenvolver software, mas sempre adiou por falta de tempo, recursos ou simplesmente por achar difícil, este artigo é para você. Nunca houve um momento melhor para iniciar a programação do que agora em 2025. O acesso ao conhecimento está mais fácil, as ferramentas estão mais intuitivas e a comunidade está mais receptiva do que nunca.</p>
<h2 id="heading-se-nao-for-agora-quando-vai-ser"><strong>Se não for agora, quando vai ser?</strong></h2>
<p>Muita gente sonha em aprender a programar, mas sempre encontra uma desculpa para adiar: "<strong>não tenho tempo</strong>", "<strong>é difícil</strong>", "<strong>começo na próxima semana</strong>"... Mas a verdade é que o melhor momento para começar é HOJE!</p>
<h2 id="heading-a-era-da-informacao-ao-seu-favor"><strong>A Era da Informação ao Seu Favor</strong></h2>
<p>Antigamente, aprender a programar exigia acesso a cursos caros, livros técnicos ou até mesmo uma faculdade. Hoje, basta um computador ou até mesmo um smartphone e conexão com a internet para começar.</p>
<p><mark>Claro, e muita disposição de sentar na cadeira e aprender, chega de procrastinar. 😉</mark></p>
<p>Há milhares de cursos gratuitos e pagos, desde plataformas como Codecademy, Udemy e Coursera até tutoriais no YouTube e documentações oficiais de linguagens populares como Python, Dart e JavaScript.</p>
<h2 id="heading-comece-com-pequenos-passos-mas-de-o-primeiro-passo"><strong>Comece com Pequenos Passos mas dê o Primeiro Passo</strong></h2>
<p>O segredo para aprender <strong>programação</strong> é começar com pequenos projetos e ir evoluindo. Aqui estão algumas sugestões:</p>
<ol>
<li><p><strong>Aprenda Lógica de Programação</strong> – Use Ferramentas como Scratch ou Portugol com VisualG para entender os fundamentos.</p>
</li>
<li><p><strong>Escolha uma Linguagem</strong> – Python ou Dart é uma excelente opção para iniciantes pela sua sintaxe simples.</p>
</li>
<li><p><strong>Construa Pequenos Projetos</strong> – Criar uma calculadora, um jogo simples ou um bot para Telegram pode ser um ótimo início.</p>
</li>
<li><p><strong>Divulgue o que você constrói</strong> – Sites, Apps tudo o que fazer mostre para o mundo e isso vai te motivando na jornada. Vai por mim é incrível.</p>
</li>
</ol>
<h2 id="heading-o-melhor-momento-e-agora"><strong>O Melhor Momento é Agora</strong></h2>
<p>Você pode começar hoje mesmo, e com dedicação, em alguns meses já terá desenvolvido projetos interessantes e legais. Não espere pelo “<strong>momento ideal</strong>”, pois ele já chegou. Aproveite as ferramentas disponíveis e dê o primeiro passo para uma nova habilidade que pode transformar sua vida profissional e pessoal!</p>
<p>Se você quiser se tornar um desenvolvedor mobile, veja este meu <a target="_blank" href="https://ianoliveira.hashnode.dev/como-se-tornar-um-desenvolvedor-mobile-flutter">artigo</a> com dicas de conteúdos.</p>
<h1 id="heading-conclusao"><strong>Conclusão ✅</strong></h1>
<p>Uma das melhores partes de aprender a desenvolver software é a capacidade de criar coisas do zero. Desde pequenos scripts que automatizam tarefas até aplicativos completos, a programação permite transformar ideias em realidade.</p>
<p>Imagine desenvolver seu próprio site, criar um jogo ou até mesmo construir uma inteligência artificial que ajuda no dia a dia. O poder da tecnologia está nas suas mãos, e quanto mais você pratica, mais possibilidades se abrem!</p>
<p>Obrigado por ler até aqui. 😁</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre desenvolvimento móvel 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Como testar widgets de imagem com testes de widget no Flutter?]]></title><description><![CDATA[Quando desenvolvemos aplicativos no Flutter, garantir que os widgets funcionem corretamente é essencial para uma boa experiência do usuário. Para isso, os testes de widget desempenham um papel fundamental. Neste post, vamos explorar um pouco como tes...]]></description><link>https://ianoliveira.dev/como-testar-widgets-de-imagem-com-testes-de-widget-no-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/como-testar-widgets-de-imagem-com-testes-de-widget-no-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[testers]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Sat, 08 Feb 2025 21:53:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/-JT6cHbiDiA/upload/778ee9fbe072d4ada30ec399a02b958f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Quando desenvolvemos aplicativos no Flutter, garantir que os widgets funcionem corretamente é essencial para uma boa experiência do usuário. Para isso, os testes de widget desempenham um papel fundamental. Neste post, vamos explorar um pouco como testar widgets no Flutter e especialmente o de renderizar imagens, pois foi com ele que tive maior dificuldade.</p>
<h3 id="heading-o-que-e-um-teste-de-widget">O que é um Teste de Widget?</h3>
<p>Os testes de widget no Flutter verificam a interface do usuário de forma isolada, garantindo que os componentes se comportem corretamente sem a necessidade de rodar o app inteiro. Eles ficam no meio termo entre os <strong>testes unitários</strong> (que verificam partes isoladas do código) e os <strong>testes de integração</strong> (que testam o aplicativo como um todo).</p>
<h1 id="heading-problema-ao-testar-widgets-de-imagem-como-o-imagenetwork"><strong>Problema ao testar widgets de imagem como o Image.network.</strong></h1>
<p>Recentemente, estava desenvolvendo um novo aplicativo e queria atingir uma cobertura de testes bem alta, próxima de 90%. Então, decidi testar as páginas e os widgets do meu aplicativo, mas tive um problema com widgets de imagem, especialmente com o <a target="_blank" href="http://Image.network"><code>Image.network</code></a><code>()</code>.</p>
<p>Um dos meus cards renderizava imagens vindas da minha API e, nos testes, tive o seguinte erro, como mostrado na imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739050088091/fb09cebe-ff3e-4ca2-955f-1ae123c87b88.png" alt class="image--center mx-auto" /></p>
<p>Se vc quiser simular esse mesmo problema de forma simplificada, execute esse teste na sua maquina: 👇🏻</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter_test/flutter_test.dart'</span>;
<span class="hljs-keyword">void</span> main() {
  testWidgets(<span class="hljs-string">'my image test'</span>, (WidgetTester tester) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> tester.pumpWidget(
      MaterialApp(
        home: Image.network(
            <span class="hljs-string">'https://www.cdc.gov/healthy-pets/media/images/2024/04/Cat-on-couch.jpg'</span>),
      ),
    );
  });
}
</code></pre>
<p>Se você executou o teste acima, ele vai dar o seguinte erro: 👇🏻</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739049381331/12430abd-7e30-4812-ba4f-3c80e16c604e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-por-que-isso-acontece"><strong>Por que isso acontece? 😕</strong></h2>
<p>Isso ocorre porque, por padrão, o ambiente de teste do Flutter retorna respostas HTTP com status 400 para todas as requisições de rede, incluindo aquelas feitas pelo <a target="_blank" href="http://Image.network"><code>Image.network</code></a><code>()</code>.</p>
<p>Fazer solicitações HTTP reais em testes é problemático. Primeiro, torna a execução de testes mais lenta. Também torna os testes imprevisíveis e instáveis.</p>
<h2 id="heading-como-resolver-isso">Como resolver isso? <strong>🤔</strong></h2>
<p>Para resolver esse problema, você pode utilizar pacotes que simulam as respostas das requisições de rede durante os testes. Aqui está a opção que usei, se chama <code>flutter_image_test_utils</code> ele fornece uma maneira simples de simular respostas de imagens de rede em testes de widget.</p>
<p>Isso garantirá que as chamadas ao <a target="_blank" href="http://Image.network"><code>Image.network</code></a><code>()</code> sejam simuladas durante os testes, evitando erros relacionados a requisições de rede.</p>
<ol>
<li><ul>
<li><p>Adicione o packagete ao seu <code>pubspec.yaml</code>:</p>
<pre><code class="lang-yaml">   <span class="hljs-attr">dev_dependencies:</span>
     <span class="hljs-attr">flutter_image_test_utils:</span> <span class="hljs-string">^1.0.0</span>
</code></pre>
<ul>
<li><p>No seu arquivo de teste, importe o pacote e utilize a função <code>provideMockedNetworkImages</code> e envolva seu codigo com ela, veja o exemplo abaixo:</p>
<pre><code class="lang-dart"> <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter_test/flutter_test.dart'</span>;
 <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter_image_test_utils/image_test/image_test.dart'</span>;

 <span class="hljs-keyword">void</span> main() {
   testWidgets(<span class="hljs-string">'my image test'</span>, (WidgetTester tester) <span class="hljs-keyword">async</span> {
     provideMockedNetworkImages(() <span class="hljs-keyword">async</span> {
       <span class="hljs-keyword">await</span> tester.pumpWidget(
         MaterialApp(
           home: Image.network(
               <span class="hljs-string">'https://www.cdc.gov/healthy-pets/media/images/2024/04/Cat-on-couch.jpg'</span>),
         ),
       );
     });
   });
 }
</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li>Isso permitirá que você teste widgets que carregam imagens da rede sem enfrentar erros de requisição. Executando o teste novamente podemos ver que ele passa com sucesso. 🟢 👇🏻</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739050622728/8f2caf9d-6b05-42c2-bc12-cec444d871c5.png" alt class="image--center mx-auto" /></p>
<p>Ao utilizar essa abordagem, todas as solicitações HTTP GET dentro do <code>provideMockedNetworkImages</code> receberão uma resposta de sucesso simulada, e seus testes não travarão mais com erros 404.</p>
<p>Agora você poderá testar seus widgets que dependem de imagens da internet sem enfrentar erros de requisição, garantindo uma cobertura de testes mais robusta para o seu aplicativo Flutter. 🧘🏻</p>
<h1 id="heading-conclusao">Conclusão</h1>
<p>Os testes de widget no Flutter são essenciais para garantir a qualidade do seu aplicativo. Com uma boa estratégia de testes, você pode detectar problemas rapidamente e oferecer uma experiência de usuário mais confiável. Experimente escrever seus próprios testes e veja como eles podem melhorar seu fluxo de desenvolvimento!</p>
<p>Obrigado por ler até aqui. 😁</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre desenvolvimento móvel 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Como configurar o Java Home e o Android Home no MacOS]]></title><description><![CDATA[Fala, devs! O ano novo chegou e estou de volta com os posts. 📚
Hoje vamos aprender a configurar o JAVA_HOME e o ANDROID_HOME no macOS, você precisará modificar o arquivo de configuração do seu shell.
Essas variáveis de ambiente essenciais no desenvo...]]></description><link>https://ianoliveira.dev/como-configurar-o-java-home-e-o-android-home-no-macos</link><guid isPermaLink="true">https://ianoliveira.dev/como-configurar-o-java-home-e-o-android-home-no-macos</guid><category><![CDATA[macOS]]></category><category><![CDATA[Android]]></category><category><![CDATA[Java]]></category><category><![CDATA[android development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Thu, 30 Jan 2025 13:18:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738242803330/784e3789-e447-43a1-a2e7-c73bbd111aa5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, devs! O ano novo chegou e estou de volta com os posts. 📚</p>
<p>Hoje vamos aprender a configurar o <strong>JAVA_HOME</strong> e o <strong>ANDROID_HOME</strong> no macOS, você precisará modificar o arquivo de configuração do seu <strong>shell</strong>.</p>
<p>Essas variáveis de ambiente essenciais no desenvolvimento de software, principalmente quando estamos lidando com Java e Android.</p>
<p>Elas servem para informar ao sistema operacional onde estão localizados os diretórios de instalação do Java e do Android SDK (Software Development Kit)</p>
<p>Vamos ver os passos para cada um.</p>
<h1 id="heading-configurando-o-javahome"><strong>Configurando o JAVA_HOME</strong></h1>
<p>O <strong>JAVA_HOME</strong> é uma variável de ambiente que aponta para o diretório onde o Java está instalado no seu sistema.</p>
<h2 id="heading-passo-a-passo"><strong>Passo a passo:</strong></h2>
<ol>
<li><strong>Encontre o caminho de instalação do seu Java:</strong></li>
</ol>
<p>No terminal, você pode usar o comando <strong>which java</strong> para encontrar onde o Java está instalado. Exemplo:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">which</span> java
</code></pre>
<p>Isso vai retornar algo como:</p>
<p><strong>/Users/ian.oliveira/Library/Java/JavaVirtualMachines/corretto-15.0.2/Contents/Home/bin/java.</strong></p>
<p>Porém, para obter o diretório exato do Java (que é o que você precisa), use o seguinte comando:</p>
<pre><code class="lang-bash">/usr/libexec/java_home
</code></pre>
<p>Esse comando irá fornecer o caminho completo para o JDK instalado, algo como no caso da minha máquina:</p>
<p><strong>/Users/ian.oliveira/Library/Java/JavaVirtualMachines/corretto-15.0.2/Contents/Home</strong></p>
<h2 id="heading-definindo-a-variavel-de-ambiente-javahome"><strong>Definindo a variável de ambiente JAVA_HOME</strong></h2>
<p>Agora que você tem o caminho, é hora de adicionar a variável no seu arquivo de configuração de <strong>shell</strong> (~/.zshrc, se você usa o <strong>Zsh</strong> ou ~/.bash_profile se você usa o <strong>Bash</strong>).</p>
<p>Se você usa o <strong>Zsh</strong> (o shell é o padrão a partir do macOS Catalina):</p>
<p>Abra o arquivo ~/.zshrc com o comando abaixo:</p>
<pre><code class="lang-bash">nano ~/.zshrc
</code></pre>
<p>Veja o resultado do comando na imagem abaixo:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*w3eAfTXY2mevjJNUQzhnJg.png" alt="Terminal macOs Sequoia" /></p>
<p>Se você usa o <strong>Bash</strong>: Abra o arquivo ~/.bash_profile:</p>
<pre><code class="lang-bash">nano ~/.bash_profile
</code></pre>
<p>No final do arquivo, adicione a seguinte linha, substituindo o caminho com o que você obteve no passo anterior: 👇🏻</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> JAVA_HOME=$(/usr/libexec/java_home)
<span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$JAVA_HOME</span>/bin:<span class="hljs-variable">$PATH</span>
</code></pre>
<p><strong>Recarregando o shell:</strong> Após salvar e fechar o arquivo, recarregue o shell o comando abaixo para aplicar as mudanças:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ~/.zshrc <span class="hljs-comment"># Para Zsh</span>

<span class="hljs-built_in">source</span> ~/.bash_profile <span class="hljs-comment"># Para Bash</span>
</code></pre>
<p>Para confirmar que a variável foi configurada corretamente, execute no terminal o comando abaixo:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-variable">$JAVA_HOME</span>
</code></pre>
<p>Ele deve retornar o caminho certinho do JDK no seu terminal. 🎉</p>
<h1 id="heading-configurando-o-androidhome"><strong>Configurando o ANDROID_HOME 🛠️</strong></h1>
<p>O <strong>ANDROID_HOME</strong> é uma variável de ambiente que aponta para o diretório onde o Android SDK está instalado.</p>
<h2 id="heading-passo-a-passo-1"><strong>Passo a passo:</strong></h2>
<ol>
<li><strong>Encontre o caminho do Android SDK:</strong> Normalmente, o Android SDK é instalado em ~/Library/Android/sdk, mas se você não tiver certeza, pode verificar se o Android Studio está configurado corretamente e onde ele instalou o SDK.</li>
</ol>
<p>No meu caso está em <strong>/Users/ian.oliveira/Library/Android/sdk</strong></p>
<p><strong>2. Definindo a variável de ambiente ANDROID_HOME:</strong> Abra novamente o arquivo de configuração do seu <strong>shell</strong> (~/.zshrc ou ~/.bash_profile).</p>
<p>No final do arquivo, adicione as seguintes linhas abaixo, substituindo o caminho de instalação do Android SDK, se necessário:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> ANDROID_HOME=~/Library/Android/sdk
<span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$ANDROID_HOME</span>/tools:<span class="hljs-variable">$ANDROID_HOME</span>/platform-tools:<span class="hljs-variable">$PATH</span>
</code></pre>
<p><strong>Recarregue o seu shell:</strong> Após salvar e fechar o arquivo, recarregue o shell para aplicar as mudanças:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ~/.zshrc <span class="hljs-comment"># Para Zsh</span>

<span class="hljs-built_in">source</span> ~/.bash_profile <span class="hljs-comment"># Para Bash</span>
</code></pre>
<p><strong>Verifique se deu certo:</strong> Para confirmar, execute:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-variable">$ANDROID_HOME</span>
</code></pre>
<p>Isso deve retornar o caminho certinho do Android SDK.</p>
<p>Agora suas variáveis de ambiente <strong>JAVA_HOME e ANDROID_HOME</strong> estarão configuradas no seu sistema. 🎉</p>
<h1 id="heading-conclusao"><strong>Conclusão</strong></h1>
<p>Bom é isso 😎.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[6 Livros que li e que você deveria ler em 2025 para ser um engenheiro de software melhor]]></title><description><![CDATA[Fala, devs! O fim de ano está chegando e nada melhor do que começar a planejar as metas de leitura para o próximo ano. 📚
Que tal aproveitar 2025 para investir no seu desenvolvimento como engenheiro de software?
Existem várias maneiras de consumir co...]]></description><link>https://ianoliveira.dev/6-livros-que-li-e-que-voce-deveria-ler-em-2025-para-ser-um-engenheiro-de-software-melhor</link><guid isPermaLink="true">https://ianoliveira.dev/6-livros-que-li-e-que-voce-deveria-ler-em-2025-para-ser-um-engenheiro-de-software-melhor</guid><category><![CDATA[resumo de livros]]></category><category><![CDATA[Desenvolvimento de Software]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Sat, 21 Dec 2024 16:22:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/iyKVGRu79G4/upload/21e2f6f1a05ada60e13d643eef9d25c5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, devs! O fim de ano está chegando e nada melhor do que começar a planejar as metas de leitura para o próximo ano. 📚</p>
<p>Que tal aproveitar 2025 para investir no seu desenvolvimento como engenheiro de software?</p>
<p>Existem várias maneiras de consumir conhecimento como desenvolvedor de software. Dentre elas, <strong>Lendo Documentação,</strong> <strong>Posts de Blog, Livros, Desenvolvendo Projetos Paralelos (Side Projects),</strong> <strong>Cursos/Workshops, Escrevendo e Ensinando.</strong></p>
<p>Eu particularmante acredito que a leitura é uma das ferramentas mais poderosas para o desenvolvimento profissional e pessoal.</p>
<p>Para engenheiros de software, ela oferece insights valiosos, não só sobre tecnologias, mas também sobre práticas, mentalidades e abordagens que podem melhorar a qualidade do código e otimizar os processos de desenvolvimento. Quando se trata de se tornar um profissional mais eficiente e competente, os livros são verdadeiros mestres que nos guiam, nos educam e nos inspiram.</p>
<p>Neste post, vou compartilhar com você 6 livros que li e que considero essenciais para a carreira em desenvolvimento de software. Se você quer aprimorar suas habilidades, aumentar sua produtividade e adotar as melhores práticas no seu dia a dia, esses livros são uma leitura obrigatória para 2025! ⚡️</p>
<h3 id="heading-1-o-programador-pragmatico-andrew-hunt-e-david-thomas">1. <strong>O Programador Pragmático</strong> – Andrew Hunt e David Thomas</h3>
<p>Este é um dos livros mais recomendados para programadores de todos os níveis, e não é à toa. <em>O</em> <a target="_blank" href="https://www.amazon.com.br/Programador-Pragm%C3%A1tico-Aprendiz-Mestre-ebook/dp/B019HM0H90"><strong><em>Programador Pragmático</em></strong></a> ensina que ser um bom programador não é apenas sobre escrever código que funciona, mas sobre como pensar de forma crítica e pragmática sobre os problemas que você está resolvendo.</p>
<p>O livro aborda princípios fundamentais, como design, refatoração, testes, depuração e como aprender constantemente. É um guia para ser um programador mais eficiente, flexível e criativo, sempre em busca de soluções práticas e elegantes.</p>
<p><mark>Eu curti bastante esse livro pois ele mostrou para mim como construir uma mentalidade mais pragmática e focada no valor real que o software pode oferecer. 🔥</mark></p>
<h3 id="heading-2-codificador-limpo-clean-code-robert-c-martin">2. <strong>Codificador Limpo (Clean Code)</strong> – Robert C. Martin</h3>
<p>Se você quer escrever código legível, bem estruturado e fácil de manter, <a target="_blank" href="https://www.amazon.com.br/Codificador-Limpo-Bob-Martin/dp/8576086476"><em>Codificador Limpo</em></a> é uma leitura essencial. Robert C. Martin, um dos maiores nomes na área de desenvolvimento de software, compartilha as melhores práticas para escrever código limpo, que é uma das habilidades mais importantes para engenheiros de software.</p>
<p>O livro aborda conceitos como a importância de nomes significativos para variáveis e funções, a estruturação adequada do código, e como evitar a complexidade desnecessária.</p>
<p><mark>O foco principal desse livro é lhe ensinar a conduta do programador como profissional, algo extremamente importante nos dias de hoje 😁.</mark></p>
<h3 id="heading-3-codigo-limpo-clean-code-robert-c-martin">3. <strong>Código Limpo (Clean Code)</strong> – Robert C. Martin</h3>
<p>Agora se tem um livro que eu não poderia deixar de mencionar é o livro <a target="_blank" href="https://www.amazon.com.br/C%C3%B3digo-limpo-Robert-C-Martin/dp/8576082675/"><em>Código Limpo</em></a>, ele é uma versão mais profunda e abrangente da filosofia do código limpo. o Uncle bob expande ainda mais as ideias do primeiro livro citado acima, trazendo mais exemplos, estudos de caso e explicações sobre como manter o código simples e organizado.</p>
<p><mark>Nesse livro eu aprendi os principais princípios e práticas para garantir que o código seja não apenas limpo, mas também ágil, eficiente e fácil de modificar ✍🏻.</mark></p>
<h3 id="heading-4-arquitetura-limpa-clean-architecture-robert-c-martin">4. <strong>Arquitetura Limpa (Clean Architecture)</strong> – Robert C. Martin</h3>
<p>Todo desenvolvedor de software precisa saber arquitetar bem um software, então o livro <a target="_blank" href="https://www.amazon.com.br/Arquitetura-Limpa-Artes%C3%A3o-Estrutura-Software/dp/8550804606"><em>Arquitetura Limpa</em></a> é fundamental.</p>
<p>Aqui, o autor vai além do código e mostra como criar uma arquitetura que seja robusta, escalável e fácil de entender.</p>
<p>O livro discute como organizar o código de forma a minimizar dependências e maximizar a flexibilidade. Para quem está lidando com sistemas complexos, este livro é uma verdadeira aula sobre como construir software com uma arquitetura sólida.</p>
<p><mark>O que eu achei mais legal desse livro é que ele enfatiza a separação de responsabilidades, o uso de princípios como </mark> <a target="_blank" href="https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/"><mark>SOLID</mark></a> <mark> e como garantir que o código esteja preparado para mudanças futuras 🛠️.</mark></p>
<h3 id="heading-5-engenharia-de-software-moderna-david-farley">5. <strong>Engenharia de Software Moderna</strong> – David Farley</h3>
<p>Este <a target="_blank" href="https://www.amazon.com.br/Modern-Software-Engineering-Really-Better/dp/0137314914">livro</a> é uma leitura obrigatória para quem quer entender as melhores práticas atualizadas de engenharia de software no contexto moderno. David Farley apresenta uma abordagem prática sobre como criar software de qualidade de forma ágil, confiável e eficiente.</p>
<p>Ele fala sobre automação de testes, integração contínua, desenvolvimento baseado em testes e outras práticas fundamentais para o sucesso em projetos de software.</p>
<p><mark>Aqui são oferecidos insights sobre o desenvolvimento ágil, práticas de entrega contínua e como construir sistemas robustos e escaláveis em um ambiente de software dinâmico. 🎯</mark></p>
<h3 id="heading-6-deep-work-retorne-a-foco-e-realize-um-trabalho-de-qualidade-em-um-mundo-distraido-cal-newport">6. <strong>Deep Work: Retorne à Foco e Realize um Trabalho de Qualidade em um Mundo Distraído</strong> – Cal Newport</h3>
<p>Agora pra finalizar vou mostrar o melhor livro que li nesse ano de 2024, embora não seja um livro específico sobre programação, <a target="_blank" href="https://www.amazon.com.br/Deep-Work-Focused-Success-Distracted/dp/1455586692"><em>Deep Work</em></a> é altamente relevante para qualquer profissional.</p>
<p>Nosso trabalho como engenheiro de software geralmente necessita de foco, concentração profunda e sem distrações para realizarmos tarefas complexas dentro do prazo.</p>
<p>No livro o autor explora como o foco profundo é a chave para alcançar resultados excepcionais no trabalho. Em um campo como o de software, onde tarefas complexas e detalhadas exigem atenção total, aprender a trabalhar profundamente sem distrações é fundamental.</p>
<p><mark>Com esse livro eu aprendi algumas estratégias para melhorar o foco, eliminar distrações e maximizar sua produtividade 🎧.</mark></p>
<p>Outro ponto interessante é que o autor, sendo cientista da computação, apresenta diversos exemplos de sucesso na engenharia de software, destacando pessoas que alcançaram grandes resultados graças ao foco profundo. 🧘🏻</p>
<h1 id="heading-conclusao">Conclusão</h1>
<p>Não subestime o poder de um bom livro; eles contêm uma vasta quantidade de conhecimentos de profissionais altamente experientes em suas áreas. Afinal, nada melhor do que aprender com a experiência dos outros.</p>
<p>Em 2025, se você se comprometer com a leitura desses títulos, com certeza verá grandes melhorias no seu desempenho como desenvolvedor. <strong>Boa leitura e bons códigos 🧑🏻‍💻.</strong></p>
<p>E para encerrar, mais uma dica valiosa, acredite em mim: aproveite esse fim de ano para planejar sua carreira e metas.</p>
<p>Obrigado por ler até aqui. <strong>Boas festas, bom natal e um feliz ano novo.</strong> 🥳🍾 🎉🌲</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir software incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre engenharia de software 📲 🚀</p>
<h2 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h2>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12"><strong>X (Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Utilizando o Firebase Analytics no Flutter]]></title><description><![CDATA[Introdução
O Firebase Analytics, é uma ferramenta gratuita do Firebase, que coleta dados de uso, engajamento do usuário e comportamento para o seu aplicativo.
Com ele você pode obter insights de como as pessoas usam o seu aplicativo.
Saber quais part...]]></description><link>https://ianoliveira.dev/utilizando-o-firebase-analytics-no-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/utilizando-o-firebase-analytics-no-flutter</guid><category><![CDATA[firebase analytics]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[analytics]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Thu, 31 Oct 2024 02:28:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730282362901/659a16f8-d0d6-4b4e-8541-54afe95f0e07.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introducao"><strong>Introdução</strong></h2>
<p>O Firebase Analytics, é uma ferramenta gratuita do Firebase, que coleta dados de uso, engajamento do usuário e comportamento para o seu aplicativo.</p>
<p>Com ele você pode obter insights de como as pessoas usam o seu aplicativo.</p>
<p>Saber quais partes ou funcionalidades são mais populares e por quanto tempo são utilizadas além de podermos registrar <strong>eventos</strong> e <strong>propriedades do usuário.</strong></p>
<p>Imagine um aplicativo de exercícios físicos, o analytics pode registrar o exercício favorito de um usuário ou registrar o gênero favorito de um usuário para um aplicativo de música.</p>
<p>Outro exemplo, seria rastrear quando alguém termina um nível de jogo, compra algo ou usa uma parte específica do seu aplicativo.</p>
<p>No geral com os dados do Analytics você pode tomar decisões mais acertadas sobre marketing de aplicativos e otimizações de desempenho.</p>
<p>Você também pode olhar esse <a target="_blank" href="https://www.youtube.com/watch?v=8iZpH7O6zXo"><strong>video</strong></a> do canal do Firebase onde eles explicam resumidamente como funciona a ferramenta.</p>
<p>Este artigo faz parte da série “<strong>Dominando o Firebase em Aplicativos Flutter</strong>”, uma sequência de posts que explora como utilizar todos os produtos do Firebase em conjunto com o Flutter. Confira as demais publicações da série no meu blog para aprofundar seus conhecimentos. 📚</p>
<h2 id="heading-beneficios-do-firebase-analytics"><strong>Benefícios do Firebase Analytics</strong></h2>
<p><img src="https://i0.wp.com/cdn-images-1.medium.com/max/960/1*xd8Zx14rQe6oIzo2uv-7uw.png?w=640&amp;ssl=1" alt="Dashboard of Firebase Analytics" /></p>
<ul>
<li><p><strong>Vários tipos de métricas:</strong> Ajuda a descrever comportamentos dos usuários – como informações geográficas, demográficas etc.</p>
<ul>
<li><p><strong>Informações demográficas</strong>  — quem são seus usuários.</p>
</li>
<li><p><strong>Retenção</strong>  — com que regularidade eles usam seu aplicativo.</p>
</li>
<li><p><strong>Engajamento</strong>  — quanto tempo eles gastam e em quê.</p>
</li>
<li><p><strong>Receita média</strong>  — mostra quanto eles gastaram, se seu aplicativo oferecer suporte a compras no aplicativo</p>
</li>
</ul>
</li>
<li><p><strong>Rastreamento de eventos:</strong> Você pode rastrear eventos que ocorrem dentro do seu aplicativo. Por exemplo um aplicativo de exercícios físicos pode registrar o exercício favorito de um usuário ou um aplicativo de música pode registrar o gênero favorito do usuário.</p>
</li>
<li><p><strong>Integração com o Firebase:</strong> O Analytics tem integração nativa com outras ferramentas do Firebase, como <a target="_blank" href="https://ianoliveira.dev/utilizando-o-firebase-crashlytics-no-flutter"><code>Crashlytics</code></a>, fornecendo dados mais abrangentes sobre a saúde e o comportamento de seus aplicativos.</p>
</li>
</ul>
<h2 id="heading-configurando-e-utilizando-em-seu-projeto"><strong>Configurando e utilizando em seu projeto 🛠️</strong></h2>
<h4 id="heading-1-habilitando-o-analytics">1 — Habilitando o Analytics</h4>
<p>Vá para o console do firebase e no painel esquerdo vá para <strong>Analytics</strong> no menu e clique no botão <strong>Ativar o Google analytics</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729594937779/b21e27dc-a89c-4b3b-8c42-8ce19b3ad66f.png" alt="Firebase console" class="image--center mx-auto" /></p>
<p>Em seguida ele vai abrir uma nova tela, apenas clique em <strong>Ativar</strong>, veja a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729595013488/b47a988d-d168-42e9-9352-dba589fb618c.png" alt class="image--center mx-auto" /></p>
<p>Em seguida uma nova tela será aberta pedindo pra configurar o Firebase no seu aplicativo caso ainda não tenha feito, se sim apenas prossiga clicando em <strong>concluir</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729595156223/1202b951-bd1a-4c0b-a6d6-2ddc0850c8bb.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-2-adicionando-a-dependencia-em-seu-projeto">2 — Adicionando a dependência em seu projeto</h4>
<p>Vamos começar adicionando a dependência ao nosso arquivo <strong><em>pubspec.yaml.</em></strong></p>
<p>Instale o pacote a partir da linha de comando com o Flutter:</p>
<pre><code class="lang-dart">$ flutter pub add firebase_analytics
</code></pre>
<p>Ou adicione <code>firebase_crashlytics</code> diretamente em seu <code>pubspec.yaml</code> e execute <code>flutter pub get</code> no momento da criação desse post ele está na versão 4.1.1 .</p>
<pre><code class="lang-dart">dependencies:
 firebase_analytics: ^<span class="hljs-number">11.3</span><span class="hljs-number">.3</span>
</code></pre>
<p>Agora, no seu código Dart, você pode importar o package:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_crashlytics/firebase_analytics.dart'</span>;
</code></pre>
<h2 id="heading-painel-do-analytics"><strong>Painel do A</strong>nalytics</h2>
<p><img src="https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfeUJAc4dINAxF7P_ptBo0t4heyz1URO0sPXLXF-yw6gvMRbIwhILrVMWp9v0wTYzWVQdaHeybyaeDaCKs82BIZj4XnZQzES-su6HFZivgBRZEiYw2no-Zk8TX2Xdo8jAoIagPneuPxee2wP5htCkmCpjkz-qzK=s2048?key=ThsfBoyOiqqdXRm6x2G5Dg" alt /></p>
<p><img src="https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfPm6WQxvrDkr0K9Q5c_E7xfaVmfk6M7kII93yGF00eNBFFgxaGGCGwoawDR_aPH-3q6y5qFo_JfZsTQnLGsnlbrWnB4-9zR9NyYyIA1L7bWI7k3pjS4NflYG8x5icNDKfP2mCVmYDFhk_MvHS-ef3Q9wYx9Po=s2048?key=ThsfBoyOiqqdXRm6x2G5Dg" alt /></p>
<p>Analytics do Firebase fornece um dashboard que mostra um gráfico somativo de métricas-chave para seu aplicativo. Aqui você pode obter as informações básicas e dados de seus usuários, como usuários ativos, usuários ativos nos últimos 30 minutos, principais eventos de conversão, receita total, adoção de versão do aplicativo, etc.</p>
<p>Bom não é mesmo? 😎</p>
<h2 id="heading-eventos-e-conversoes"><strong>Eventos e Conversões</strong></h2>
<p><strong>Eventos</strong>: No centro do Firebase Analytics, os eventos são o que acontece no seu aplicativo, como ações do usuário ou eventos do sistema ou erros.</p>
<p><strong>Conversões:</strong> São ações importantes que os usuários do site ou app realizam e que os transformam em clientes, geram leads ou assinantes. São exemplos de conversões: compras, inscrições, entre outras.</p>
<p>Veremos um pouco mais sobre isso aditante.</p>
<p>O Analytics registra automaticamente alguns <a target="_blank" href="https://support.google.com/analytics/answer/9234069?hl=pt-br">eventos</a> para você. Não é necessário adicionar códigos para recebê-los. Caso o aplicativo precise coletar outros dados, é possível registrar até 500 <em>tipos</em> diferentes de eventos do Analytics no app, veja abaixo alguns exemplos:</p>
<p><a target="_blank" href="https://support.google.com/analytics/answer/9234069?hl=pt-BR"><img src="https://i0.wp.com/cdn-images-1.medium.com/max/640/1*DYMRiTt0tIwPQiGJMcIRCA.png?w=640&amp;ssl=1" alt="Eventos automáticos são registrados no firebase automaticamente" /></a></p>
<p><strong>first_open</strong>: Na primeira vez que um usuário inicia um app após a instalação ou reinstalação. Este evento não é acionado quando um usuário faz o download do app em um dispositivo, mas quando ele o utiliza pela primeira vez..</p>
<p><strong>in_app_purchase</strong>  : se seu aplicativo oferece compras no aplicativo, automaticamente um evento de compra no aplicativo será registrado para você, contendo o valor da compra e o produto que foi adquirido.</p>
<p><strong>session_start</strong>: Quando um usuário interage com o app ou site.</p>
<h3 id="heading-eventos-sugeridos"><strong>Eventos sugeridos</strong></h3>
<p>O próprio google nos recomenda alguns eventos essenciais aos clientes em todos os verticais de negócio. O SDK define uma série de eventos sugeridos que são comuns entre diferentes tipos de aplicativos, incluindo aplicativos de varejo e comércio eletrônico, viagens e jogos.</p>
<p>Para saber mais <a target="_blank" href="https://support.google.com/analytics/answer/9322688">sobre esses eventos</a> <a target="_blank" href="https://support.google.com/analytics/answer/9322688">e quando usá-los,</a> navegue pelos artigos e clique nesse <a target="_blank" href="https://support.google.com/analytics/answer/9267735?hl=pt">link</a> e veja a lista completa dos eventos.</p>
<p><a target="_blank" href="https://firebasetutorials.com/events-in-firebase-analytics/"><img src="https://firebasetutorials.com/wp-content/uploads/2020/04/2-suggested_events.jpg" alt=" Eventos sugeridos (eventos pré-definidos)" /></a></p>
<p>Nos eventos sugeridos, você pode usar:</p>
<ul>
<li><p><strong>Jogos</strong></p>
</li>
<li><p><strong>Varejo/comércio eletrônico</strong></p>
</li>
<li><p><strong>Empregos</strong></p>
</li>
<li><p><strong>Educação</strong></p>
</li>
<li><p><strong>Viagem</strong></p>
</li>
<li><p><strong>Ofertas locais</strong></p>
</li>
<li><p><strong>Imobiliária</strong></p>
</li>
</ul>
<p>Por exemplo, se você quiser ver quando um usuário adicionar um produto no carrinho de compras, você pode usar o evento <a target="_blank" href="https://developers.google.com/analytics/devguides/collection/ga4/reference/events?dark=0&amp;sjid=912055845948613132-SA&amp;hl=pt-br&amp;client_type=gtag#add_to_cart"><strong><em>add_to_cart</em></strong></a> que se enquadra na categoria de eventos <strong>varejo/comércio eletrônico</strong> ou usar o evento <a target="_blank" href="https://developers.google.com/analytics/devguides/collection/ga4/reference/events#view_item">view_item</a> que indica que parte do conteúdo foi exibido ao usuário.</p>
<h3 id="heading-eventos-personalizados">Eventos personalizados</h3>
<p>Se seu aplicativo tiver necessidades específicas não cobertas por um tipo de evento sugerido, você pode registrar seus próprios eventos personalizados</p>
<p><mark>Certifique-se de apenas criar eventos personalizados quando nenhum outro evento funciona para o seu exemplo de utilização. Os eventos personalizados não são apresentados na maioria dos relatórios padrão e, por isso, tem de configurar explorações ou relatórios personalizados para obter uma análise significativa.</mark></p>
<h3 id="heading-enviando-eventos-para-analytics"><strong>Enviando eventos para Analytics ⚡️</strong></h3>
<p>Para implementar eventos de conversão com Firebase Analytics no seu app Flutter, a estratégia é identificar os principais pontos de interação do usuário com seu app. Esses eventos de conversão geralmente estão ligados a ações que têm impacto nos objetivos do app, como engajamento, retenção ou receita.</p>
<p>Sugiro que passe um tempo mapeando quais partes do seu aplicativo seriam importantes para estarem no analytics ✍🏻.</p>
<p>Para enviar dados de eventos ao <strong>Analytics</strong>, no seu <strong><em>main.dart</em></strong> adicione o seguinte trecho de código:</p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
    WidgetsFlutterBinding.ensureInitialized();
    <span class="hljs-keyword">await</span> Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
    FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(<span class="hljs-keyword">true</span>);
    runApp(MyApp());
}
</code></pre>
<p>Antes de usar o Firebase Analytics, você precisa inicializar o Firebase.</p>
<p>Agora execute seu aplicativo e vá para o <strong>Dashboard do Analytics</strong> no console do firebase. A princípio, não haverá dados do usuário, pois o aplicativo é criado pela primeira vez, então levará tempo, e também não há eventos integrados no flutter, mas podemos ver um dado que é atualizado rapidamente que é os usuarios ativos no momento.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729682264538/1f1685ac-aef0-4f54-9eec-994ec0dc0840.png" alt="Usuários ativos nos últimos 30 minutos" class="image--center mx-auto" /></p>
<p>Você pode ver a atividade dos usuários nos últimos 30 minutos após buildar seu aplicativo no meu caso levou uns 3 minutos para aparecer essa informação no painel.</p>
<h3 id="heading-adicionando-eventos-no-firebase-analytics"><strong>Adicionando eventos no Firebase Analytics</strong></h3>
<ul>
<li><p><strong>Eventos:</strong> o que está acontecendo no seu aplicativo, como ações do usuário, eventos do sistema ou erros. Você pode relatar até 500 tipos diferentes de Eventos por aplicativo e pode associar até 25 parâmetros exclusivos a cada tipo de Evento.</p>
<p>  Cada tipo de <a target="_blank" href="https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event#APP_OPEN\(\)">evento</a> é identificado por um nome exclusivo. Os nomes de eventos podem ter até 40 caracteres, podem conter apenas caracteres <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#isLetterOrDigit-int-">alfanuméricos e sublinhado</a>s ("_") e devem começar com um caractere <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#isLetter-int-">alfabético</a>.</p>
</li>
<li><p><strong>Propriedades do usuário:</strong> atributos que você define para descrever segmentos da sua base de usuários, como preferência de idioma ou localização geográfica.</p>
</li>
</ul>
<p>Certos eventos são recomendados para todos os aplicativos, outros são recomendados para tipos de negócios ou verticais específicos.</p>
<p>Você deve enviar eventos sugeridos junto com seus parâmetros prescritos, para garantir o máximo de detalhes disponíveis em seus relatórios e para se beneficiar de recursos e integrações futuras conforme eles se tornam disponíveis.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">await</span> FirebaseAnalytics.instance
  .logBeginCheckout(
    value: <span class="hljs-number">10.0</span>,
    currency: <span class="hljs-string">'USD'</span>,
    items: [
      AnalyticsEventItem(
        itemName: <span class="hljs-string">'Socks'</span>,
        itemId: <span class="hljs-string">'xjw73ndnw'</span>,
        price: <span class="hljs-string">'10.0'</span>
      ),
    ],
    coupon: <span class="hljs-string">'10PERCENTOFF'</span>
  );
</code></pre>
<p><strong>Eventos predefinidos:</strong> O evento <code>logBeginCheckout</code> é criado especificamente para rastrear o início de um processo de checkout ele é um evento padrão do analytics para aplicativos de compras.</p>
<p><strong>Eventos personalizados:</strong> Se seu aplicativo tiver necessidades específicas não cobertas por um tipo de evento sugerido, você pode registrar seus próprios eventos personalizados, conforme mostrado neste exemplo:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">await</span> FirebaseAnalytics.instance.logEvent(
    name: <span class="hljs-string">"share_image"</span>,
    parameters: {
        <span class="hljs-string">"image_name"</span>: name,
        <span class="hljs-string">"full_text"</span>: text,
    },
);
</code></pre>
<p><code>logEvent</code> é um método de uso geral para registrar eventos personalizados com um nome e parâmetros definidos por você.</p>
<p>O evento do exemplo se chama <code>share_image</code>.</p>
<p><code>parameters</code>: Aqui você pode passar informações adicionais, como o método de cadastro (ex: email, Google, etc.) ou até mesmo o ID do usuário recém-criado.</p>
<p>Parâmetros personalizados podem ser usados como <a target="_blank" href="https://support.google.com/analytics/answer/10075209?hl=pt-br">dimensões ou métricas em relatórios do Ana</a><a target="_blank" href="https://support.google.com/analytics/answer/9212670?hl=pt-br">lytics.</a></p>
<h3 id="heading-aqui-estao-algumas-sugestoes-de-onde-voce-pode-implementar-eventos-de-conversao"><strong>Aqui estão algumas sugestões de onde você pode implementar eventos de conversão 🎯</strong></h3>
<ol>
<li><p><strong>Cadastro/Login de Usuário:</strong></p>
<ul>
<li><p>Evento: <code>sign_up</code> ou <code>login</code></p>
</li>
<li><p>Quando um usuário criar uma conta ou fizer login no app, você pode capturar esses eventos para medir o engajamento de novos usuários e a retenção de antigos.</p>
</li>
</ul>
</li>
<li><p><strong>Interações com Funcionalidades Importantes:</strong></p>
<ul>
<li><p>Evento: Defina eventos personalizados como <code>feature_usage</code> para funcionalidades que você considera chave no app.</p>
</li>
<li><p>Exemplo: No caso de um app de adoção de pets, pode ser quando o usuário visualizar um pet ou enviar uma solicitação de adoção.</p>
</li>
</ul>
</li>
<li><p><strong>Compra ou Ações Monetizadas (se houver):</strong></p>
<ul>
<li><p>Evento: <code>purchase</code> ou um evento personalizado como <code>subscription_upgrade</code></p>
</li>
<li><p>Caso o app tenha compras ou assinatura premium, é essencial rastrear quando um usuário realiza uma compra ou upgrade.</p>
</li>
</ul>
</li>
<li><p><strong>Finalização de Fluxos Críticos:</strong></p>
<ul>
<li><p>Evento: <code>conversion</code></p>
</li>
<li><p>Esse evento pode ser acionado quando o usuário completar um fluxo essencial para o objetivo do app. No seu caso, seria ideal rastrear quando um usuário adota um pet com sucesso, por exemplo.</p>
</li>
</ul>
</li>
</ol>
<p>Esses eventos darão insights sobre o comportamento do usuário e ajudarão a medir o sucesso das conversões dentro do seu app.</p>
<h3 id="heading-onde-integrar-os-eventos-no-aplicativo"><strong>Onde integrar os eventos no aplicativo?</strong></h3>
<p>Para chamar os métodos do Firebase Analytics no Flutter, o ideal é integrá-los nos momentos corretos do ciclo de vida das telas e nas interações do usuário. Aqui estão os melhores pontos para chamar os métodos do Analytics no seu app Flutter:</p>
<p><strong>1. Inicialização do App (Primeira execução ou navegação)</strong></p>
<p>Se você deseja rastrear a primeira vez que o usuário abre o app ou chega em uma tela específica, pode usar o método <code>logEvent</code> no momento em que a tela é construída ou quando o app é iniciado.</p>
<ul>
<li><pre><code class="lang-dart">  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> initState() {
    <span class="hljs-keyword">super</span>.initState();
    FirebaseAnalytics.instance.logEvent(name: <span class="hljs-string">'app_open'</span>);
  }
</code></pre>
</li>
</ul>
<p>Esse código pode ser colocado no <code>initState</code> da tela inicial do seu app ou na primeira página carregada após o Splash Screen.</p>
<p><strong>2. Navegação Entre Telas:</strong></p>
<p>Use o Firebase Analytics para rastrear quando o usuário navega entre telas ou páginas importantes no seu app. Para isso, você pode utilizar o método <code>setCurrentScreen</code> quando a navegação for concluída.</p>
<ul>
<li><pre><code class="lang-dart">  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> didChangeDependencies() {
    <span class="hljs-keyword">super</span>.didChangeDependencies();
    FirebaseAnalytics.instance.setCurrentScreen(
      screenName: <span class="hljs-string">'home_screen'</span>,
      screenClassOverride: <span class="hljs-string">'HomeScreen'</span>,
    );
  }
</code></pre>
</li>
</ul>
<p>Chame esse método quando o usuário acessar uma nova página, como na função de navegação ou ao construir o widget da página.</p>
<p><strong>3. Interações de Usuário:</strong></p>
<p>Para eventos que envolvem interações específicas, como clicar em um botão, enviar um formulário ou qualquer outra ação importante, você deve chamar o método <code>logEvent</code> diretamente dentro do callback do evento.</p>
<ul>
<li><pre><code class="lang-dart">  ElevatedButton(
    onPressed: () {
      FirebaseAnalytics.instance.logEvent(name: <span class="hljs-string">'button_click'</span>, parameters: {
        <span class="hljs-string">'button_name'</span>: <span class="hljs-string">'adopt_pet'</span>,
      });
    },
    child: Text(<span class="hljs-string">'Adotar Pet'</span>),
  )
</code></pre>
</li>
</ul>
<p>Isso vai garantir que eventos de interação como cliques ou ações de formulário sejam registrados corretamente.</p>
<p><strong>4. Finalização de Páginas</strong></p>
<ul>
<li>Se você deseja rastrear quando o usuário deixa uma página ou completa uma tarefa (ex: finaliza o cadastro), você pode chamar o <code>logEvent</code> ou <code>setCurrentScreen</code> ao sair de uma página ou ao final de um fluxo de navegação.</li>
</ul>
<h3 id="heading-onde-evitar"><strong>Onde evitar?</strong> 🧐</h3>
<ul>
<li><strong>Construtor de Widgets:</strong> Evite chamar eventos de Analytics no <code>build()</code> de widgets. Isso pode resultar em chamadas excessivas e impactar o desempenho, já que o <code>build</code> pode ser chamado várias vezes durante a execução de uma página.</li>
</ul>
<h2 id="heading-conversoes"><strong>Conversões</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729769991613/5d1a5ca3-e5b3-4462-a02e-8f7df17c6922.png" alt class="image--center mx-auto" /></p>
<p>São seus eventos mais importantes que contribuem para o sucesso do seu negócio. Quando você rotula um evento como um evento de conversão, ele será carregado imediatamente pelo SDK para torná-lo acionável mais rapidamente.</p>
<p>Coisas como fazer uma compra, inscrever-se para uma conta, compartilhar um produto e assim por diante são todos bons eventos que devem ser rotulados como conversões.</p>
<p>Por exemplos poderiamos ter uma conversão chamada <strong>begin_checkout</strong> que é quando um usuário clica no botão Checkout em seu carrinho de compras.</p>
<h2 id="heading-audiencias"><strong>Audiências</strong></h2>
<p>São grupos específicos de usuários segmentados que você pode definir com base em certos critérios ou eventos dentro do seu app Flutter.</p>
<p>Isso permite que você segmente os usuários com base em atributos como idade, localização, eventos específicos que realizaram no app, ou até ações como interações com certas telas ou cliques em botões.</p>
<p>Essas audiências são úteis para acompanhar o comportamento de grupos específicos, criando campanhas personalizadas e direcionadas, como enviar notificações específicas via Firebase Cloud Messaging.</p>
<p>Por exemplo, poderiamos criar um audiência de usuários que visualizam produtos várias vezes, mas não fazem uma compra e nesse caso enviar enviar notificações específicas para esse público.</p>
<h2 id="heading-rastrear-propriedades-do-usuario"><strong>Rastrear propriedades do usuário</strong></h2>
<p>Você pode definir propriedades de asuário do Analytics para descrever os usuários do seu aplicativo. Analisar comportamentos de vários segmentos de usuários aplicando essas propriedades como filtros aos seus relatórios. Veja o exemplo abaixo:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">await</span> FirebaseAnalytics.instance
  .setUserProperty({
    name: <span class="hljs-string">'favorite_food'</span>,
    value: favoriteFood,
  });
</code></pre>
<p><strong>Rastrear IDS do usuário</strong></p>
<p>O Google Analytics tem uma <a target="_blank" href="https://firebase.flutter.dev/docs/analytics/userid">setUserID</a> método, que permite que você armazene um ID de usuário para o indivíduo que usa seu aplicativo.</p>
<p>Observação: você é responsável por garantir que seu uso do ID do usuário esteja de acordo com os <a target="_blank" href="https://firebase.google.com/terms/analytics">Termos de Serviço do Google Analytics</a> .</p>
<p>Isso inclui evitar o uso de informações de identificação pessoal não permitidas e fornecer aviso apropriado sobre seu uso de identificadores em sua Política de Privacidade</p>
<pre><code class="lang-dart"><span class="hljs-keyword">await</span> FirebaseAnalytics.instance
  .setUserId({
    id: <span class="hljs-string">'xxxxxxx'</span>
  });
</code></pre>
<p><strong>Rastrear visualizações de tela</strong></p>
<p>O Analytics rastreia transições de tela e anexa informações sobre a tela atual a eventos, permitindo que você rastreie métricas como engajamento do usuário ou comportamento do usuário por tela.</p>
<p>O método <a target="_blank" href="https://firebase.flutter.dev/docs/analytics/screenviews"><strong>setCurrentScreen</strong></a> é usado para definir o nome da tela atual e a classe, que podem então aparecer no console do Firebase. Isso ajuda você a entender o fluxo de interação do usuário no seu aplicativo e identificar telas e caminhos de navegação populares onde os usuários passam a maior parte do tempo.</p>
<p>Entender isso pode ajudar você a tomar decisões baseadas em dados sobre em quais áreas do seu aplicativo concentrar seus esforços de desenvolvimento e melhoria.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">await</span> FirebaseAnalytics.instance.setCurrentScreen(
  screenName: <span class="hljs-string">'screen_name'</span>,
  screenClassOverride: <span class="hljs-string">'screen_class'</span>,
);
</code></pre>
<p><strong><mark>Firebase Analytics Observer ao Navigator (opcional)</mark></strong></p>
<p>Se você quiser rastrear eventos de navegação, precisará adicionar o <strong>FirebaseAnalyticsObserver</strong> à propriedade <strong>navigatorObservers</strong> do seu <strong>MaterialApp</strong> , <strong>WidgetsApp</strong> ou <strong>CupertinoApp</strong> .</p>
<p>Veja o exemplo abaixo: ⬇️</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-comment">// Inicializando o FirebaseAnalytics</span>
  <span class="hljs-keyword">static</span> FirebaseAnalytics analytics = FirebaseAnalytics();
  <span class="hljs-keyword">static</span> FirebaseAnalyticsObserver observer =
      FirebaseAnalyticsObserver(analytics: analytics);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> MaterialApp(
      title: <span class="hljs-string">'Firebase Analytics Example'</span>,
      navigatorObservers: [
        observer,  <span class="hljs-comment">// Adiciona o FirebaseAnalyticsObserver ao sistema de navegação</span>
      ],
      home: MyHomePage(),
    );
  }
}
</code></pre>
<p>O <code>FirebaseAnalyticsObserver</code> é uma classe do pacote <code>firebase_analytics</code> no Flutter, usada para integrar o Firebase Analytics ao sistema de navegação do Flutter.</p>
<p>Isso permite que eventos de navegação dentro do app sejam automaticamente rastreados e enviados ao Firebase Analytics, facilitando o acompanhamento de quais telas estão sendo acessadas pelos usuários e em que ordem.</p>
<p>Quando você adiciona o <code>FirebaseAnalyticsObserver</code> ao seu app Flutter, ele monitora as mudanças de rota (ou páginas) dentro da aplicação e envia eventos correspondentes para o Firebase Analytics, como o nome da rota que foi visitada. Isso é útil para medir o comportamento do usuário, como quais telas ele acessa mais frequentemente ou se ele completa um fluxo específico no app.</p>
<h2 id="heading-conferindo-os-eventos-no-painel">Conferindo os eventos no painel</h2>
<p>Você pode encontrar estatísticas agregadas sobre os eventos nos painéis de controle do Console do Firebase. Eles são atualizados periodicamente ao longo do dia.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730115682034/8174962b-9e13-47bf-8099-7252848bc964.png" alt="Console do Firebase Analytics" class="image--center mx-auto" /></p>
<p>🛑  <mark> Segundo a documentação, pode ser que leve de 1h até 24 horas para aparecer os eventos clicados no aplicativo.</mark></p>
<p>Siga para a proxíma seção: ⬇️</p>
<h2 id="heading-exibir-eventos-na-depuracao-debugview">Exibir eventos na depuração (DebugView)</h2>
<p>Com o modo DebugView, você pode ver dados brutos de eventos registrados pelo seu app quase em tempo real em dispositivos de desenvolvimento.</p>
<p>Isso é muito útil para fins de validação durante a fase de instrumentação do desenvolvimento e pode ajudar você a descobrir erros e falhas na sua implementação do Analytics, além de confirmar se todas as propriedades dos usuários e eventos estão sendo registrados corretamente.</p>
<h4 id="heading-android">Android</h4>
<p>Para habilitar a depuração em dispositivos Android, execute o seguinte comando no seu terminal:</p>
<pre><code class="lang-bash">adb shell setprop debug.firebase.analytics.app [your_app_package_name]
</code></pre>
<p>O modo de depuração vai permanecer ativado até que você execute a linha de comando a seguir:</p>
<pre><code class="lang-bash">adb shell setprop debug.firebase.analytics.app .none.
</code></pre>
<h4 id="heading-ios">iOS</h4>
<p>Para habilitar o debug view para iOS, comece abrindo a pasta <strong><em>ios</em></strong> <em>no Xcode. Em seguida, navegue até</em> <strong><em>Product-&gt;Scheme-&gt;Edit Scheme.</em></strong></p>
<p>Seguida adicione os seguintes argumentos <strong>-FIRDebugEnabled</strong> e <strong>-FIRDebugDisabled</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730116165249/298e7710-2580-459e-96a5-e803905d92b5.png" alt="Xcode" class="image--center mx-auto" /></p>
<p>Para adicionar esses argumentos, edite o esquema do projeto e adicione uma nova entrada a "<strong>Arguments Passed on Launch</strong>". conforme mostrado acima</p>
<p>🛑 <mark>Atenção! O debug view no iOS </mark> <strong><mark>só funcionará se você executar seu aplicativo diretamente do Xcode</mark></strong> <mark>. Executar o aplicativo usando flutter run ou por meio de outra IDE não acionará os argumentos a serem executados na inicialização.</mark></p>
<p>Para desabilitar a depuração, você pode executar os seguintes argumentos na inicialização: *-*<strong><em>FIRDebugDisabled</em></strong> e <em>-<strong><strong>FIRAnalyticsDebugDisabled</strong></strong>.</em></p>
<h3 id="heading-visualizando-o-debugview">Visualizando o DebugView 💡</h3>
<p>Rodei o aplicativo no android e os eventos apareceram em tempo real no painel como mostrado na imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730116449218/72ee6430-965d-4836-a5a0-4a1f3a0a748b.png" alt="DebugView do Analytics" class="image--center mx-auto" /></p>
<p>O <strong>streaming de segundos</strong> (coluna do meio) exibe os eventos que foram registrados nos últimos 60 segundos. O streaming de minutos (coluna da esquerda) exibe uma série de arquivos de eventos nos últimos 30 minutos.</p>
<p>A coluna da direita exibe os principais eventos registrados no intervalo de 30 minutos, bem como as propriedades do usuário atual do dispositivo de desenvolvimento selecionado no momento.</p>
<p>Saiba mais sobre o debug view no <a target="_blank" href="https://firebase.google.com/docs/analytics/debugview?hl=pt-br">link</a>: 🔗</p>
<h3 id="heading-isolando-a-regra-do-analytics-com-o-padrao-service"><strong>Isolando a regra do Analytics com o padrão Service</strong></h3>
<p>A finalidade da camada de serviço, por outro lado, é encapsular a lógica de negócios em um único local para promover a reutilização de código e a separação de interesses.</p>
<p>Basicamente seria isolar uma tarefa específica em um outro objeto sendo assim assumindo uma responsabilidade muito estreita de realizar alguma atividade útil.</p>
<p>Então, vamos criar um serviço para integrar o Firebase Analytics ao seu projeto Flutter e gerenciar os relatórios de erros. 👇🏻</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_analytics/firebase_analytics.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutterfirebaseapp/errors/failure.dart'</span>;

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AnalyticsService</span> </span>{
  <span class="hljs-comment">/// <span class="markdown">If analytics is supported on the current platform.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; initAnalytics();

  <span class="hljs-comment">/// <span class="markdown">If analytics is supported on the current platform.</span></span>
  Future&lt;<span class="hljs-built_in">bool</span>&gt; isSupported();

  <span class="hljs-comment">/// <span class="markdown">Retrieves the session id from the client. Returns null if analyticsStorageConsentGranted is false or session is expired.</span></span>
  Future&lt;<span class="hljs-built_in">int?</span>&gt; getSessionId();

  <span class="hljs-comment">/// <span class="markdown">Logs the standard <span class="hljs-code">`app_open`</span> event.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logAppOpen();

  <span class="hljs-comment">/// <span class="markdown">Logs events customizeds with the given [name] and [parameters].</span></span>
  <span class="hljs-comment">/// <span class="markdown">[name] is the name of the event.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[parameters] are the optional parameters.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logEvent({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  });

  <span class="hljs-comment">/// <span class="markdown">Logs the standard <span class="hljs-code">`screen_view`</span> event.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[screenClass] is the class of the screen.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[screenName] is the name of the screen.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[parameters] are the optional parameters.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logScreenView({
    <span class="hljs-built_in">String?</span> screenClass,
    <span class="hljs-built_in">String?</span> screenName,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  });

  <span class="hljs-comment">/// <span class="markdown">Logs the standard <span class="hljs-code">`sign_up`</span> event.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[signInMethod] is the method used to sign up.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[parameters] are the optional parameters.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logSignUp({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> signUpMethod,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  });

  <span class="hljs-comment">/// <span class="markdown">Clears all analytics data for this app from the device and resets the app instance id.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; resetAnalyticsData();

  <span class="hljs-comment">/// <span class="markdown">Adds parameters that will be set on every event logged from the SDK, including automatic ones.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[defaultParameters] are the default parameters.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setDefaultEventParameters(
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object?</span>&gt;? defaultParameters,
  );

  <span class="hljs-comment">/// <span class="markdown">Sets the duration of inactivity that terminates the current session.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[timeout] is the duration of inactivity that terminates the current session.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setSessionTimeoutDuration(<span class="hljs-built_in">Duration</span> timeout);

  <span class="hljs-comment">/// <span class="markdown">Sets the user id.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[id] is the user id.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setUserId({<span class="hljs-built_in">String?</span> id});

  <span class="hljs-comment">/// <span class="markdown">Sets the user property.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[name] is the name of the property.</span></span>
  <span class="hljs-comment">/// <span class="markdown">[value] is the value of the property.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setUserProperty({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String?</span> value,
  });
}

<span class="hljs-comment">/// <span class="markdown">A class that extends [AnalyticsService] to log events and</span></span>
<span class="hljs-comment">/// <span class="markdown">screen views for Google and Firebase Analytics</span></span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomAnalyticsService</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">AnalyticsService</span> </span>{
  <span class="hljs-keyword">final</span> _firebaseAnalytics = FirebaseAnalytics.instance;
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; initAnalytics() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> _firebaseAnalytics.setAnalyticsCollectionEnabled(<span class="hljs-keyword">true</span>);
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">int?</span>&gt; getSessionId() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> _firebaseAnalytics.getSessionId();
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried get session id from analytics: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">bool</span>&gt; isSupported() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> _firebaseAnalytics.isSupported();
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried check if analytics is supported: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logAppOpen({<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters}) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.logAppOpen(parameters: parameters);
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register a log for app open: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logEvent({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  }) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.logEvent(
        name: name,
        parameters: parameters,
      );
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register a event: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logScreenView({
    <span class="hljs-built_in">String?</span> screenClass,
    <span class="hljs-built_in">String?</span> screenName,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  }) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.logScreenView(
        screenClass: screenClass,
        screenName: screenName,
        parameters: parameters,
      );
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register a event for Screen View: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logSignUp({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> signUpMethod,
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt;? parameters,
  }) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.logSignUp(
        signUpMethod: signUpMethod,
        parameters: parameters,
      );
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register a log for sign up: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; resetAnalyticsData() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.resetAnalyticsData();
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried reset log from analytics data: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setDefaultEventParameters(
    <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object?</span>&gt;? defaultParameters,
  ) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.setDefaultEventParameters(defaultParameters);
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried set default event parameters on analytics: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setSessionTimeoutDuration(<span class="hljs-built_in">Duration</span> timeout) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.setSessionTimeoutDuration(timeout);
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried set session timeout on analytics: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setUserId({<span class="hljs-built_in">String?</span> id}) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.setUserId(id: id);
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register user id on analytics: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; setUserProperty({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String?</span> value,
  }) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _firebaseAnalytics.setUserProperty(name: name, value: value);
    } <span class="hljs-keyword">catch</span> (exception, stackTrace) {
      <span class="hljs-keyword">throw</span> AnalyticsException(
        <span class="hljs-string">"Error when tried register user property on analytics: exception <span class="hljs-subst">$exception</span> stackTrace: <span class="hljs-subst">$stackTrace</span>"</span>,
      );
    }
  }
}
</code></pre>
<p><strong>Referências:</strong></p>
<p><a target="_blank" href="https://firebase.flutter.dev/docs/analytics/get-started">https://firebase.flutter.dev/docs/analytics/get-started</a></p>
<p><a target="_blank" href="https://www.walturn.com/insights/how-to-set-up-analytics-in-flutter-using-firebase">https://www.walturn.com/insights/how-to-set-up-analytics-in-flutter-using-firebase</a></p>
<p><a target="_blank" href="https://firebasetutorials.com/events-in-firebase-analytics/">https://firebasetutorials.com/events-in-firebase-analytics/</a></p>
<h1 id="heading-conclusao"><strong>Conclusão</strong></h1>
<p>Bom é isso 😎.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*pIVZ59MRLIckIWQMUzlyDg.gif" alt="Spark via Dribble" /></p>
<p>O Firebase Analytics é uma ótima ferramenta para entender melhor o comportamento do seu cliente e o desempenho do aplicativo combinado a outros produtos do Firebase. 🔥</p>
<p>Neste artigo, você aprendeu como configurar e preparar nossos aplicativos Flutter para serem usados ​​com o Firebase Analytics. 📚</p>
<p>Aqui está o código do <a target="_blank" href="https://github.com/iang12/firebase-flutter-example"><strong>projeto</strong></a> de exemplo no github. 🔗</p>
<p>Em artigos futuros da série, veremos como usar outros recursos do Firebase, como Authentication, Remote Config, Admob e muito mais com Flutter. 💙</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo! 🌍</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h3 id="heading-minhas-redes-sociais">🌐 Minhas redes sociais 🌐</h3>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> <strong>(X)</strong> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Utilizando o Firebase Crashlytics no Flutter]]></title><description><![CDATA[Introdução
Diga adeus às falhas misteriosas com o Crashlytics!
O Firebase Crashlytics, uma ferramenta robusta e essencial do Firebase, é um serviço fornecido pelo Google projetado para rastrear e capturar falhas em tempo real em nossos aplicativos. 
...]]></description><link>https://ianoliveira.dev/utilizando-o-firebase-crashlytics-no-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/utilizando-o-firebase-crashlytics-no-flutter</guid><category><![CDATA[Firebase]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Tue, 17 Sep 2024 11:49:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726570802208/2211ccc8-946d-42cd-8984-6ed8d5911cea.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introducao"><strong>Introdução</strong></h3>
<p>Diga adeus às falhas misteriosas com o Crashlytics!</p>
<p>O Firebase Crashlytics, uma ferramenta robusta e essencial do Firebase, é um serviço fornecido pelo Google projetado para rastrear e capturar falhas em tempo real em nossos aplicativos. </p>
<p>Sua funcionalidade crucial reside em manter um registro detalhado e imediato de qualquer falha que ocorra, oferecendo insights valiosos sobre a estabilidade do aplicativo. Ao enviar relatórios detalhados assim que as falhas acontecem, o Crashlytics fornece uma visão clara e profunda das questões que afetam a experiência do usuário. </p>
<p>Ao coletar dados preciosos, essa ferramenta capacita os desenvolvedores a entenderem melhor a causa raiz dos problemas e assim tomar medidas corretivas eficazes.</p>
<p>Este artigo faz parte da série “<strong>Dominando o Firebase em Aplicativos Flutter</strong>”, uma sequência de posts que explora como utilizar todos os produtos do Firebase em conjunto com o Flutter. Confira as demais publicações da série no blog para aprofundar seus conhecimentos.</p>
<h3 id="heading-beneficios-do-firebase-crashlytics"><strong>Benefícios do Firebase Crashlytics</strong></h3>
<ul>
<li><p><strong>Melhora na estabilidade do aplicativo:</strong> Com insights detalhados sobre as falhas, você pode corrigir bugs de forma rápida e eficiente, resultando em um aplicativo mais confiável.</p>
</li>
<li><p><strong>Experiência aprimorada do usuário:</strong> Identificando e corrigindo erros proativamente, você evita experiências ruins para os usuários, o que leva a melhor satisfação e retenção.</p>
</li>
<li><p><strong>Economia de tempo de desenvolvimento:</strong> As informações detalhadas do Crashlytics ajudam a localizar e solucionar problemas com muito mais rapidez em comparação a tentativas aleatórias de depuração.</p>
</li>
<li><p><strong>Integração com o Firebase:</strong> O Crashlytics tem integração nativa com outras ferramentas do Firebase, como <strong>Analytics</strong>, fornecendo dados mais abrangentes sobre a saúde e o comportamento de seus aplicativos.</p>
</li>
</ul>
<p>Você também pode olhar esse <a target="_blank" href="https://www.youtube.com/watch?v=1wBpX0iFl5E">video</a> do canal do Flutter onde eles explicam resumidamente como funciona a ferramenta.</p>
<h3 id="heading-configurando-e-utilizando-em-seu-projeto">Configurando e utilizando em seu projeto</h3>
<h4 id="heading-1-habilitando-o-crashlytics">1 — Habilitando o Crashlytics</h4>
<p>Vá para o Console do Firebase e no painel esquerdo, em Release &amp; Monitor, vá para Crashlytics no menu e clique no botão.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*aG4HhFFTVRFmxMR-DlryHg.png" alt="Firebase console" /></p>
<h4 id="heading-2-adicionando-a-dependencia-em-seu-projeto">2 — Adicionando a dependência em seu projeto</h4>
<p>Vamos começar adicionando a dependência ao nosso arquivo <strong><em>pubspec.yaml.</em></strong></p>
<p>Instale o pacote a partir da linha de comando com o Flutter:</p>
<pre><code class="lang-bash">$ flutter pub add firebase_crashlytics
</code></pre>
<p>Ou adicione <code>firebase_crashlytics</code> diretamente em seu <code>pubspec.yaml</code> e execute <code>flutter pub get</code> no momento da criação desse post ele está na versão 4.1.1 .</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
 <span class="hljs-attr">firebase_crashlytics:</span> <span class="hljs-string">^4.1.1</span>
</code></pre>
<p>Agora, no seu código Dart, você pode importar o package:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_crashlytics/firebase_crashlytics.dart'</span>;
</code></pre>
<h3 id="heading-painel-do-crashytics">Painel do crashytics</h3>
<p><img src="https://cdn-images-1.medium.com/max/800/1*VICuVgJvwP-T16pEDexqug.png" alt="Firebase crashlytics" /></p>
<p>Essa é a parte central do Crashlytics. Ela contém informações sobre o dispositivo, usuário, logs, stack traces, etc.</p>
<h3 id="heading-tipos-de-falhas">Tipos de falhas</h3>
<p>No Firebase Crashlytics, os erros são divididos em duas categorias principais: <strong>erros fatais</strong> e <strong>erros não fatais</strong>. Vamos entender cada um:</p>
<h4 id="heading-erros-fatais-fatal-errors">Erros Fatais (Fatal Errors)</h4>
<p>São falhas que levam ao fechamento inesperado do aplicativo, interrompendo a execução imediatamente. </p>
<p>Por exemplo: quando uma exceção não tratada ocorre e o app é forçado a parar, como um erro de <code>NullPointerException</code> em uma linguagem como Kotlin ou Java.</p>
<h4 id="heading-erros-nao-fatais-non-fatal-errors">Erros Não Fatais (Non-fatal Errors)</h4>
<p>São erros que ocorrem dentro do aplicativo, mas que não causam o fechamento imediato. O aplicativo continua rodando, mas uma operação pode ter falhado ou algo não foi executado corretamente. </p>
<p>Por exemplo: uma requisição de rede que falha ou uma operação lógica que lança uma exceção tratada, como um erro de parsing JSON. Registrar exceções não fatais significa que podemos registrar exceções capturadas nos blocos <em>catch</em> do nosso aplicativo.</p>
<h3 id="heading-enviando-relatorios-para-crashlytics">Enviando relatórios para Crashlytics ⚡️</h3>
<p>Para enviar dados de relatório ao Crashlytics, o aplicativo deve ser reiniciado. O Crashlytics envia automaticamente quaisquer relatórios de falhas ao Firebase na próxima vez que o aplicativo for iniciado.</p>
<p>Para testar se a integração com o crashlytics foi realizada com sucesso vamos induzir um erro de propósito para que seja registrado no console do firebase. </p>
<p>No seu <strong><em>main.dart</em></strong> adicione o seguinte trecho de código:</p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
    WidgetsFlutterBinding.ensureInitialized();
    <span class="hljs-keyword">await</span> Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
    FlutterError.onError = (errorDetails) {
      FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
    };
    <span class="hljs-comment">// Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics</span>
    PlatformDispatcher.instance.onError = (error, stack) {
      FirebaseCrashlytics.instance.recordError(error, stack, fatal: <span class="hljs-keyword">true</span>);
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
    };
    runApp(MyApp());
}
</code></pre>
<p>Ao substituir o <code>FlutterError.onError</code> por <code>FirebaseCrashlytics.instance.recordFlutterError</code>, ele captura automaticamente todos os erros lançados na estrutura do Flutter e registra-os para enviar ao Firebase.</p>
<p>Para capturar quaisquer erros assíncronos que não são tratados pela estrutura do Flutter, podemos usar <code>PlatformDispatcher.instance.onError</code></p>
<p>Depois que rodei o aplicativo com o código acima o crashlytics detectou a integração com o meu aplicativo automaticamente. Veja a imagem abaixo:</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*Mm5atxOL9x8Hzx488UcBXQ.png" alt /></p>
<h4 id="heading-gerando-uma-falha-para-registro"><strong>Gerando uma falha para registro</strong></h4>
<p>Agora crie um botão qualquer no seu aplicativo Flutter e coloque o seguinte trecho de código: <code>FirebaseCrashlytics.instance.crash()</code> .</p>
<pre><code class="lang-dart">ElevatedButton(
    onPressed: () {
      FirebaseCrashlytics.instance.crash();
    },
    child: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Gerar falha'</span>),
  )
</code></pre>
<p>Ao rodar o aplicativo e apertar no botão, quase instantaneamente, a aplicação quebrará.</p>
<p>Na próxima vez que ela for aberta, o aplicativo será sincronizado com o Firebase e teremos a estatística no painel do Crashlytics. As vezes pode demorar alguns minutinhos para aparecer no painel ou não, no meu caso foi instantâneo.</p>
<p>Confira a imagem abaixo:</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*XyzWF1tNI7UcyCMXC7DCLw.png" alt="Painel do crashlytics" /></p>
<p>O painel do crashlytics mostra detalhadamente e agrupa os problemas lhe ajudando a priorizar quais correções são mais urgentes no momento.</p>
<p>Quando você clica na mensagem de erro, você pode ver a mensagem de teste (<code>This is a test crash caused by calling .crash() in Dart</code>) como abaixo.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*4ZITDcilRc13biOXZELlyQ.png" alt /></p>
<h3 id="heading-personalizar-relatorios-de-erros-do-firebase-crashlytics">Personalizar relatórios de erros do Firebase Crashlytics</h3>
<p>No Crashlytics é possível associar pares de chave-valor arbitrários aos seus relatórios de erros e usar as chaves personalizadas para pesquisar e filtrar relatórios no console do Firebase. Veja alguns exemplos:</p>
<pre><code class="lang-dart"><span class="hljs-comment">// Set a key to a string.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">'str_key'</span>, <span class="hljs-string">'hello'</span>);

<span class="hljs-comment">// Set a key to a boolean.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">"bool_key"</span>, <span class="hljs-keyword">true</span>);

<span class="hljs-comment">// Set a key to an int.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">"int_key"</span>, <span class="hljs-number">1</span>);

<span class="hljs-comment">// Set a key to a long.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">"int_key"</span>, <span class="hljs-number">1</span>L);

<span class="hljs-comment">// Set a key to a float.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">"float_key"</span>, <span class="hljs-number">1.0</span>f);

<span class="hljs-comment">// Set a key to a double.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">"double_key"</span>, <span class="hljs-number">1.0</span>);
</code></pre>
<h4 id="heading-logs-e-informacoes-relacionadas-ao-usuario">Logs e informações relacionadas ao usuário.</h4>
<p><code>setCustomKey</code>é usado para armazenar informações personalizadas sobre o usuário ou o aplicativo.</p>
<p>Você pode associar pares arbitrários de chave/valor aos seus relatórios de falha e, em seguida, usar as chaves personalizadas para pesquisar e filtrar relatórios de falha no console do Firebase.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*Y5VTKRCvH6GUcbzTNmLSFw.png" alt /></p>
<pre><code class="lang-dart"><span class="hljs-comment">// Chaves.</span>
FirebaseCrashlytics.instance.setCustomKey(<span class="hljs-string">'userId'</span>, <span class="hljs-string">'12345'</span>);
<span class="hljs-comment">// Logs.</span>
FirebaseCrashlytics.instance.log(<span class="hljs-string">"Higgs-Boson detected! Bailing out"</span>);
<span class="hljs-comment">// Dados.</span>
FirebaseCrashlytics.instance.setUserIdentifier(<span class="hljs-string">"12345"</span>);
</code></pre>
<p><code>log</code>é usado para armazenar logs. </p>
<p>Para dar a si mesmo mais contexto para os eventos que levaram a uma falha, você pode adicionar logs personalizados do Crashlytics ao seu aplicativo. </p>
<p><code>setUserIdentifier</code>é usado para definir a quem o relatório pertence.</p>
<p>Para diagnosticar um problema, geralmente é útil saber quais dos nossos usuários experimentaram uma determinada falha. </p>
<h3 id="heading-desabilitando-o-envio-de-dados-em-desenvolvimento">Desabilitando o envio de dados em desenvolvimento</h3>
<p>Para garantir que o Crashlytics fique desabilitado quando seu aplicativo estiver no modo de debug, você pode fazer o seguinte:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/foundation.dart'</span> <span class="hljs-keyword">show</span> kDebugMode;

<span class="hljs-keyword">if</span> (kDebugMode) {
  <span class="hljs-comment">// Force disable Crashlytics collection while doing every day development.</span>
  <span class="hljs-comment">// Temporarily toggle this to true if you want to test crash reporting in your app.</span>
  <span class="hljs-keyword">await</span> FirebaseCrashlytics.instance
      .setCrashlyticsCollectionEnabled(<span class="hljs-keyword">false</span>);
} <span class="hljs-keyword">else</span> {
  <span class="hljs-comment">// Handle Crashlytics enabled status when not in Debug,</span>
  <span class="hljs-comment">// e.g. allow your users to opt-in to crash reporting.</span>
}
</code></pre>
<p>Você também consegue saber se ele está ativado com o seguinte trecho de código.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">if</span> (FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled) {
  <span class="hljs-comment">// Collection is enabled.</span>
}
</code></pre>
<h3 id="heading-como-capturar-erros-manualmente">Como capturar erros manualmente?</h3>
<p>Os erros não fatais são exceções ou problemas que você quer registrar manualmente sem fechar o aplicativo. Para isso, o Firebase Crashlytics oferece métodos para logar esses erros, permitindo que você capture situações como falhas de rede ou erros de lógica tratáveis.</p>
<p>Você pode capturar exceções específicas com Crashlytics, se necessário, usando o código abaixo:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_crashlytics/firebase_crashlytics.dart'</span>;

<span class="hljs-keyword">void</span> reportNonFatalError() {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Simulando um erro que você capturou e tratou</span>
    <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">'Erro não fatal'</span>);
  } <span class="hljs-keyword">catch</span> (error, stackTrace) {
    <span class="hljs-comment">// Registra o erro manualmente no Crashlytics sem fechar o app</span>
    FirebaseCrashlytics.instance.recordError(error, stackTrace);
  }
}
</code></pre>
<p>Esse código acima irá registrar no console do Firebase o erro e a <a target="_blank" href="https://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors">stack trace</a> no Crashlytics como <strong>erro não fatal</strong>, mas o aplicativo continuará rodando normalmente.</p>
<h3 id="heading-isolando-a-regra-do-crashlytics-com-o-padrao-service">Isolando a regra do Crashlytics com o padrão Service</h3>
<p>A finalidade da camada de serviço, por outro lado, é encapsular a lógica de negócios em um único local para promover a reutilização de código e a separação de interesses. </p>
<p>Basicamente seria isolar uma tarefa específica em um outro objeto sendo assim assumindo uma responsabilidade muito estreita de realizar alguma atividade útil.</p>
<p>Então, vamos criar um serviço para integrar o Firebase Crashlytics ao seu projeto Flutter e gerenciar os relatórios de erros. 👇🏻</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="88f75528fb028e59b646c2d4d9003efd"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iang12/88f75528fb028e59b646c2d4d9003efd" class="embed-card">https://gist.github.com/iang12/88f75528fb028e59b646c2d4d9003efd</a></div><p> </p>
<ul>
<li><code>Isolate.current.addErrorListener(ErrorReport.isolateErrorListener)</code> adiciona um ouvinte de erros para isolados (ou seja, quando múltiplos threads estão rodando em paralelo no app), garantindo que erros ocorridos fora do thread principal sejam capturados e reportados.</li>
</ul>
<h3 id="heading-exemplo-de-uso-do-crashlytcsservice">Exemplo de uso do <code>CrashlytcsService</code></h3>
<p>Essa abordagem centraliza a manipulação de exceções e falhas no aplicativo, garante que erros sejam capturados e enviados para monitoramento via Crashlytics, e oferece flexibilidade para criar diferentes tipos de erros com pouca repetição de código.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/foundation.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'../service/crashlytics_service.dart'</span>;

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Failure</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Exception</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> errorMessage;

  Failure({
    StackTrace? stackTrace,
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    <span class="hljs-keyword">this</span>.errorMessage = <span class="hljs-string">''</span>,
  }) {
    <span class="hljs-comment">// Loga a stack trace apenas no modo debug para evitar poluição de logs em produção.</span>
    <span class="hljs-keyword">if</span> (stackTrace != <span class="hljs-keyword">null</span> &amp;&amp; kDebugMode) {
      debugPrintStack(label: label, stackTrace: stackTrace);
    }

    <span class="hljs-comment">// Reporta o erro ao Crashlytics se houver exception</span>
    ErrorReport.externalFailureError(exception, stackTrace, label);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UnknownError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Failure</span> </span>{
  UnknownError({
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace? stackTrace,
  }) : <span class="hljs-keyword">super</span>(
          stackTrace: stackTrace,
          label: label,
          exception: exception,
          errorMessage:
              <span class="hljs-string">'Unknown Error'</span>, <span class="hljs-comment">// Passa a mensagem diretamente para a classe base</span>
        );
}
</code></pre>
<h4 id="heading-possiveis-extensoes">Possíveis extensões</h4>
<p>Se no futuro você quiser criar outras subclasses de <code>Failure</code> para diferentes tipos de erros, será muito fácil. Por exemplo, você pode criar uma classe <code>NetworkError</code> para representar erros relacionados à rede, e utilizar o mesmo padrão de construção.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NetworkError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Failure</span> </span>{
  NetworkError({
    <span class="hljs-built_in">String?</span> label,
    <span class="hljs-built_in">dynamic</span> exception,
    StackTrace? stackTrace,
  }) : <span class="hljs-keyword">super</span>(
          stackTrace: stackTrace,
          label: label,
          exception: exception,
          errorMessage: <span class="hljs-string">'Network Error'</span>,
        );
}
</code></pre>
<h3 id="heading-configurando-os-arquivos-dsym-do-xcode-para-o-crashlytics-no-ios">Configurando os arquivos dSYM do Xcode para o crashlytics no IOS <strong>🛠️</strong></h3>
<p>Para gerar relatórios de falhas legíveis por humanos no IOS, o Crashlytics precisa dos arquivos de símbolo de depuração (dSYM) do seu projeto salvos no console do Firebase.</p>
<p>Sem isso o Crashlytics vai ficar te enviando emails constantemente pedindo que você faça esse upload dos (dSYM) no painel do crashlytics, veja a imagem abaixo:</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*NlT0pTvI2uKTG78U0Necgw.png" alt /></p>
<p>Abra seu projeto no Xcode e gere um <strong>archive</strong>. Basta ir no menu, clicar em <strong>product &gt; archive.</strong></p>
<p>Depois de gerado com sucesso vai aparecer a seguinte tela para você: 👇🏻</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*VriClkFizkw8xbHLZdeHig.png" alt="Xcode" /></p>
<p>Clique com o botão direito no <strong>archive</strong> e selecione a opção <strong>Show in Finder</strong>, e após abrir o finder clique no arquivo com o botão direito e selecione a opção <strong>Show Packages Contents,</strong> veja a imagem abaixo:</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*M6VwcZfOhSIWgRMvgm6q8w.png" alt="Finder (MacOS)" /></p>
<p>O resultado será uma listagem de arquivos e pastas e nela terá o que precisamos os nossos <strong>dSYMs.</strong></p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*y4F0-Z6JK2dG-G62rYdVuA.png" alt="Finder (MacOS)" /></p>
<p>Comprima essa pasta em um .<strong>zip</strong> e faça o upload dela no firebase crashlytics na parte do IOS.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*ykJkP71o-lVccotixdZoWQ.png" alt /></p>
<p>Feito isso, podemos ver que os nossos <strong>dSYMs</strong> foi enviado com sucesso.</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*WEQHN__Rwv5N72CvmhVesA.png" alt="Firebase crashlytics" /></p>
<h3 id="heading-conclusao">Conclusão</h3>
<p><img src="https://cdn-images-1.medium.com/max/800/1*pIVZ59MRLIckIWQMUzlyDg.gif" alt="Spark via Dribble" /></p>
<p>Bom é isso 😎.</p>
<p>Neste artigo, você aprendeu como configurar e preparar nossos aplicativos Flutter para serem usados ​​com o Firebase Crashlytics.</p>
<p>Aqui está o código do <a target="_blank" href="https://github.com/iang12/firebase-flutter-example">projeto</a> de exemplo no github. 🔗</p>
<p>Em artigos futuros da série, veremos como usar outros recursos do Firebase, como Authentication, Remote Config, Analytics e muito mais com Flutter.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h3 id="heading-minhas-redes-sociais">🌐 Minhas redes sociais 🌐</h3>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> <strong>(X)</strong> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Explorando o Consumo de APIs no Flutter com o Package Dio]]></title><description><![CDATA[Fala meus amigos, tudo blz? 😄.
Nesse artigo vamos aprender a consumir dados da internet em nosso aplicativo utilizando um package chamado dio o client HTTP mais famoso do mundo Flutter. 💙
Consumir dados da internet é a coisa mais básica que pratica...]]></description><link>https://ianoliveira.dev/explorando-o-consumo-de-apis-no-flutter-com-o-package-dio</link><guid isPermaLink="true">https://ianoliveira.dev/explorando-o-consumo-de-apis-no-flutter-com-o-package-dio</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[internet]]></category><category><![CDATA[Flutter Examples]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Tue, 03 Sep 2024 11:33:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725362429334/a6b04076-142d-449d-ba46-47de3580b427.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala meus amigos, tudo blz? 😄.</p>
<p>Nesse artigo vamos aprender a consumir dados da internet em nosso aplicativo utilizando um package chamado <a target="_blank" href="https://pub.dev/packages/dio">dio</a> o client HTTP mais famoso do mundo Flutter. 💙</p>
<p>Consumir dados da internet é a coisa mais básica que praticamente todo aplicativo vai ter, então vamos lá ✍🏻</p>
<h3 id="heading-o-que-sao-apis">O que são APIS ?</h3>
<p>De forma geral uma API significa <strong><em>Application Programming Interface</em></strong> (interface de programação de aplicações, ou seja, é uma forma que permite a transmissão de dados entre um software e outro, utilizando APIS empresas conseguem abrir os dados e funcionalidades de seus aplicativos para desenvolvedores externos de terceiros, parceiros de negócios, sistemas etc.</p>
<p>Sendo assim, as APIs proporcionam interoperabilidade entre aplicações totalmente diferentes possibilitando uma integração entre dois ou mais sistemas. </p>
<p>O mais interessante é que quem consome a API não precisa se preocupar com os detalhes da implementação dessa API, um exemplo disso é uma aplicação mobile consumindo dados de uma api de clima para obter os dados sobre o tempo local.</p>
<h3 id="heading-o-que-e-rest">O que é REST?</h3>
<p>o conceito de <strong>REST</strong> (<em>Representational State Transfer</em>) é como um modelo de boas práticas de arquitetura de software que define uma série de requisitos para que as APIs sejam desenvolvidas. Uma API REST é uma API que está em conformidade com os princípios de design do REST.</p>
<p>Se você quiser aprender um pouco mais sobre esse tema acesse esse <a target="_blank" href="https://www.redhat.com/en/topics/api/what-is-a-rest-api">link</a>. </p>
<h3 id="heading-o-que-e-http">O que é HTTP?</h3>
<p>O HTTP (Hypertext Transfer Protocol ou Protocolo de Transferência de Hipertexto em português) é o protocolo principal de comunicação entre computadores no mundo, oferece aos usuários uma maneira de interagir com recursos da Web, como arquivos HTML, transmitindo mensagens de hipertexto entre clientes e servidores.</p>
<h3 id="heading-metodos-de-solicitacao-http">Métodos de solicitação HTTP</h3>
<p>O HTTP utiliza métodos ou verbos de solicitação específicos para realizar várias tarefas como solicitar, criar, atualizar e deletar os dados, abaixo eu mostro os principais e mais utilizados.</p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET"><code>GET</code></a> Solicita e recupera dados do servidor</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"><code>POST</code></a> Adicionar ou cria dados no servidor;</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT"><code>PUT</code></a> Atualizações de registros.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE"><code>DELETE</code></a> Excluir um registro especificado.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH"><code>PATCH</code></a> Atualiza ou modifica parcialmente um recurso.</p>
</li>
</ul>
<h3 id="heading-conhecendo-o-dio">Conhecendo o DIO</h3>
<p>DIO é um Cliente HTTP para Dart e Flutter que trás uma experiência simples e robusta para os nossos aplicativos multiplataforma. Possui suporte para interceptores e headers personalizados, cancelamento de requisições, tempo limite, e muito mais.</p>
<h3 id="heading-implementacao-do-aplicativo-de-games-usando-o-dio">Implementação do aplicativo de Games usando o DIO</h3>
<p>Nesse exemplo, vamos criar um app bem simples de listagem de games consumindo alguns dados que estão na API <a target="_blank" href="https://rawg.io/apidocs">RAWG</a>. 🔗</p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*_FrUBR1zCQei62M1iorzbA.png" alt="RAWG API" /></p>
<p>Crie uma conta e pegue sua <em>API Key</em> para conseguir buscar os dados.</p>
<p>A ideia aqui é mostrar como é facil fazer essa integração para ter um aplicativo consumindo dados da internet sem muito trabalho. </p>
<ol>
<li>Vamos começar adicionando a dependência ao nosso arquivo <strong><em>pubspec.yaml.</em></strong> </li>
</ol>
<p><em>No momento desse artigo o mesmo se encontra em sua versão mais nova</em> <strong><em>5</em>.6.0</strong></p>
<pre><code class="lang-bash">dependencies:
  dio: ^5.6.0
</code></pre>
<p>Ou instale o pacote a partir da linha de comando com o Flutter:</p>
<pre><code class="lang-bash">$ flutter pub add dio
</code></pre>
<p>3. Agora, no seu código Dart, você pode importar o package:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;
</code></pre>
<h3 id="heading-sobre-boas-praticas">Sobre Boas Práticas</h3>
<p>Quando nós vamos criar consumos de API geralmente é uma ótima prática usar o alguns design patterns como o <a target="_blank" href="https://en.wikipedia.org/wiki/Service_layer_pattern">Servi</a><a target="_blank" href="https://en.wikipedia.org/wiki/Service_layer_pattern">ce ou R</a><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design">eposito</a><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design">ry.</a> </p>
<p><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design">B</a><a target="_blank" href="https://en.wikipedia.org/wiki/Service_layer_pattern">asicame</a>nte ess<a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design">es padrões</a> consistem em criarmos uma classe separada somente com a finalidade de acessar e buscar os dados do meio ext<a target="_blank" href="https://en.wikipedia.org/wiki/Service_layer_pattern">erno is</a>so deix<a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design">a as coisa</a>s mais organizadas, e mais bem definidas ajudando até mesmo com a manutenção futuramente em nosso aplicativo.</p>
<p><strong>Service Pattern X Repository Pattern</strong></p>
<p><strong>Repositorios</strong> encapsulam a lógica necessária para acessar fontes de dados. Eles centralizam a funcionalidade comum de acesso a dados, oferecendo um nível adicional de abstração sobre o acesso a dados. Esse padrão é útil em situações em que o mecanismo de acesso aos dados podem mudar significativamente.</p>
<p>A finalidade da camada de <strong>serviço</strong>, por outro lado, é encapsular a lógica de negócios em um único local para promover a reutilização de código e a separação de interesses. Basicamente seria isolar uma tarefa específica em um outro objeto sendo assim assumindo uma responsabilidade muito estreita de realizar alguma atividade útil.</p>
<p>Nesse exemplo usaremos o padrão <strong>Repository</strong> 😉</p>
<h3 id="heading-criando-nosso-repository-para-consumir-dados-da-api">Criando Nosso Repository para consumir dados da API 🛠️</h3>
<p>Crie um repository chamado <strong><em>GamesRepository</em></strong> que vai conter a instância do <code>Dio</code> e métodos para fazer as requisições HTTP. </p>
<p>Veja o código completo abaixo: </p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GamesRepository</span> </span>{
  <span class="hljs-keyword">final</span> Dio dio;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> _apiKey = <span class="hljs-string">''</span>;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> _baseUrl = <span class="hljs-string">'https://api.rawg.io/api/games'</span>;

  GamesRepository(<span class="hljs-keyword">this</span>.dio);

  Future&lt;<span class="hljs-built_in">List</span>&lt;GameModel&gt;&gt; getGames() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> dio.<span class="hljs-keyword">get</span>(
        _baseUrl,
        queryParameters: {
          <span class="hljs-string">'key'</span>: _apiKey,
        },
      );

      <span class="hljs-keyword">if</span> (response.statusCode == <span class="hljs-number">200</span>) {
        <span class="hljs-keyword">return</span> (response.data[<span class="hljs-string">'results'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">List</span>)
            .map((game) =&gt; GameModel.fromJson(game))
            .toList();
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">'Erro ao obter games: Código <span class="hljs-subst">${response.statusCode}</span>'</span>);
      }
    } <span class="hljs-keyword">on</span> DioError <span class="hljs-keyword">catch</span> (dioError) {
      <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">'Erro ao fazer a requisição: <span class="hljs-subst">${dioError.message}</span>'</span>);
    }
  }
}
</code></pre>
<p>Se atente para <strong>API key</strong> onde você vai conseguir no site após realizar seu cadastro.</p>
<p>O principal objetivo do nosso repository é listar os games, convertendo os dados da API em modelos (<code>GameModel</code>) que podem ser usados no resto da aplicação.</p>
<p>O <code>GamesRepository</code> abstrai os detalhes de como os dados dos jogos são obtidos da API. Em vez de espalhar a lógica de requisição pela aplicação, ela fica centralizada no repositório.</p>
<p>Se você decidir mudar a fonte dos dados (por exemplo, mudar de uma API para um banco de dados local), você só precisaria alterar o repositório, sem impactar outras partes do código.</p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*v8O7DqTCgWny9L91jmVZCg.png" alt="Aplicativo de games rodando" /></p>
<p>Acima temos o aplicativo rodando e trazendo os dados com sucesso ✅</p>
<p>Para a gerência de estado eu usei o <a target="_blank" href="https://bloclibrary.dev/pt-br/">Bloc</a>, em um artigo futuro veremos sobre ele aqui também.</p>
<p>Aqui está o <a target="_blank" href="https://github.com/iang12/flutter_bloc_example">código</a> completo caso queria ver como ficou todo o aplicativo. 👨🏻‍💻</p>
<h3 id="heading-estrutura-basica-do-games-repository">Estrutura Básica do Games Repository</h3>
<ul>
<li><p><strong>Model (GameModel):</strong> Representa a estrutura dos dados que você está manipulando, neste caso, um jogo.</p>
</li>
<li><p><strong>Repository (GamesRepository):</strong> Contém a lógica de como obter, armazenar e manipular os dados (nesse caso, os jogos) de uma fonte externa, como uma API.</p>
</li>
</ul>
<h3 id="heading-vantagens-do-padrao-repository">Vantagens do Padrão Repository</h3>
<ul>
<li><p><strong>Modularidade:</strong> A lógica de acesso a dados é separada do restante da aplicação, facilitando a manutenção e evolução do código.</p>
</li>
<li><p><strong>Testabilidade:</strong> Como o <code>GamesRepository</code> é uma camada separada, você pode testá-lo isoladamente, simulando a resposta da API e verificando se o repositório lida com os dados e erros corretamente.</p>
</li>
<li><p><strong>Facilidade de Substituição:</strong> Se futuramente você quiser trocar a API que fornece os dados dos jogos, ou quiser implementar caching, você só precisa alterar o <code>GamesRepository</code>.</p>
</li>
</ul>
<h4 id="heading-referenciashttpswwwtodamateriacombrreferencias-abnt"><a target="_blank" href="https://www.todamateria.com.br/referencias-abnt/">Referências</a></h4>
<ul>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/5049363/difference-between-repository-and-service-layer/5049454#5049454">https://stackoverflow.com/questions/5049363/difference-between-repository-and-service-layer/5049454</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/22963352/difference-between-repository-and-service-layer">https://stackoverflow.com/questions/22963352/difference-between-repository-and-service-layer</a></p>
</li>
</ul>
<h3 id="heading-conclusao">Conclusão ✅</h3>
<p>Bom, eu particulamente acho muito simples consumir APIS com o Flutter, já vi e tentei em outras tecnologias de desenvolvimento móvel e a curva de aprendizado é bem maior rsrsr.</p>
<p>E para encerrar, uma dica valiosa, acredite em mim: envolva-se com a comunidade local de desenvolvedores. Aprenda com outros desenvolvedores: participar de eventos de tecnologia, palestrar e contribuir com conteúdos pode expô-lo a uma variedade de ideias, tecnologias e abordagens diferentes.</p>
<p>Isso pode enriquecer seu conhecimento e ampliar sua perspectiva sobre a indústria de desenvolvimento de software.</p>
<p>Conheça novas pessoas e faça networking nos eventos, pois isso pode abrir portas para novos contatos e oportunidades valiosas em sua carreira.</p>
<p>Obrigado por ler até aqui. 😁</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre desenvolvimento móvel 📲 🚀</p>
<h3 id="heading-minhas-redes-sociais">🌐 Minhas redes sociais 🌐</h3>
<p><a target="_blank" href="https://www.github.com/iang12">GitHub</a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/">LinkedIn</a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/">Instagram</a> | <a target="_blank" href="https://x.com/ianoliveirag12">X (Twitter)</a> | <a target="_blank" href="https://medium.com/@ianoliveirag12">Medium</a></p>
]]></content:encoded></item><item><title><![CDATA[O Caminho das Pedras para Aprender Flutter: O guia definitivo para Iniciantes]]></title><description><![CDATA[Nos últimos anos, o Flutter emergiu como uma das ferramentas mais poderosas e versáteis para o desenvolvimento de aplicativos móveis. Desenvolvido pelo Google, essa ferramenta de código aberto permite criar interfaces de usuário nativas e impressiona...]]></description><link>https://ianoliveira.dev/o-caminho-das-pedras-para-aprender-flutter-o-guia-definitivo-para-iniciantes</link><guid isPermaLink="true">https://ianoliveira.dev/o-caminho-das-pedras-para-aprender-flutter-o-guia-definitivo-para-iniciantes</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[Dart]]></category><category><![CDATA[learning]]></category><category><![CDATA[Flutter Examples]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 19 Aug 2024 14:46:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719019651023/eb643630-40ed-4744-858f-9de768e8e363.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nos últimos anos, o Flutter emergiu como uma das ferramentas mais poderosas e versáteis para o desenvolvimento de aplicativos móveis. Desenvolvido pelo Google, essa ferramenta de código aberto permite criar interfaces de usuário nativas e impressionantes para iOS e Android a partir de uma única base de código.</p>
<p>Você já se perguntou: "<strong>Por onde começar?</strong> <strong>Qual o melhor caminho?</strong> <strong>Quais as melhores dicas?</strong>" Essas são perguntas frequentes em eventos e nas redes sociais. Decidi escrever este guia para ajudar você a encontrar as respostas e trilhar o caminho do aprendizado dessa ferramenta incrível.</p>
<p>Hoje, vamos trilhar juntos o caminho das pedras para aprender o Flutter. Aqui, você encontrará dicas essenciais que irão descomplicar sua jornada, ajudando a transformar ideias em aplicativos funcionais e atraentes.</p>
<p>Seja você um desenvolvedor experiente em busca de uma nova habilidade ou um completo novato no mundo da programação, este artigo oferece o suporte necessário para dar seus primeiros passos com o Flutter além de também complementar um outro post que fiz com o tema "<a target="_blank" href="https://ianoliveira.hashnode.dev/como-se-tornar-um-desenvolvedor-mobile-flutter">como se</a> <a target="_blank" href="https://ianoliveira.hashnode.dev/como-se-tornar-um-desenvolvedor-mobile-flutter">tornar um desenvolvedor Flutter.</a>"</p>
<p>Prepare-se para descobrir as melhores práticas, recursos indispensáveis e truques úteis que farão toda a diferença no seu aprendizado. Vamos embarcar nesta jornada rumo ao domínio do Flutter e explorar todo o <a target="_blank" href="https://ianoliveira.hashnode.dev/como-se-tornar-um-desenvolvedor-mobile-flutter">potencial que essa incrível ferram</a>enta tem a oferecer. Pronto para começar? Então, vamos nessa!</p>
<h1 id="heading-aprendendo-como-desenvolvedor-de-software"><strong>Aprendendo como desenvolvedor de software</strong> 📚</h1>
<p>Existem várias maneiras de consumir conhecimento como desenvolvedor de software. Dentre elas, <strong>Lendo Documentação,</strong> <strong>Posts de Blog, Livros, Desenvolvendo Projetos Paralelos (Side Projects),</strong> <strong>Cursos/Workshops, Escrevendo e Ensinando.</strong></p>
<p>O ponto chave aqui é tente descobrir o que funciona para você, qual a melhor forma que você aprende e absorve o conhecimento? Depois que descobrir isso é preciso trabalhar de forma inteligente e abordar o aprendizado de forma estratégica.</p>
<p>Forme bons hábitos. Ao fazer algo regularmente no mesmo horário, seu corpo e mente se acostumarão, e você perceberá que precisará de menos energia mental para completar as tarefas.</p>
<p>Depois de formar o hábito de estudar você vai perceber que o aprendizado vai se tornar simples e gostoso!</p>
<p>Por exemplo, eu gosto mais de aprender lendo posts de blog e fazendo pequenos projetos de estudo, onde sou forçado a pesquisar e procurar na web até conseguir o que quero fazer. Dessa forma, vou aprendendo! 💡</p>
<p>Tento encaixar isso nos meus hábitos até se tornar uma rotina estudar alguma tecnologia nova!</p>
<p>Por exemplo, se você almoça quase no mesmo horário todos os dias: 👇🏻</p>
<blockquote>
<p><strong><em>Depois de jantar todos os dias, vou praticar programação por 45 minutos, focado. 🎧 👨🏻‍💻</em></strong></p>
</blockquote>
<p>Eu sei que não é fácil formar hábitos de estudo, mas com esforço e dedicação você vai conseguir. Eu acredito em você! 🙏🏻</p>
<h1 id="heading-por-que-flutter"><strong>Por que Flutter?</strong></h1>
<p>Com o mundo se tornando cada vez mais dependente de dispositivos móveis, há uma grande demanda por novos desenvolvedores capazes de criar e manter aplicativos com qualidade.</p>
<p>Além disso, essa habilidade permite que você implemente suas próprias ideias de apps, e quem sabe, seu <a target="_blank" href="https://www.techtudo.com.br/stories/2022/04/26/alem-do-twitter-6-apps-que-foram-vendidos-por-cifras-de-milhoes.ghtml">aplicativo</a> poderá se tornar o próximo negócio de 1 bilhão de dólares.</p>
<p>Hoje em dia, existem diversas ferramentas que permitem o desenvolvimento de aplicativos para dispositivos móveis. Hoje, vamos focar no Flutter, que se destaca como uma das ferramentas mais populares no desenvolvimento mobile.</p>
<p>O Flutter transforma o processo de criação de aplicativos, permitindo que você entregue mais rápido e com qualidade.</p>
<p>Nesse <a target="_blank" href="https://medium.com/flutterando/iniciando-carreira-no-desenvolvimento-mobile-escolho-nativo-ou-flutter-de1fe8124604">link</a> de outro artigo, vou citar alguns motivos pelos quais você deveria considerar iniciar sua carreira como desenvolvedor mobile usando Flutter. 💙</p>
<h1 id="heading-o-que-e-flutter"><strong>O que é Flutter?</strong></h1>
<p>Flutter é um kit de ferramentas (SDK) de interface de usuário e de código aberto criado pela Google em 2015, sendo lançado oficialmente em <a target="_blank" href="https://www.youtube.com/watch?v=kpcjBD1XDwU">2018.</a></p>
<p>Com ele, é possível criar diferentes aplicativos bonitos e multiplataformas (Android, iOS, web e desktop) usando a linguagem de programação <a target="_blank" href="https://dart.dev/">Dart</a> e uma única base de código, ou seja, sem precisar escrever o código separadamente para cada sistema ou plataforma.</p>
<p>Seu forte atrativo está baseado em alguns pilares: <strong>(a) Desenvolvimento Rápido, (b) UI Expressiva e Flexível e (c) Desempenho Nativo. (d) Multiplataforma</strong> etc. 🤙</p>
<p>Se quiser entender um pouco mais desses pilares visite meu outro <a target="_blank" href="https://blog.flutterando.com.br/como-se-tornar-um-desenvolvedor-mobile-flutter-7ee130bfc45">artigo</a> onde explico com detalhes cada um deles e também mais algumas dicas.</p>
<p><strong><mark>🛑 ‼️ Atenção!!!</mark></strong> <mark>Se você é totalmente novo na programação não aprenda Flutter agora, comece pelos cursos abaixo iniciando por algoritmos, caso contrário siga em frente.</mark></p>
<p>1 - <a target="_blank" href="https://www.youtube.com/watch?v=S9uPNppGsGo&amp;t=3s">Introdução a Algoritmos — Curso de</a> <a target="_blank" href="https://www.youtube.com/watch?v=8mei6uVttho&amp;list=PLHz_AreHm4dmSj0MHol_aoNYCSGFqvfXV">Algoritmos #01 — Gustavo Guanabara</a></p>
<p>2 - <a target="_blank" href="https://www.youtube.com/watch?v=S9uPNppGsGo&amp;t=3s">Curso Python #01 — Seja um Programador</a></p>
<h3 id="heading-iniciando-os-estudos-com-a-linguagem-dart"><strong>Iniciando os estudos com a linguagem Dart</strong></h3>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*7GSIZ07ZOipVEO3EAQHH2g.png" alt /></p>
<p>Não pule diretamente para o Flutter sem conhecer o Dart! Além de ser a linguagem principal do Flutter, o Dart está rapidamente ganhando popularidade, sendo amplamente utilizado na criação de aplicativos web, códigos de servidor e aplicativos de IoT (Internet das Coisas).</p>
<p>Dart é uma linguagem moderna e poderosa, orientada a objetos, que pode ser compilada para código nativo. Ele possui um <a target="_blank" href="https://dart.dev/overview">compilador</a> Ahead-Of-Time (AOT) e Just-In-Time (JIT).</p>
<p>O Dart é uma linguagem relativamente fácil de aprender, principalmente se você já tiver experiência prévia com outras linguagens de programação. Há muitos materiais disponíveis e gratuitos na internet para você começar.</p>
<p>Abaixo, deixo alguns links de conteúdos que considero bons. 📚</p>
<p><strong>Documentação oficial do Dart:</strong></p>
<p>A <a target="_blank" href="https://dart.dev/guides">documentação</a> oficial do Dart é um excelente recurso para aprender a linguagem. Ela contém guias detalhados, tutoriais e exemplos de código que cobrem os conceitos fundamentais e avançados do Dart. Inicialmente, vale a pena focar nos dois principais recursos: “<a target="_blank" href="https://dart.dev/language">Language Tour</a>” e “<a target="_blank" href="https://dart.dev/guides/libraries/library-tour">Language samples</a>”.</p>
<p>Eles fornecem uma breve introdução baseada em exemplos da linguagem Dart, o que pode ser de grande ajuda para iniciantes. Além disso, a documentação oficial do Dart possui o recurso chamado <a target="_blank" href="https://dart.dev/#try-dart">DartPad</a>, uma espécie de editor de código online onde você pode ver e executar exemplos de código Dart, o que pode ser muito útil para praticar.</p>
<p><strong>Conceitos fundamentais da linguagem:</strong></p>
<p>Abaixo, listo alguns conceitos fundamentais da linguagem Dart que você tem que aprender: 🔥</p>
<ul>
<li><p><a target="_blank" href="https://pt.linkedin.com/pulse/programa%C3%A7%C3%A3o-orientada-objetos-gabriela-pereira-dos-santos"><strong>Fundamentos do POO</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language/built-in-types"><strong>Tipos de dados</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language/variables"><strong>Variáveis e constantes</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language#control-flow-statements"><strong>Estruturas condicionais</strong></a></p>
</li>
<li><p><strong>Estruturas de repetição</strong></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language/functions"><strong>Funções</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language/classes"><strong>Classes e objetos</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language/error-handling"><strong>Exceções e erros</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dart.dev/language#exceptions"><strong>Programação assíncrona</strong></a></p>
</li>
<li><p><a target="_blank" href="https://dev.to/rrafush/entendendo-o-null-safety-437k"><strong>Null Safety</strong></a></p>
</li>
<li><p><a target="_blank" href="https://docs.flutter.dev/packages-and-plugins/using-packages"><strong>Bibliotecas e pacotes</strong></a></p>
</li>
</ul>
<p><strong>Recursos – Cursos de Dart no Youtube</strong></p>
<p>Se você gosta de aprender por cursos online, abaixo deixo 3 boas playlist de cursos para você aprender Dart 🎯.</p>
<p>Assista os 3 ou apenas o que desejar. 👇🏻</p>
<p>1 - <a target="_blank" href="https://www.youtube.com/watch?v=PgRv_aeqf-4&amp;list=PLRpTFz5_57cseSiszvssXO7HKVzOsrI77">Curso de Dart - <strong>Deivid Willyan</strong></a></p>
<p>2 - <a target="_blank" href="https://www.youtube.com/watch?v=Q-n2XtKTnmg&amp;list=PL5EmR7zuTn_bhzkvSNve2RQ8KLw79Mj6z">Curso de Dart - Daves Tecnologia</a></p>
<p>3 - <a target="_blank" href="https://www.youtube.com/watch?v=Vz11rFFewkM&amp;list=PLK5FPzMuRKlyiWZUUqea2Hmszhy9vUixJ"><strong>Dart - Curso Completo -</strong></a> <a target="_blank" href="https://www.youtube.com/watch?v=Vz11rFFewkM&amp;list=PLK5FPzMuRKlyiWZUUqea2Hmszhy9vUixJ"><strong>Washington Developer</strong></a></p>
<p><mark>Aqui vai uma dica: Lembre-se de que “a prática leva à perfeição”, portanto, nenhum curso, leitura de documentação ou visualização de vídeos de tutoriais será útil se você não codificar e aprender com seus erros.</mark></p>
<p><mark>É importante praticar e aplicar o conhecimento em projetos pessoais para solidificar o aprendizado. 🫡</mark></p>
<h3 id="heading-iniciando-os-estudos-com-flutter"><strong>Iniciando os Estudos com Flutter</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724064909875/259104ed-93b9-4c31-8ee6-63fbc18fae28.png" alt class="image--center mx-auto" /></p>
<p>Depois de dominar a linguagem Dart, você pode começar com o Flutter instalando o SDK dele no seu computador e configurando todo o ambiente de desenvolvimento para dar os primeiros passos. Todo o processo é descrito <a target="_blank" href="https://docs.flutter.dev/get-started/install">aqui</a>.</p>
<p>Quanto às IDEs, você pode escolher usar o <em>Android Studio</em> ou o <strong>Visual Studio Code</strong>. Eu particularmente gosto do Visual Studio Code por ser mais leve e simples de usar.</p>
<p><mark>Você não sabe por quê o Flutter usa o Dart como linguagem?</mark> <a target="_blank" href="https://www.youtube.com/watch?v=5F-6n_2XWR8">veja esse video</a> 🔗</p>
<p>Abaixo, listo alguns conceitos fundamentais do Flutter que você deve aprender: 💙</p>
<p><a target="_blank" href="https://docs.flutter.dev/development/ui/widgets"><strong>Widgets</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/development/ui/layout"><strong>Layouts</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/ui/adaptive-responsive">Responsividade</a></p>
<p><a target="_blank" href="https://docs.flutter.dev/cookbook/forms"><strong>Formulários</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/development/ui/animations"><strong>Animações</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/development/ui/navigation"><strong>Navegação e rotas</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/development/data-and-backend/state-mgmt/intro"><strong>Gestão do estado</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/cookbook/persistence/sqlite"><strong>Conceitos de banco de dados</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/cookbook/networking/fetch-data"><strong>Consumos de API REST</strong></a></p>
<p><a target="_blank" href="https://www.geeksforgeeks.org/how-to-choose-the-right-architecture-pattern-for-your-flutter-app/"><strong>Arquitetura de software</strong></a></p>
<p><a target="_blank" href="https://refactoring.guru/design-patterns"><strong>Design patterns</strong></a></p>
<p><a target="_blank" href="https://docs.flutter.dev/testing"><strong>Testes automatizados</strong></a></p>
<h3 id="heading-dicas"><strong>Dicas ⚡️</strong></h3>
<p><strong><mark>Praticando Programação: </mark></strong> <mark>🛠️</mark></p>
<p>Comece a desenvolver aplicativos simples no Flutter para colocar em prática o que você aprendeu. Inicie com projetos básicos como listar dados na tela ou codificar uma simples interface, e a medida que você ganha mais confiança, aumente a complexidade dos projetos, incorporando novos conceitos como navegação, gerenciamento de estados e integrações com APIs.</p>
<p>A prática contínua é essencial para consolidar seu conhecimento.</p>
<p>Nesse <a target="_blank" href="https://www.youtube.com/shorts/ED8suVYARgU">video</a> eu dou 6 sugestões de APIS para você consumir.</p>
<p><strong><mark>Crie Projetos do Mundo Real: </mark></strong> <mark>👨🏻‍💻</mark></p>
<p>Aplique seu conhecimento resolvendo problemas do dia a dia com a criação de novos aplicativos. Identifique uma necessidade real e desenvolva um aplicativo para isso. Trabalhar em projetos do mundo real não só solidifica suas habilidades, mas também oferece uma visão valiosa sobre os desafios e as melhores práticas de desenvolvimento.</p>
<p>Recentemente desenvolvi um <a target="_blank" href="https://play.google.com/store/apps/details?id=com.radardoroubo.br.radar_do_roubo&amp;hl=pt">Aplicativo</a> para mapear ocorrências de Furtos e Roubos nas grandes cidades, uma ideia simples mas que virou uma aplicativo real e que resolve um problema.</p>
<h3 id="heading-recursos-onde-aprender-flutter"><strong>Recursos — Onde Aprender Flutter?</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724064828655/82a56ac4-a27e-45d6-8ded-644a72b66893.png" alt class="image--center mx-auto" /></p>
<p>Existem vários recursos gratuitos em português para aprender Flutter. Abaixo, vou listar alguns que sei que são bons e também compartilhar links de alguns roadmaps estruturados de conteúdos em Flutter que podem auxiliar no seu aprendizado.</p>
<p><strong>Recursos – Cursos de Flutter no Youtube</strong></p>
<p>Se você gosta de aprender por meio de cursos online, abaixo deixo 3 boas playlists de cursos para você aprender Flutter.</p>
<p>1 - <a target="_blank" href="https://www.youtube.com/watch?v=1UY4LLob0iQ&amp;list=PL5EmR7zuTn_Yu_YV2pT0h0843vRGiTMtx">Curso completo de Flutter 3</a> - Daves Tecnologia</p>
<p>2 - <a target="_blank" href="https://www.youtube.com/watch?v=2NQUjHZZ9t8&amp;list=PLqdwHeoSjEN-9aGd-RxaS_2cyD_AKT0c_&amp;index=1">Curso de Flutter &amp; Dart</a> - Polimofirsmo</p>
<p>3 - <a target="_blank" href="https://www.youtube.com/watch?v=XeUiJJN0vsE&amp;list=PLlBnICoI-g-d-J57QIz6Tx5xtUDGQdBFB">Curso de Flutter</a> - Flutterando</p>
<p>4 - <a target="_blank" href="https://www.youtube.com/@flutterdev">Canal do Flutter oficial</a> - Inglês</p>
<p>5 - <a target="_blank" href="https://www.youtube.com/watch?v=8sAyPDLorek&amp;t=2769s">Building your first Flutter App 1— with a Codelab!</a> - Inglês</p>
<p><strong>Recursos escritos - Tutoriais em blogs e sites ✍🏻</strong></p>
<p>Bom, o próprio site do Flutter tem uma especie de roadmap com uma listagem conteúdos para o níveis Junior, Pleno e Senior. Apesar de tudo estar em inglês você pode usar o Google translate para entender melhor os materiais escritos.</p>
<p><a target="_blank" href="https://flutter.dev/learn">Acesse aqui.</a> 🔗</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724064157633/1d0eedd1-4b29-498e-bf8e-d97f8e9c1168.png" alt class="image--center mx-auto" /></p>
<p>1 <a target="_blank" href="https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=pt-br#0">- Desenvolvendo seu primeiro app em Flutter</a> 🔗</p>
<p><mark>OBS: É importante lembrar de praticar o que foi aprendido por meio de projetos reais e experimentar diferentes recursos do Flutter é fundamental para ganhar familiaridade com o framework.</mark></p>
<h3 id="heading-roadmap-estruturado-para-estudo">Roadmap estruturado para estudo 📆</h3>
<p>Navegando no LinkedIn um dia desses, vi uma publicação em que um cara chamado Dinesh compartilhou uma foto de um roadmap com temas do mundo Flutter organizados de forma estruturada. Achei interessante e vou compartilhá-lo <a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">aq</a><a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">ui.</a></p>
<p><a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa"><strong>Link do Roa</strong></a><a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa"><strong>dmap 🔗</strong></a></p>
<p>Criei um segundo roadmap pessoal com uma listinha de conteúdos organizados por semana em um PDF do que estudar, vou deixar o link abaixo:</p>
<p><a target="_blank" href="https://docs.google.com/document/d/10MLUOyRukh_MGcN-DeG5H8YjHsWj80ayeSR_ijJ53Hg/edit?usp=sharing"><strong>Link do PDF criado</strong></a> <a target="_blank" href="https://docs.google.com/document/d/10MLUOyRukh_MGcN-DeG5H8YjHsWj80ayeSR_ijJ53Hg/edit?usp=sharing"><strong>por mim 🔗 ⚡️</strong></a></p>
<h1 id="heading-dicas-de-projetos-para-praticar"><strong>Dicas de projetos para praticar 🛠️</strong></h1>
<p><a target="_blank" href="https://docs.google.com/document/d/10MLUOyRukh_MGcN-DeG5H8YjHsWj80ayeSR_ijJ53Hg/edit?usp=sharing">Para compl</a>ementar seu aprendiza<a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">do,</a> aqui estão a<a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">lguns projetos</a> de di<a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">ferentes níveis</a> de complexidade nos quais você pode criar para praticar Flutter.</p>
<ol>
<li><p>Aplicativo de lista de tarefas com arma<a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">zena</a>mento local/<a target="_blank" href="https://www.linkedin.com/posts/dineshsowndar_flutter-roadmap-activity-6791000401727647744-TdIa">em nuvem</a></p>
</li>
<li><p>Aplicativo de notícias (<a target="_blank" href="https://newsapi.org/">News API</a>)</p>
</li>
<li><p>Aplicativo de filmes (<a target="_blank" href="https://developer.themoviedb.org/reference/intro/getting-started">TMDB API</a>)</p>
</li>
<li><p>Aplicativo de clima (<a target="_blank" href="https://openweathermap.org/api"><strong>Weather API</strong></a>)</p>
</li>
<li><p>Aplicativo de Notas (<a target="_blank" href="https://medium.com/flutterando/s%C3%A9rie-dominando-o-firebase-em-aplicativos-flutter-f379b98d29fb">Firebase</a>)</p>
</li>
</ol>
<p>Realize ess<a target="_blank" href="https://docs.google.com/document/d/10MLUOyRukh_MGcN-DeG5H8YjHsWj80ayeSR_ijJ53Hg/edit?usp=sharing">es projetos para aplicar s</a>eu conhecimento, aprimorar suas habilidades e ganhar experiência prática no desenvolvimento de aplicativos Flutter.</p>
<p>Desejo a você boa sorte em sua jornada para se tornar um desenvolvedor de aplicativos Flutter, e qualquer dúvida me chama ou comenta ai em baixo, Ok? 😉</p>
<h1 id="heading-conclusao"><strong>Conclusão ✅</strong></h1>
<p>Uma coisa que eu sempre digo é que a curva de aprendizado para criar bons aplicativos ficou consideravelmente reduzida com o Flutter. Não digo que seja fácil, mas as tecnologias nativas têm uma curva de aprendizado muito mais íngreme em comparação ao Flutter.</p>
<p>E para encerrar, mais uma dica valiosa, acredite em mim: envolva-se com a comunidade local de desenvolvedores. Aprenda com outros desenvolvedores: participar de eventos de tecnologia, palestrar e contribuir com conteúdos pode expô-lo a uma variedade de ideias, tecnologias e abordagens diferentes.</p>
<p>Isso pode enriquecer seu conhecimento e ampliar sua perspectiva sobre a indústria de desenvolvimento de software.</p>
<p>Conheça novas pessoas e faça networking nos eventos, pois isso pode abrir portas para novos contatos e oportunidades valiosas em sua carreira.</p>
<p>Obrigado por ler até aqui. 😁</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição me manda uma DM ou deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos sobre desenvolvimento móvel 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12">GitHub</a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/">LinkedIn</a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/">Instagram</a> | <a target="_blank" href="https://x.com/ianoliveirag12">X (Twitter)</a> | <a target="_blank" href="https://medium.com/@ianoliveirag12">Medium</a></p>
]]></content:encoded></item><item><title><![CDATA[Publicando um aplicativo Flutter na Apple Store em 7 passos]]></title><description><![CDATA[Fala, Flutter devs! Tudo bem? Hoje vamos aprender como publicar o seu aplicativo Flutter na loja de aplicativos da Apple!
Um pouco de contexto: Eu desenvolvi um aplicativo de adoção de animais para o meu TCC da pós-graduação e agora estou prestes a p...]]></description><link>https://ianoliveira.dev/publicando-um-aplicativo-flutter-na-apple-store-em-7-passos</link><guid isPermaLink="true">https://ianoliveira.dev/publicando-um-aplicativo-flutter-na-apple-store-em-7-passos</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Apple]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[ios app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 22 Jul 2024 10:32:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721597760078/79326dc0-fec5-4439-a31c-dc6c81a42c27.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, Flutter devs! Tudo bem? Hoje vamos aprender como publicar o seu aplicativo Flutter na loja de aplicativos da Apple!</p>
<p>Um pouco de contexto: Eu desenvolvi um aplicativo de adoção de animais para o meu TCC da pós-graduação e agora estou prestes a publicá-lo na loja de aplicativos. Achei que seria interessante documentar todo o processo de submissão para ajudar vocês quando forem passar por isso também! Vamos juntos nessa jornada! 🚀</p>
<p>A maravilha do Flutter é que ele é <a target="_blank" href="https://flutter.dev/multi-platform"><strong>multiplataforma</strong></a>, ou seja, está disponível para várias plataformas, como Android, iOS, sistemas desktop e também web, tudo com apenas um único código.</p>
<p>Ao longo do artigo vou mostrar em algumas etapas como enviar o aplicativo que desenvolvi para a loja!</p>
<p>Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-requisitos-basicos-para-publicar-seu-aplicativo-na-app-store">Requisitos Básicos para Publicar seu Aplicativo na App Store</h3>
<ol>
<li><p><strong>Um Macbook com o Xcode instalado:</strong> O Xcode é necessário para construir e lançar seu aplicativo, pois algumas configurações importantes do app são feitas através dele.</p>
</li>
<li><p><strong>Uma conta de desenvolvedor Apple:</strong> Você precisa adquirir uma licença do <a target="_blank" href="https://developer.apple.com/programs/enroll/">A<strong>pple Developer Program</strong></a> para acessar o painel e as ferramentas de publicação da Apple. Essa licença custa $100 dólares, o que, dependendo da cotação do dólar, pode ficar em torno de R$550 reais.</p>
<p> Quando eu comprei a minha, após fazer o pedido e enviar os dados, levou em torno de uma semana para aprovação e liberação da licença.</p>
<h4 id="heading-dica-importante">Dica Importante:</h4>
<p> Use um cartão de crédito físico ao invés de virtual. Ouvi relatos de que com o cartão virtual estava dando problemas. Para garantir, usei o cartão físico e deu tudo certo. 😎</p>
</li>
</ol>
<h3 id="heading-1-registre-seu-bundle-id-no-portal-do-desenvolvedor"><strong>1 - Registre seu Bundle ID no portal do desenvolvedor</strong></h3>
<p><strong>Bundle ID é um identificador exclusivo associado a aplicativos iOS</strong>. Os proprietários de aplicativos definem esse ID. A Apple recomenda que os proprietários de aplicativos nomeiem o ID usando uma notação reversa de nome de domínio. Como por exemplo:</p>
<p>Domain: mycompany.com</p>
<p><strong>Reverse domain</strong>: com.mycompany.appname.</p>
<p><strong>Bundle ID:</strong> com.mycompany.myapp</p>
<p>Agora que vc já sabe o que é o Bundle ID, vamos prosseguir acessando o <a target="_blank" href="https://developer.apple.com/account">site</a> (<a target="_blank" href="https://developer.apple.com/">https://developer.apple.com</a>) clique em <strong>Identifiers</strong> (Identificadores).</p>
<p>Veja a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720990604108/8c640199-2989-48ce-bde1-7d05c92870b0.png" alt class="image--center mx-auto" /></p>
<p>Depois na próxima página clique no icone de <strong><em>+</em></strong> para criar um novo <strong><em>Bundle ID</em>.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720991320587/1f4664e5-6b98-4e2e-9dd0-058240ad997b.png" alt class="image--center mx-auto" /></p>
<p>Agora prosseguindo vamos selecionar <strong>Apps IDS como na imagem a</strong>baixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720990738347/10294f83-3fa4-4064-b783-61bb97adf0d3.png" alt class="image--center mx-auto" /></p>
<p>Selecione o tipo <strong>App</strong> que aparecerá logo em seguida após a aba anterior. Veja a imagem abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720990811142/b3714bb8-3c5b-44a5-b4de-658beed1b5f9.png" alt class="image--center mx-auto" /></p>
<p>O Bundle ID deve ser exclusivo para a app store. Se você selecionar um existente, um pop-up de aviso solicitará que você o altere.</p>
<p>Selecione os recursos e serviços que correspondem aos do seu aplicativo.</p>
<p>Insira o seu <strong>Bundle ID</strong> e a descrição sem caracteres especiais.</p>
<p>Mais embaixo selecione tambem quais <strong>Capabilities</strong> o seu app usa no meu caso selecionei <strong><em>push notifications</em></strong> pois o meu aplicativo recebe notificacões do Firebase.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720991694173/86931e29-4d9e-4737-9f22-cd2e30c1d120.png" alt class="image--center mx-auto" /></p>
<p>Prossiga e clique em registrar! ✅</p>
<h3 id="heading-2-criando-o-aplicativo-na-loja"><strong>2 - Criando o aplicativo na Loja</strong></h3>
<p>Agora vamos criar o nosso aplicativo no portal, vá na página inicial do portal do apple developer e clique em <strong>Apps</strong>, vai aparecer um botão para adicionar um novo aplicativo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720991878570/2c8e5f88-30d4-4aca-b2c3-d8ed79d06bd6.png" alt class="image--center mx-auto" /></p>
<p>Preencha os dados do seu aplicativo. Veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720992166931/b1c35442-3d38-4a20-b7ac-ff380dbc7088.png" alt class="image--center mx-auto" /></p>
<p>Clicando em criar podemos ver que o aplicativo foi criado com sucesso e registrado no portal do desenvolvedor da Apple.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720992434502/8fed8c7e-1d97-4734-91f0-06e18cd32c1b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-3-revise-as-configuracoes-do-seu-projeto-no-xcode"><strong>3 - Revise as configurações do seu projeto no Xcode</strong></h3>
<p>Verifique as configurações mais importantes. Como <strong>Nome do aplicativo</strong>, <strong>Bundle Identifie</strong>r e o <strong>Team</strong> que é a equipe associada à sua conta Apple Developer registrada. Se necessário, selecione <strong>Adicionar conta</strong> e atualize esta configuração.</p>
<p>Em <strong>iOS Deployment Target</strong> a versão mínima do iOS que seu aplicativo suporta. O Flutter suporta iOS 12 e versões posteriores. A guia Geral das configurações do seu projeto deve ser semelhante à seguinte:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720992734855/97d7b02e-1159-40cc-93af-fe5262a43ac5.png" alt class="image--center mx-auto" /></p>
<p><strong>Agora vamos em Signing e Capabilities</strong></p>
<p>Confira o Team e o Bundle Identifier se esta correto. Deixe marcado a opção (<strong><em>Automatically manage signing</em></strong>) para o Xcode criar o perfil de provisionamento automaticamente, que é um arquivo que contém informações necessárias para que um aplicativo iOS possa ser instalado e executado em dispositivos Apple.</p>
<p>Ele vincula seu dispositivo a seu aplicativo, permitindo que você teste e distribua seu aplicativo em dispositivos físicos.</p>
<p>No meu caso deu um erro, veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720993207497/ddfd8d3c-99a9-4a35-b68f-47cbd96e311c.png" alt class="image--center mx-auto" /></p>
<p>Ele diz que não temos um device (iPhone) registrado na nossa conta, para resolver esse erro devemos adicionar um dispositivo iPhone no portal do desenvolvedor apple.</p>
<p>Voce pode plugar seu iPhone no macbook e tentar novamente e irá aparecer um botão para registrar automaticamente, veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721044429982/859ec991-73d7-4235-b554-26e04dcf53aa.png" alt class="image--center mx-auto" /></p>
<p>Quando eu cliquei em registrar deu tudo certo. Foi automático!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721044761242/c4440809-6583-4620-8b95-3ccda6f78ae3.png" alt class="image--center mx-auto" /></p>
<p>Outra forma seria acessando o site do portal do desenvolvedor e registrar manualmente, <a target="_blank" href="https://developer.apple.com/account">acesse</a> e clique em <strong>dispositivos</strong> (devices).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721044056407/06fa5d85-6e87-4640-a764-1fb51568fd4e.png" alt class="image--center mx-auto" /></p>
<p>Agora clique para adicionar um novo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721044133494/5346eb3c-3fb5-49af-800f-e9c7954c1013.png" alt class="image--center mx-auto" /></p>
<p>Preecha os dados requeridos e principalmente com o seu Device ID (<a target="_blank" href="https://udid.tech/what-is-udid">UDID</a>) e pronto.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721044249288/80bc0cbd-d5cb-4286-96eb-ca64b2723786.png" alt class="image--center mx-auto" /></p>
<p><strong>Encontrando seu UDID com Finder (macOS)</strong></p>
<p>Plugue seu iPhone no seu mac e navegue até o Finder e selecione-o, você verá algumas informações sobre o celular conectado. Para mim tive que clicar algumas vezes nos dados abaixo do nome do iPhone para mostrar o UDID com sucesso!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713958906414/149704e4-524d-47bc-869a-fc1bc19174a6.png?auto=compress,format&amp;format=webp" alt="Finder" /></p>
<p><strong>Maneira alternativa de encontrar UDID com o Xcode</strong></p>
<ul>
<li><p>Conecte seu dispositivo iOS ao Xcode</p>
</li>
<li><p>Abra o menu <strong>Janela</strong> &gt; <strong>Dispositivos e Simuladores</strong></p>
</li>
<li><p>Encontre o seu dispositivo exibido nesta lista e visualize-o no <strong>Identifier</strong> “identificador” que é o mesmo <strong>UDID.</strong></p>
</li>
</ul>
<p>Depois de inserir com sucesso <em>o UUID</em> e o nome, continue o processo. Em seguida, <em>aceite</em> e <em>registre</em> o dispositivo.</p>
<h3 id="heading-4-adicionando-o-icone-ao-seu-aplicativo"><strong>4 -</strong> Adicionando o Ícone ao Seu Aplicativo</h3>
<p>Existem várias formas de adicionar o ícone ao seu aplicativo, mas hoje vou mostrar uma maneira bem prática utilizando um site chamado <a target="_blank" href="https://appicon.co/">Appicon.</a> Este site permite que você cole sua imagem e ele gera os arquivos de ícone tanto para Android quanto para iOS.</p>
<h4 id="heading-passos-para-gerar-icones-com-o-appicon">Passos para gerar ícones com o Appicon:</h4>
<ol>
<li><p>Acesse o site <a target="_blank" href="https://appicon.co/">Appicon</a>.</p>
</li>
<li><p>Faça o upload da sua imagem.</p>
</li>
<li><p>O site gerará automaticamente os arquivos necessários para ambas as plataformas.</p>
</li>
<li><p>Baixe os arquivos e adicione-os ao seu projeto.</p>
</li>
</ol>
<h4 id="heading-dica-importante-1">Dica Importante 💡</h4>
<p>Se tiver dúvidas sobre as diretrizes de ícones, é sempre bom revisar as guidelines específicas da Apple para garantir que seu ícone esteja em conformidade com os padrões. Você pode encontrar as diretrizes da Apple <a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/app-icons/">aqui</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721042633709/491bafc3-fb52-4ad4-a58c-a4e6530a2100.png" alt class="image--center mx-auto" /></p>
<p>Depois de gerado baixe os arquivos e cole na pasta <code>Assets.xcassets</code> dentro da <code>Runner</code> substituindo os icones do Flutter gerados na criação do projeto pelos novos.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721042888910/32f9d46b-b898-469b-b228-b4d631fb9039.png" alt class="image--center mx-auto" /></p>
<p>Feito isso, verifique se o ícone foi substituído executando seu aplicativo usando <strong>flutter run</strong> ⚡️</p>
<h3 id="heading-5-atualize-os-numeros-de-compilacao-e-versao-do-aplicativo">5 - Atualize os números de compilação e versão do aplicativo</h3>
<p>O número da versão padrão do aplicativo é <code>1.0.0</code>. Para a<a target="_blank" href="https://docs.flutter.dev/deployment/ios#update-the-apps-build-and-version-numbers">t</a>ua<a target="_blank" href="https://docs.flutter.dev/deployment/ios#update-the-apps-build-and-version-numbers">l</a>izá-lo, navegue até o arquivo <code>pubspec.yaml</code> e atualize a seguinte linha:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-number">1.0</span><span class="hljs-number">.0</span><span class="hljs-string">+1</span>
</code></pre>
<p>O número da versão é composto por três números separados por pontos, como <code>1.0.0</code> no exemplo acima, seguidos por um número de build opcional, como <code>1</code> no exemplo acima, separados por <code>+</code>.</p>
<h3 id="heading-6-gerando-o-arquivo-archive-de-build-e-enviando-a-loja">6 - Gerando o arquivo (archive) de build e enviando a loja</h3>
<p>Bom, aqui existe duas formas de fazer isso, uma pelo Vscode em combinação com um outro programa e outra pelo Xcode!</p>
<p><strong>Com o Vs code</strong></p>
<p>Execute <code>flutter build ipa</code> para produzir um arquivo de compilação do Xcode ( <code>.xcarchive</code>) no diretório do seu projeto <code>build/ios/archive/</code> e um pacote de aplicativos da App Store (<code>.ipa</code>) em <code>build/ios/ipa</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721045378402/2c2f2f51-2460-41ed-afbf-5293a54f2ede.png" alt class="image--center mx-auto" /></p>
<p>Pronto, Archive gerado com sucesso no caminho <code>build/ios/ipa</code> observe que ele pede que usemos um app chamado <a target="_blank" href="https://apps.apple.com/us/app/transporter/id1450874784?mt=12"><strong>Apple Transporter</strong></a> para enviar para o portal do desenvolvedor apple o nosso aplicativo em formato IPA.</p>
<p>Faça a instalação dele via AppStore, veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721214597012/4ac3f291-72e0-4ff3-9436-44e1d05eb2a7.png" alt class="image--center mx-auto" /></p>
<p>Depois de instalado, faça login e abra-o 🛠️</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721214687515/37f148fa-4ffd-4fd2-8c27-f8f448805787.png" alt class="image--center mx-auto" /></p>
<p>Agora vamos transportar nosso IPA para o <a target="_blank" href="https://developer.apple.com/testflight/">TestFlight</a>, uma ferramenta no portal do desenvolvedor Apple que possibilita aos testadores usarem seus aplicativos e concederem feedbacks antes de lançá-los na App Store.</p>
<p>Clique em <strong>ADD APP</strong> vá no caminho mostrado anteriormente e selecione o seu aplicativo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721218599470/3abb7969-5662-44cf-aa6a-06713bd8c637.png" alt class="image--center mx-auto" /></p>
<p>Veja que obtivemos sucesso ao fazer o upload para o transporter, agora é so enviar para o portal da Apple, clique em <strong>DELIVER. 😎</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721219084625/f95d042f-ae5c-4507-8c3e-fe201c872f56.png" alt class="image--center mx-auto" /></p>
<p>Depois de carregado podemos ver que as nossas compilações aparecem no Test Flight com sucesso ✈️</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721598578205/1ed14534-1c9e-4e81-ab9a-a34c4b87919f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-7-finalizando-a-configuracao-e-enviando-para-a-revisao">7 - Finalizando a configuração e enviando para a revisão</h3>
<p>Quando estiver pronto para lançar seu aplicativo para o mundo, siga estas etapas para enviá-lo para análise e lançamento na App Store:</p>
<p>Selecione a compilação desejada.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721601728216/6b7dfc9e-1db1-45ff-9f31-d7f0b6f45a35.png" alt class="image--center mx-auto" /></p>
<p>Em seguida preencha os demais dados como descrição do aplicativo, texto promocional, classificação, categoria, local de disponibilidade, preço, palavras chave e screenshots etc.</p>
<p>E depois clique em submeter para a revisão.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721602510835/bb3d797b-7748-44e3-af59-3d72767bf01a.png" alt class="image--center mx-auto" /></p>
<p><strong>Dica importante</strong> 💡</p>
<p>Para os screenshots devemos emular o nosso aplicativo nos simuladores corretos e assim tirar os screenshots no tamanho ideal. 📲</p>
<p>Para iPhone telas 6,5 e 6,7 pol, pode usar o simulador do iPhone 15 Plus.</p>
<p>Para iPhone tela 5,5 pol, pode usar o simulador do iPhone 8 Plus.</p>
<p>Para mais detalhes sobre os diversos tamanhos de screenshots confira e acesse o <a target="_blank" href="https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications">link</a> da documentação oficial.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721602053227/970299b4-9bce-43c1-b462-b0620ea7886a.png" alt class="image--center mx-auto" /></p>
<p>A Apple notifica você quando o processo de revisão do aplicativo é concluído.</p>
<p><strong>Outra dica importante</strong> 💡</p>
<p>Instale o aplicativo do apple store connect e assim ficar por dentro da revisão do seu aplicativo pois a apple também notifica tudo por lá.</p>
<p>Bom é isso, agora é aguardar 😉.</p>
<p>Seu aplicativo será lançado de acordo com as instruções que você especificou na seção Lançamento da <strong>Lançamento da versão na App Store</strong>.</p>
<p><strong>Referências 🔗</strong></p>
<p><a target="_blank" href="https://appstoreconnect.apple.com/">Release an iO</a><a target="_blank" href="https://www.youtube.com/watch?v=iE2bpP56QKc">S app with Flutter</a><a target="_blank" href="https://appstoreconnect.apple.com/">in 7 steps</a></p>
<p><a target="_blank" href="https://appstoreconnect.apple.com/">Buil</a><a target="_blank" href="https://docs.flutter.dev/deployment/ios">d and release an iOS app</a></p>
<h2 id="heading-conclusao"><strong>Conclusão</strong></h2>
<p>Bom é isso 😎.</p>
<p>Neste artigo, você aprendeu como fazer o deploy da sua aplicação Flutter na loja da Apple 🍏</p>
<p>Em artigos futuros da série, veremos como fazer o processo para a loja do Android.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://x.com/ianoliveirag12">X (<strong>Twitter)</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Utilizando o Firebase Hosting para hospedar suas aplicações Flutter na Web]]></title><description><![CDATA[Fala, Flutter devs. Blz? Hoje vamos dar continuidade a série "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.
Um pouco de contexto: es...]]></description><link>https://ianoliveira.dev/utilizando-o-firebase-hosting-para-hospedar-suas-aplicacoes-flutter-na-web</link><guid isPermaLink="true">https://ianoliveira.dev/utilizando-o-firebase-hosting-para-hospedar-suas-aplicacoes-flutter-na-web</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[Firebase hosting]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[Dart]]></category><category><![CDATA[mobile app development]]></category><category><![CDATA[hosting]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Tue, 18 Jun 2024 03:29:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718459291777/c86afb02-ea51-4a11-8f73-24d4496476da.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, Flutter devs. Blz? Hoje vamos dar continuidade a <a target="_blank" href="https://ianoliveira.hashnode.dev/serie-dominando-o-firebase-em-aplicativos-flutter"><strong>série</strong></a> "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.</p>
<p>Um pouco de contexto: estamos em junho e, no Dia dos Namorados, eu estava sem nada para fazer. Então, resolvi brincar e desenvolvi um aplicativo com Flutter para pedir uma pessoa em namoro de uma forma especial, hahaha. 🤣</p>
<p>A maravilha do Flutter é que ele é <a target="_blank" href="https://flutter.dev/multi-platform">multiplataforma</a>, ou seja, está disponível para várias plataformas, como Android, iOS, sistemas desktop e também web, tudo com apenas um único código. Foi aí que pensei: "Bom, a forma mais rápida de divulgar esse app e mostrá-lo ao mundo é colocando-o na web para que o público possa acessá-lo." E foi aí que me ocorreu: "<strong>Flutter e Firebase Hosting, uma combinação perfeita</strong>!" 💙🔥</p>
<p>Hoje, meu objetivo é abordar o uso do Firebase Hosting, que é uma maneira simples de distribuir aplicativos aos testadores ou automatizar o processo de lançamento de novas versões de forma rápida e fácil na web.</p>
<p>Eu tive a ideia de escrever este artigo depois que um amigo me mandou uma mensagem ontem, perguntando como e o que eu usei para hospedar o aplicativo do Dia dos Namorados. 💘📲</p>
<p>Ao longo do artigo vou mostrar o aplicativo de pedido de namoro que fiz de exemplo usando Flutter e Firebase, e como hospedá-lo no Firebase Hosting!</p>
<p>Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-o-que-e-firebase-hosting">O que é Firebase Hosting?</h3>
<p><img src="https://uploads-ssl.webflow.com/5f5097f276b52f2a32f9c27a/6464b029008bed92193cba4b_firebase-features.jpg" alt="Firebase Features" /></p>
<p>Firebase Hosting é um dos serviços oferecido pelo Firebase. Este serviço permite que desenvolvedores hospedem conteúdo estático e dinâmico na web de maneira rápida e segura.</p>
<p>Ele é especialmente útil para hospedagem de aplicativos de página única (SPA), sites estáticos, APIs e microsserviços. Abaixo eu listo os principais recursos e benefícios do Firebase Hosting 😎.</p>
<h3 id="heading-recursos-do-firebase-hosting">Recursos do Firebase Hosting</h3>
<ol>
<li><p><strong>Entrega Rápida e Segura:</strong> Firebase Hosting utiliza a rede de entrega de conteúdo (CDN) do Google para garantir que seu conteúdo seja entregue rapidamente aos usuários em todo o mundo. Isso melhora o tempo de carregamento e a experiência do usuário.</p>
</li>
<li><p><strong>SSL Automático:</strong> Todas as conexões são automaticamente criptografadas com HTTPS, garantindo que os dados transmitidos entre o servidor e o cliente sejam seguros.</p>
</li>
<li><p><strong>Configuração Simples:</strong> O processo de implantação é simples, facilitado por uma linha de comando (CLI) intuitiva. Com apenas alguns comandos, você pode implantar seu site ou aplicativo.</p>
</li>
<li><p><strong>Suporte a Rotas Personalizadas e Redirecionamentos:</strong> Permite configurar rotas personalizadas e redirecionamentos para URLs específicas, o que é útil para gerenciar URLs e navegação dentro do seu aplicativo.</p>
</li>
<li><p><strong>Integração com Outras Ferramentas Firebase:</strong> Firebase Hosting se integra perfeitamente com outras ferramentas Firebase, como Cloud Functions e Firebase Authentication, permitindo a criação de aplicações web robustas e escaláveis.</p>
</li>
</ol>
<h3 id="heading-beneficios-do-firebase-hosting">Benefícios do Firebase Hosting</h3>
<ol>
<li><p><strong>Desempenho:</strong> A utilização da CDN global do Google garante tempos de carregamento rápidos, reduzindo a latência e melhorando a experiência do usuário final.</p>
</li>
<li><p><strong>Segurança:</strong> Com SSL automático, todas as suas conexões são seguras, sem a necessidade de configuração manual de certificados.</p>
</li>
<li><p><strong>Escalabilidade:</strong> O serviço é capaz de escalar automaticamente para lidar com o aumento do tráfego, sem que o desenvolvedor precise se preocupar com a infraestrutura.</p>
</li>
<li><p><strong>Fácil Integração:</strong> A integração com outras ferramentas do Firebase torna o desenvolvimento de aplicativos mais eficiente, oferecendo soluções prontas para autenticação, banco de dados em tempo real, notificações push, entre outros.</p>
</li>
<li><p><strong>Desenvolvimento Rápido:</strong> A simplicidade de configuração e a poderosa CLI permitem que os desenvolvedores implantem rapidamente mudanças e atualizações, facilitando o desenvolvimento ágil.</p>
</li>
</ol>
<h3 id="heading-como-funciona"><strong>Como funciona?</strong></h3>
<p><a target="_blank" href="https://firebase.google.com/docs/hosting/manage-hosting-resources?hl=pt-br"><img src="https://firebase.google.com/static/docs/hosting/images/hosting-single-site-hierarchy.png?hl=pt-br" alt="Visão geral da infraestrutura do Hosting" /></a></p>
<p>Ele funciona usando a infraestrutura do Google Cloud, que é escalável e segura. Quando você faz o deploy de um site, seus arquivos são armazenados nos servidores do Google e distribuídos através de uma rede de distribuição de conteúdo (CDN).</p>
<p>Essa CDN tem servidores de borda espalhados pelo mundo, garantindo que os arquivos do site sejam entregues rapidamente aos usuários a partir do servidor mais próximo geograficamente.</p>
<p>O serviço oferece HTTPS automaticamente, gerenciando certificados SSL para garantir comunicações seguras. Além disso, ele permite o controle de acesso e segurança por meio de integrações com outros serviços do Firebase, como o Firebase Authentication.</p>
<h3 id="heading-usando-o-firebase-hosting-com-o-flutter-web">Usando o Firebase Hosting com o Flutter web</h3>
<p>Vou mostrar como hospedei a aplicação dos dias do namorados que desenvolvi ✍🏻.</p>
<p>É muito simples hospedar seu aplicativo da flutter web existente com o Firebase Hosting.</p>
<h3 id="heading-criacao-do-projeto-e-inicializacao-do-firebase">Criação do projeto e Inicialização do Firebase</h3>
<p>Vamos utilizar o projeto <a target="_blank" href="https://valentine-day-app-636d7.web.app/">valentine_day_app</a> que criei no dia dos namorados rsrs 💕</p>
<p>Você já tem um projeto Firebase criado? Caso contrário, siga meu outro <a target="_blank" href="https://ianoliveira.hashnode.dev/configurando-o-firebase-no-flutter">artigo</a> de configuração e instalação do firebase com todas as etapas detalhadas!</p>
<p>No post de hoje não irei mostrar como inicializa o Firebase no Flutter pois fiz isso no artigo mencionado acima com todas as etapas detalhadas!</p>
<p>Nele mostro como criar um projeto Firebase do zero e como vinculá-lo ao seu aplicativo Flutter. Acesse <a target="_blank" href="https://ianoliveira.hashnode.dev/configurando-o-firebase-no-flutter">aqui</a>. 🔗</p>
<h3 id="heading-instalando-a-cli-do-firebase-tools"><strong>Instalando a CLI do firebase-tools 🛠️</strong></h3>
<p>Firebase Tools é uma ferramenta de linha de comando que ajuda você a implantar e gerenciar seus projetos do Firebase.</p>
<p>🏃‍♀ Pule esta etapa se você já tiver o firebase-tools instalado.</p>
<p>Se você não tiver o <code>npm</code>, deverá instalá-lo primeiro.</p>
<ul>
<li><p><strong>Instale o Node.js:</strong> as ferramentas do Firebase exigem o <em>Node.js</em>. Baixe e instale-o do site <a target="_blank" href="http://nodejs.org">nodejs.org</a><a target="_blank" href="https://nodejs.org/">.</a></p>
</li>
<li><p><strong>Instale as ferramentas do Firebase:</strong> abra o terminal e execute o seguindo comando:</p>
<pre><code class="lang-bash">  $ npm install -g firebase-tools
</code></pre>
<p>  Pronto 🎉, o <strong>firebase-tools</strong> agora está instalado!</p>
</li>
</ul>
<h3 id="heading-inicializando-o-firebase-hosting"><strong>Inicializando o Firebase Hosting</strong></h3>
<p>Se você não tiver inicializado o Firebase Hosting em seu projeto vamos fazer isso agora acessando o painel do <a target="_blank" href="https://console.firebase.google.com/u/0/?hl=pt-br">Firebase console</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718635907985/6a95c9af-15a8-4ac9-bc06-c883db3b3279.png" alt class="image--center mx-auto" /></p>
<p>Depois clique em <strong>vamos começar,</strong> veja imagem abaixo:</p>
<ol>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718636603714/c36ece5b-7856-4e36-9f59-77ca03546f5e.png" alt class="image--center mx-auto" /></p>
<p> Acesse a pasta do seu projeto pelo terminal e com a CLI do Firebase, ative a visualização de frameworks da web com o comano abaixo:</p>
<pre><code class="lang-json"> firebase experiments:enable webframeworks
</code></pre>
<p> Abaixo eu mostro o resultado com sucesso do comando.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718636756152/eec5ba36-5099-481f-9936-0d74f28439b4.png" alt="Rodando o comando firebase experiments:enable webframeworks" class="image--center mx-auto" /></p>
<p> Execute o próximo comando abaixo de inicialização do Hosting e siga as instruções:</p>
<pre><code class="lang-json"> firebase init hosting
</code></pre>
<ul>
<li><p>Responda "Sim" para a pergunta "<strong>Você quer usar uma estrutura da Web?</strong>"</p>
</li>
<li><p>Responda "Sim" para a pergunta "<strong>Você quer usar uma estrutura da Web?</strong>" (experimental)</p>
</li>
<li><p>Escolha o diretório de origem de hospedagem, que pode ser um app Flutter já usado.</p>
</li>
<li><p>Se necessário, escolha Flutter Web.</p>
</li>
</ul>
</li>
</ol>
<p>    Veja abaixo o resultado do comando realizado 🛠️.</p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718637283861/1ae1dc36-76f7-4d23-a052-4a0703e0d028.png" alt="Rodando o comando firebase init hosting" class="image--center mx-auto" /></p>
<h3 id="heading-implantando-seu-app-no-firebase-hosting"><strong>Implantando seu app no Firebase Hosting</strong></h3>
<ol>
<li><p>Antes de implantar, você precisa criar uma versão de lançamento do seu aplicativo Web Flutter e para isso execute em seu terminal o comando <code>flutter build web</code>.</p>
<p> Este comando compila seu aplicativo em um formato web implantável.</p>
</li>
<li><p>Com seu aplicativo criado e o Firebase configurado, você está pronto para implantar.</p>
<p> No diretório do projeto, execute o comando abaixo que faz upload do seu aplicativo criado para o Firebase Hosting.</p>
</li>
</ol>
<pre><code class="lang-json">    firebase deploy
</code></pre>
<p>    Veja o resultado do comando abaixo.</p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718637737290/b70f547d-1bc7-49ed-abf3-286eed142bd7.png" alt="Rodando o comando firebase deploy" class="image--center mx-auto" /></p>
<p>    Assim que a implantação for concluída, o Firebase fornecerá um URL para acessar seu aplicativo da web.</p>
<p>    No nosso caso teremos a aplicação hospedada nesse <a target="_blank" href="https://valentine-day-app-636d7.web.app/">link</a> gerado.</p>
<p>    Vamos ver abaixo nosso app flutter web hospedado e funcionando na web 🤩 🎉</p>
<p>    <img src="https://cdn-images-1.medium.com/max/800/0*KSAd_g1y8Ez6_p3V.png" alt="Aplicativo Flutter Valentine Day 💕" /></p>
<p>    Aplicativo Flutter Valentine Day 💕</p>
<h3 id="heading-adicionando-um-dominio-personalizado-ao-aplicativo"><strong>Adicionando um domínio personalizado ao aplicativo</strong></h3>
<p>Para adicionar um domínio personalizado ao seu aplicativo da web do Firebase, siga estas etapas:</p>
<p>No Firebase Hosting você encontrará um botão que diz “<strong>Adicionar domínio personalizado</strong>” na seção “<strong>Domínios</strong>” veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718678859177/30baca97-225c-4fcd-bd88-e00df127187d.png" alt="Adicionar domínio personalizado" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Vincular um domínio personalizado envolve informar ao Firebase sobre o domínio, comprovar a propriedade do domínio e aguardar a emissão dos certificados SSL.</em></p>
</blockquote>
<ul>
<li><p>Insira o seu nome de domínio personalizado no campo “Nome de domínio” e clique em “Continuar”.</p>
</li>
<li><p>O Firebase Hosting verificará se você é o proprietário do domínio. Para isso, será fornecido um registro TXT que você precisa adicionar às configurações de DNS do seu domínio. Acesse o site do seu registrador de domínio e insira esse registro TXT nas configurações de DNS.</p>
</li>
<li><p>Após a adição do registro TXT, aguarde até que as configurações de DNS sejam propagadas. Isso permite que o Firebase Hosting verifique se você é o proprietário do domínio e conceda acesso ao seu site no Firebase Hosting.</p>
</li>
<li><p>Após a verificação do proprietário do domínio, será necessário atualizar novamente as configurações de DNS do seu domínio. O Firebase Hosting fornecerá os registros A e CNAME necessários. Acesse o site do seu registrador de domínio e adicione esses registros às configurações de DNS.</p>
</li>
<li><p>Uma vez concluídas essas etapas, seu domínio personalizado estará conectado ao site do Firebase Hosting. Lembre-se de que pode levar de 24 a 48 horas para que as alterações de DNS sejam totalmente propagadas pela Internet.</p>
</li>
</ul>
<p><strong>Materiais Adicionais 🔗</strong></p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=A13rZZYbB-U">Deploy Flutter Web App to Firebase Hosting under 60 secs</a></p>
<p><a target="_blank" href="https://docs.flutter.dev/deployment/web">https://docs.flutter.dev/deployment/web</a></p>
<h2 id="heading-conclusao"><strong>Conclusão</strong></h2>
<p>Bom é isso 😎.</p>
<p><a target="_blank" href="https://dribbble.com/shots/22627336-Flutter-Firebase-Festival-Google"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718680657932/9b1e2cb9-5bb9-40c8-8fc6-07cb4b9f0fdf.gif" alt="Dash e Spark dando Tchauzinho" class="image--center mx-auto" /></a></p>
<p>Hospedar um aplicativo web Flutter no Firebase é um processo simples que abre um mundo de possibilidades para desenvolvedores de aplicativos.</p>
<p>Com o Firebase, você pode não apenas hospedar seu aplicativo, mas também aproveitar outros recursos, como análises, gerenciamento de banco de dados e muito mais.</p>
<p>Em resumo, o Firebase Hosting é uma solução poderosa e fácil de usar para desenvolvedores que precisam hospedar conteúdo web, oferecendo segurança, desempenho e integração eficiente com outras ferramentas do Firebase.</p>
<p>Neste artigo, você aprendeu como configurar e preparar nossos aplicativos Flutter para serem usados ​​com o Firebase Hosting.</p>
<p>Em artigos futuros da série, veremos como usar recursos do Firebase, como Cloud Firestore, Authentication, Crashlytics, Remote Config e muito mais com Flutter.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Guia Passo a Passo: Configurando Flavors no Flutter para Android, IOS e Web]]></title><description><![CDATA[Fala devs blz? Hoje nós vamos ver como configurar Flavors em nossas aplicações Flutter, algo extremamente importante e útil quando se está trabalhando com desenvolvimento mobile etc. Eu sempre uso flavors em meus aplicativos que vão para produção, po...]]></description><link>https://ianoliveira.dev/guia-passo-a-passo-configurando-flavors-no-flutter-para-android-ios-e-web</link><guid isPermaLink="true">https://ianoliveira.dev/guia-passo-a-passo-configurando-flavors-no-flutter-para-android-ios-e-web</guid><category><![CDATA[flavors]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Tue, 21 May 2024 11:35:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/38iUwPww0Xc/upload/c76f77a8dbd1507068b0839e1d96c146.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala devs blz? Hoje nós vamos ver como configurar Flavors em nossas aplicações Flutter, algo extremamente importante e útil quando se está trabalhando com desenvolvimento mobile etc. Eu sempre uso flavors em meus aplicativos que vão para produção, pois eles facilitam bastante quando se tem que trabalhar com múltiplos ambientes (<strong>development, staging, production</strong>) para um mesmo app.</p>
<p>Depois de várias e várias tentativas e erros para fazer os flavors funcionarem, especialmente no iOS, decidi escrever este artigo com meus aprendizados. A ideia que ele seja um guia definitivo passo a passo sobre o assunto, pois pesquisando na internet não vi muitos materiais estruturados sobre o assunto.</p>
<p>Toda vez que eu ia configurar flavors acabava passando algumas horas na construção pois tinha que consultar vários materiais da internet, especificamente para IOS onde dava bastante problema.</p>
<h3 id="heading-o-que-sao-flavors-e-por-que-voce-precisa-usar">O que são Flavors e <strong>por que você precisa usar</strong></h3>
<p>Flavors, também chamados de sabores em português é quando você tem ambientes separados para seu aplicativo usando a mesma base de código. Normalmente, os tipos mais usados ​​são <strong>dev</strong>, <strong>stag</strong> e <strong>prod</strong>.</p>
<p>Por exemplo você pode ter um flavor para seu aplicativo de produção que aponta para uma API de produção com o endereço <a target="_blank" href="http://meuapp.com.br/api">meuapp.com.br/api</a> e outra versão de desenvolvimento do app apontando para o host de API em <a target="_blank" href="http://dev.meuapp.com.br/api">dev.meuapp.com.br/api</a> ou até mesmo ter ícones de aplicativos diferentes para cada configuração.</p>
<p>A maioria das empresas e projetos normalmente têm um ciclo de vida no processo de construção de software bem definido, onde as novas funcionalidades passam pelas mais diferentes etapas, como desenvolvimento, teste, e, finalmente, vão para a produção.</p>
<p>Abaixo dou uma breve explicação sobre esses ambientes/configurações.</p>
<ul>
<li><p><strong>development (dev)</strong> : usado apenas durante a criação do aplicativo onde os desenvolvedores usam a vontade sem medo de comprometer os dados.</p>
</li>
<li><p><strong>staging (stg)</strong> : usado para distribuir versões de teste para a equipe QA e outras partes interessadas no teste do aplicativo. O back-end vai configurado para dados de desenvolvimento, mas não pronto para fins de produção.</p>
</li>
<li><p><strong>production (prod)</strong> : usado por todos os usuários que baixaram o aplicativo nas lojas onde os dados do backend já são os reais.</p>
</li>
</ul>
<p>A grande sacada dos <strong>flavors</strong> é nos possibilitar termos vários ambientes para mexer antes de enviar pra produção nos dando uma garantia que os dados no ambiente de produção não sejam alterados por engano durante o desenvolvimento. 😄</p>
<p>Sem flavors teríamos que mudar os hosts das APIS manualmente em variáveis a cada build o que seria bem chato, sem falar que se quisermos mudar logo, o nome do app seria mais complicado ainda.</p>
<p>Mas se nosso aplicativo Flutter usar um back-end do Firebase, configurá-lo para cada ambiente (dev, stg, prod) sem flavors é também extremamente chato, trabalhoso e custoso ter que toda vez na build fazer isso.</p>
<p><mark>Com a nova versão do Flutter configurar o firebase para os flavors ficou bem mais simples do que no passado, então sem mais delongas vamos lá. 💛</mark></p>
<h3 id="heading-a-abordagem-para-este-tutorial"><strong>A abordagem para este tutorial</strong></h3>
<p>Vou construir um aplicativo de exemplo com duas opções: <strong>dev</strong> e <strong>prod</strong> .</p>
<h3 id="heading-configurando-flavors-no-dart-para-multiplos-ambientes-de-api"><strong>Configurando Flavors no Dart para múltiplos ambientes de API.</strong></h3>
<p>Vamor criar um arquivo de flavors no dart e com isso poderemos disponibilizá-los em qualquer lugar do nosso código, começaremos criando o arquivo <code>flavors.dart</code> na pasta <code>lib</code> do nosso projeto.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> FlavorTypes { dev, prod }

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Flavor</span> </span>{
  Flavor._instance();

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">late</span> FlavorTypes flavorType;

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> <span class="hljs-keyword">get</span> flavorMessage {
    <span class="hljs-keyword">switch</span> (flavorType) {
      <span class="hljs-keyword">case</span> FlavorTypes.dev:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Dev'</span>;
      <span class="hljs-keyword">case</span> FlavorTypes.prod:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Production'</span>;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Dev'</span>;
    }
  }

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> <span class="hljs-keyword">get</span> apiBaseUrl {
    <span class="hljs-keyword">switch</span> (flavorType) {
      <span class="hljs-keyword">case</span> FlavorTypes.dev:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseDev'</span>;
      <span class="hljs-keyword">case</span> FlavorTypes.prod:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseProd'</span>;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseDev'</span>;
    }
  }

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">bool</span> isProduction() =&gt; flavorType == FlavorTypes.prod;
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">bool</span> isDevelopment() =&gt; flavorType == FlavorTypes.dev;
}
</code></pre>
<p>Nesse arquivo configurei-o para ser um singleton, pois com isso ele será facilmente acessível em qualquer lugar já que vamos precisar.</p>
<p>No <code>FlavorTypes</code> enum declaramos os tipos de ambientes que utilizaremos, e o <code>getApiBaseUrl</code> será responsáveil ​​por selecionar a URL correta para a nossa API conforme o flavor setado quando a aplicação estiver rodando.</p>
<p>Agora para cada ambiente flavor, criamos um arquivo main+flavor onde sera o ponto de entrada usado para iniciar o aplicativo setando o flavor correto</p>
<ul>
<li><p><code>main_dev.dart</code>: Nosso flavor para o ambiente de <strong>desenvolvimento</strong> .</p>
<pre><code class="lang-dart">  <span class="hljs-keyword">import</span> <span class="hljs-string">'flavors.dart'</span>;
  <span class="hljs-keyword">import</span> <span class="hljs-string">'main.dart'</span> <span class="hljs-keyword">as</span> main_common;

  Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
    Flavor.flavorType = FlavorTypes.dev;
    main_common.main();
  }
</code></pre>
</li>
<li><p><code>main_prod.dart</code>: Do nosso flavor para o lançamento em <strong>produção</strong> .</p>
<pre><code class="lang-dart">  <span class="hljs-keyword">import</span> <span class="hljs-string">'flavors.dart'</span>;
  <span class="hljs-keyword">import</span> <span class="hljs-string">'main.dart'</span> <span class="hljs-keyword">as</span> main_common;

  Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
    Flavor.flavorType = FlavorTypes.prod;
    main_common.main();
  }
</code></pre>
</li>
</ul>
<p>O <strong><em>main_common</em></strong> é apenas um alias para o main padrão que ja existia antes de configuramos os flavor no projeto, apenas estamos encapsulando-o para ser chamado conforme o <strong>flavor</strong> (sabor) setado.</p>
<p>Veja abaixo o código do <code>main_common</code>:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-keyword">void</span> main() {
  runApp(<span class="hljs-keyword">const</span> MyApp());
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> MyApp({<span class="hljs-keyword">super</span>.key});

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> MaterialApp(
      title: <span class="hljs-string">'Flutter Demo Flavor'</span>,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: <span class="hljs-keyword">const</span> MyHomePage(),
    );
  }
}
</code></pre>
<p>Para rodar nosso aplicativo devemos escolher o flavor desejado e em seguida digitar o seguinte comando no terminal:</p>
<ul>
<li><p><strong>flutter run -t lib/main_dev.dart</strong></p>
</li>
<li><p><strong>flutter run -t lib/main_prod.dart</strong></p>
</li>
</ul>
<p>O comando acima irá executar nosso aplicativo em modo de depuração, com <code>-t</code> ou <code>--target</code> definimos o ponto inicial, ou seja o arquivo principal.</p>
<p>Veja abaixo o aplicativo rodando no emulador Android com o ambiente de <strong>development</strong> configurado parcialmente pois ainda precisamos fazer alguns ajustes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714223799112/74bd3e58-0107-474a-867c-a8180237a87f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-adicionando-flavors-para-android"><strong>Adicionando flavors para Android</strong></h3>
<p>Com o nosso aplicativo inicial de exemplo rodando precisamos finalizar a configuração dos nossos flavors para o android, é bem simples e rápido de configurar.</p>
<p>Na pasta android navegue até o arquivo em <mark>app/build.gradle</mark> e adicione o seguinte código.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714224576766/7896f3f7-09c7-42df-8d79-db9f8c2acb6c.png" alt="app/build.gradle" class="image--center mx-auto" /></p>
<p>O flavor <strong>dev</strong> usará o <code>applicationId</code> como <code>org.cajuinaapps.br.dev</code> com o final indicando ambiente de desenvolvimento e o flavor <strong>prod</strong> usará o <code>applicationId</code> padrão <code>org.cajuinaapps.br</code> sem prefixo no final indicando ambiente de <strong>produção</strong>.</p>
<p>Também definimos um recurso de string chamado <code>app_name</code> no <strong>resValue</strong> que estamos usando em <code>AndroidManifest.xml</code> isso serve para configurar o nome do aplicativo em tempo de execução conforme o flavor usado.</p>
<p><strong><em>NOTA: Não se esqueça de adicionar</em></strong> <code>android:label="@string/app_name"</code> <strong><em>a</em></strong> <code>application</code><strong><em>tag no</em></strong> <code>AndroidManifest.</code></p>
<h3 id="heading-vamor-testar"><strong>Vamor testar 🧪</strong></h3>
<p>Agora podemos executar o aplicativo usando os seguintes comandos um de cada vez e rodar os ambientes.</p>
<pre><code class="lang-dart">flutter run --flavor dev --target lib/main_dev.dart
flutter run --flavor prod --target lib/main_prod.dart
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714226234835/36fa6fc2-156e-40c4-a30e-2877748b4169.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-definindo-configuracoes-de-inicializacao-para-vs-code-e-android-studio">Definindo configurações de inicialização para Vs code e Android Studio</h2>
<p>Para rodar o nosso app não queremos toda vez ter que digitar o comando no terminal não é mesmo, por isso vamos configurar o nosso editor de código para fazer isso para a gente.</p>
<p>No <strong>Vs code</strong>, adicione um arquivo <strong>launch.json</strong>, isso permite que você execute o comando <code>flutter run --flavor [environment name]</code>.</p>
<p>Defina as configurações de inicialização da seguinte forma:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714226375031/e4674159-0eb3-46bd-ba6c-43a6cf1fbc57.png" alt="Vs code" class="image--center mx-auto" /></p>
<ol>
<li><p>No diretório raiz do seu projeto, adicione uma pasta chamada <strong>.vscode</strong> .</p>
</li>
<li><p>Dentro da pasta <strong>.vscode</strong> , crie um arquivo chamado <strong>launch.json</strong> .</p>
</li>
<li><p>No arquivo <strong>launch.json</strong> , adicione uma configuração para cada variação do flavor. Cada configuração possui uma chave <strong>name</strong> , <strong>request</strong> , <strong>type</strong> , <strong>program</strong> e <strong>args.</strong></p>
<p> Veja o exemplo abaixo.</p>
</li>
</ol>
<pre><code class="lang-json">{
    <span class="hljs-attr">"version"</span>: <span class="hljs-string">"0.2.0"</span>,
    <span class="hljs-attr">"configurations"</span>: [
        {
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Development"</span>,
            <span class="hljs-attr">"request"</span>: <span class="hljs-string">"launch"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"dart"</span>,
            <span class="hljs-attr">"program"</span>: <span class="hljs-string">"lib/main_dev.dart"</span>,
            <span class="hljs-attr">"args"</span>: [
                <span class="hljs-string">"--flavor"</span>,
                <span class="hljs-string">"dev"</span>,
            ]
        },
        {
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Production"</span>,
            <span class="hljs-attr">"request"</span>: <span class="hljs-string">"launch"</span>,
            <span class="hljs-attr">"type"</span>: <span class="hljs-string">"dart"</span>,
            <span class="hljs-attr">"program"</span>: <span class="hljs-string">"lib/main_prod.dart"</span>,
            <span class="hljs-attr">"args"</span>: [
                <span class="hljs-string">"--flavor"</span>,
                <span class="hljs-string">"prod"</span>,
            ]
        },
    ]
}
</code></pre>
<p>Agora podemos executar com sucesso o nosso app com o ambiente escolhido.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714226705034/65d9a546-2264-45e2-90f7-565c1d6532e3.png" alt class="image--center mx-auto" /></p>
<p>Configurando no <strong>Android Studio 🛠️</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714227765328/ff84c75e-81f4-48bb-8fab-8e8e6b3320e4.gif" alt="Android studio" class="image--center mx-auto" /></p>
<p>Agora, temos a capacidade de executar nosso aplicativo tanto no VS code quanto no Android Studio.</p>
<p>Se o seu aplicativo utilizar uma API, você pode simplesmente utilizar o <code>Flavor.apiBaseUrl</code> para obter a URL Base correspondente ao ambiente, seja ele de desenvolvimento ou produção.</p>
<p>Fácil, não é mesmo 😅 ? Mas Ian, e se estivermos usando o Firebase? Bem, vamos explorar como configurar flavors para múltiplos projetos do Firebase mais adiante nesse artigo.</p>
<h3 id="heading-configurando-flavors-para-ios">Configurando Flavors para IOS</h3>
<p>Abra a pasta ios do seu projeto no <em>Xcode</em> . Sem configurar nada vamos rodar o comando <code>flutter run --flavor dev</code> no terminal direcionando a um simulador do IOS e veja o que acontece.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714306847911/77cf4a17-d8bf-4310-8f5b-cffb96906c9b.png" alt class="image--center mx-auto" /></p>
<p>Primeiro, precisamos criar novos <strong>Schemes</strong> de produtos no XCode. Em nosso exemplo, é <code>prod</code> e <code>dev</code>.  Um Scheme descreve como o Xcode executa diferentes ações.</p>
<p>Já temos um scheme <code>Runner</code>, que é o scheme padrão. Iremos renomeá-lo para <code>prod</code>e criar mais um novo esquema <code>dev</code>. Vamos lá? veja o passo a passo abaixo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714308766130/f2723a2c-696d-48cf-85c9-4ff84cc842ec.gif" alt="Xcode" class="image--center mx-auto" /></p>
<p>Agora novamente rodando o comando <code>flutter run --flavor dev</code> no terminal direcionando a um simulador do IOS e veja o que acontece.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714307486081/7ff454c5-835c-4bc2-b072-e8ea31ff9c64.png" alt class="image--center mx-auto" /></p>
<p>Esse erro nos diz que o Flutter espera uma <em>configuração de build</em> chamada <strong>Debug-dev</strong> ou similar. Vamos criar essas configurações agora. Depois que os schemes são criados, temos que duplicar as configurações de compilação:</p>
<p><strong>Debug</strong>, <strong>Release</strong>, and <strong>Profile</strong> de acordo com o scheme, com o nome da configuração de compilação copiado + prefixo como nome. Duplique as configurações de build para diferenciar entre as configurações padrão que já estão disponíveis e as novas configurações do scheme <code>dev</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714308981086/f075f346-8ebf-4b77-a6fd-061ef0589c23.gif" alt class="image--center mx-auto" /></p>
<p>Feito isso, teremos 6 configurações, 3 para cada flavor (sabor).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714309145483/5e1e6e41-f20a-4385-8a24-ebebec1a9330.png" alt class="image--center mx-auto" /></p>
<p>Agora rode <code>flutter run --flavor dev</code> novamente…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714309425265/feefd6b9-6006-49bc-adac-f38c6ae4efdc.png" alt class="image--center mx-auto" /></p>
<p>Ainda estamos com erro pois no momento não personalizamos nada no esquema de construção/configuração de compilação, então o aplicativo ainda não irá ser executado com sucesso. Vamos configurar isso agora. ✍🏻</p>
<p>Renomeie o esquema de construção padrão e as configurações de construção para <strong>prod</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714309818437/17ae302f-4174-4ccc-a732-015a97541ce4.gif" alt class="image--center mx-auto" /></p>
<p>Como duplicamos as configurações de build, as configurações de dev ainda estão conectadas ao scheme original (que agora se chama <strong>prod</strong>). Vamos consertar isso também…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714310513511/3237c5e4-b6d9-4a0c-819c-f741265fb2fc.gif" alt class="image--center mx-auto" /></p>
<p>Esse é o resultado final abaixo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714310462239/b83a3fa8-92b4-4e59-987e-0bfee9a2635f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-personalizando-configuracoes-para-cada-scheme"><strong>Personalizando configurações para cada scheme</strong></h3>
<p>Vamos primeiro alterar o identificador do pacote de aplicativos para ser diferente em ambos os esquemas. O <strong><em>applicationId</em></strong> no Android era <code>org.cajuinaapps.br</code> o identificador do pacote no iOS é paralelo ao applicationId do Android.</p>
<p>Então, vamos alterar nosso identificador de pacote de produtos para <code>org.cajuinaapps.br</code> conforme o flavor.</p>
<p>Agora, vamos adicionar o identificador do pacote para cada configuração. Em <code>Target</code>-&gt; <code>Runner</code>, clique <code>Build Settings</code>e pesquise <code>Product Bundle Identifier</code> e altere o identificador do pacote de aplicativos para diferenciar os esquemas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714312239691/4d79d4d5-35b3-41f0-a659-397086810141.gif" alt class="image--center mx-auto" /></p>
<p>Quando terminar, você terá algo assim.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714312425131/8633fdc5-0a45-45e1-a302-8906e2c31714.png" alt class="image--center mx-auto" /></p>
<p><strong>Configurando nomes diferentes para o aplicativo conforme o flavor.</strong></p>
<p>No mesmo <code>Target</code>-&gt; <code>Runner</code>-&gt; <code>Build Settings</code>, clique no botão <code>+</code><strong>Add User Defined Settings</strong> e crie uma nova variável definida pelo usuário.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714313084379/51fa59c8-0c4b-416a-9873-a59f74c47d60.gif" alt class="image--center mx-auto" /></p>
<p>Quando terminar, você terá algo assim.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714313022256/2b4caee3-29f8-4391-aa43-55b5054e6c17.png" alt class="image--center mx-auto" /></p>
<p>Depois de concluir a variável definida pelo usuário, você precisa alterar <code>Info.plist</code> para usar esta variável.</p>
<pre><code class="lang-json">&lt;key&gt;CFBundleDisplayName&lt;/key&gt;
&lt;string&gt;$(APP_DISPLAY_NAME)&lt;/string&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714329034137/2243238a-a9b0-40d4-9cc8-7d3a94999ac8.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-vamos-testar"><strong>Vamos testar 🧪</strong></h2>
<p>Semelhante ao Android, podemos testar o iOS executando o comando para os ambientes <strong>prod</strong> e <strong>dev</strong>.</p>
<pre><code class="lang-yaml"><span class="hljs-string">flutter</span> <span class="hljs-string">run</span> <span class="hljs-string">--flavor</span> <span class="hljs-string">dev</span> <span class="hljs-string">--target</span> <span class="hljs-string">lib/main_dev.dart</span>
<span class="hljs-string">flutter</span> <span class="hljs-string">run</span> <span class="hljs-string">--flavor</span> <span class="hljs-string">prod</span> <span class="hljs-string">--target</span> <span class="hljs-string">lib/main_prod.dart</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714329960283/6761ac0e-7e11-4f10-a385-12386a2f57ba.png" alt="aplicativos de produção e desenvolvimento" class="image--center mx-auto" /></p>
<h3 id="heading-icones-diferentes-no-aplicativo-para-android-e-ios"><strong>Ícones diferentes no aplicativo para Android e iOS</strong></h3>
<p>Agora, vamos ter ícones diferentes baseados nos flavors. Teremos 2 ícones diferentes um para cada ambiente.</p>
<p>O ícone verdinho vai ser o de ambiente de desenvolvimento e o outro será o do aplicativo de produção.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714330579010/4961e6d2-0493-47bf-8685-c2a879bdb692.png" alt="Logos para os apps" class="image--center mx-auto" /></p>
<p>Vamos utilizar o package <code>flutter_launcher_icons</code> para nos ajudar a gerar os ícones para o aplicativo. Instale-o como uma dependência de desenvolvimento.</p>
<pre><code class="lang-json">flutter pub add flutter_launcher_icons --dev
</code></pre>
<p>Após a instalação vamos criar um arquivo de configuração para ícones de cada ambiente flavor.</p>
<p>Veja o exemplo abaixo.</p>
<ul>
<li><p><code>flutter_launcher_icons-dev.yaml</code></p>
<pre><code class="lang-json">  flutter_launcher_icons:
    android: <span class="hljs-literal">true</span>
    ios: <span class="hljs-literal">true</span>
    remove_alpha_ios: <span class="hljs-literal">true</span>
    image_path: <span class="hljs-string">"assets/icon_dev.png"</span>
</code></pre>
</li>
<li><p><code>flutter_launcher_icons-prod.yaml</code></p>
<pre><code class="lang-json">  flutter_launcher_icons:
    android: <span class="hljs-literal">true</span>
    ios: <span class="hljs-literal">true</span>
    remove_alpha_ios: <span class="hljs-literal">true</span>
    image_path: <span class="hljs-string">"assets/prod-icon.png"</span>
</code></pre>
</li>
</ul>
<p>Agora vamos gerar os ícones com o comando:</p>
<pre><code class="lang-json">flutter pub run flutter_launcher_icons:main -f flutter_launcher_icons-*
</code></pre>
<p>Rodando o comando nossos ícones foram gerados com sucesso. No Android dentro de <code>app/src/</code> foi gerado duas pastas chamadas de <strong>prod</strong> e <strong>dev</strong> e dentro delas teremos uma outra pasta chamada <code>res</code> com os nosso icones respectivos.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714331058176/574e81da-f0f0-4784-aa96-af88d22f3659.png" alt="ícones gerados com sucesso" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714603368470/fc1688fe-1bf7-43ae-9911-9858e75b7810.png" alt="Vs code" class="image--center mx-auto" /></p>
<p>Para IOS vá em <code>Runner</code> -&gt; <code>Assets.xcassets</code> podemos ver que temos todos os ícones necessários. Podemos remover o <code>AppIcon</code>, que não é utilizado.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714338449919/83706866-9b9f-4a24-996f-e5728b800393.png" alt class="image--center mx-auto" /></p>
<p>Agora, em <code>Target</code>-&gt; <code>Runner</code>-&gt; <code>Build Settings,</code> procure por <code>Primary App Icon</code>. defina o sufixo correspondente para cada um.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714338743810/9bd0d447-9d01-4fc9-bd6a-300f931e0c53.png" alt class="image--center mx-auto" /></p>
<p>Testando as duas compilações e o resultado final é esse abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714340362502/6d9748ee-1f87-4dfe-8dad-e4bf0c7b23a7.png" alt="Aplicativos instalado com ícones diferentes" class="image--center mx-auto" /></p>
<h3 id="heading-configurando-flavors-para-diferentes-projetos-do-firebase">Configurando Flavors para diferentes projetos do Firebase 🔥</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714229772648/557cd777-b09c-464c-96c1-cb530bdda442.png" alt="Flavor mapping for dev and prod environments." class="image--center mx-auto" /></p>
<p>Primeira coisa, você deve ter dois projetos do Firebase criados para cada ambiente flavor.</p>
<p>Para o nosso exemplo nesse artigo teremos um de <code>dev</code> e outro de <code>prod</code>.</p>
<p><mark>A integração do Firebase em um projeto costumava ser mais complicada do que é hoje. Você tinha que integrá-lo em um nível nativo, baixar configurações separadas para Android, iOS e web e era bastante sujeito a erros mas hoje temos uma nova maneira mais prática e rápido de configurar isso graças as evoluções da integração entre times do Flutter e Firebase.</mark></p>
<p>Nesse artigo vou mostrar rapidamente como adicionar e configurar seu projeto ao Firebase mas se você quiser algo mais detalhado pode consultar isso em outro <a target="_blank" href="https://ianoliveira.hashnode.dev/configurando-o-firebase-no-flutter">artigo</a> onde mostro todo o processo bem detalhado, você pode consultar <a target="_blank" href="https://ianoliveira.hashnode.dev/configurando-o-firebase-no-flutter">aqui</a>.</p>
<h2 id="heading-integrando-o-firebase"><strong>Integrando o Firebase</strong></h2>
<p>Abaixo no <a target="_blank" href="https://console.firebase.google.com/u/0/?hl=pt-br">Firebase console</a> já deixei criado os dois projetos para o nosso aplicativo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714242258193/68e4ee1f-4511-4b9f-abfa-a6489c456e5e.png" alt="Firebase console" class="image--center mx-auto" /></p>
<p>Instale a <a target="_blank" href="https://pub.dev/packages/firebase_core">lib</a> do Firebase core em seu app</p>
<pre><code class="lang-json">flutter pub add firebase_core
</code></pre>
<p>Isso adicionará uma linha como esta ao <code>pubspec.yaml</code> do seu pacote (e executará um comando implícito <code>flutter pub get</code>):</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-attr">firebase_core:</span> <span class="hljs-string">^2.31.0</span>
</code></pre>
<p>Em seguida, como o novo processo de integração usa FlutterFire CLI, que depende do <a target="_blank" href="https://firebase.google.com/docs/cli?hl=pt-br">Firebase CLI,</a> você precisa instalar o Firebase CLI em nível global e fazer login. Se você tiver dúvidas na instalação consulte o meu <a target="_blank" href="https://ianoliveira.hashnode.dev/configurando-o-firebase-no-flutter">artigo</a> sobre isso ou a própria documentação <a target="_blank" href="https://firebaseopensource.com/projects/firebase/firebase-tools/">aqui</a>.</p>
<p>Em seguida, faça login na sua conta do Firebase com o seguinte comando:</p>
<pre><code class="lang-json">firebase login
</code></pre>
<p>Se você ainda não estiver logado, este comando abrirá um navegador para permitir que você faça login em sua conta. Em seguida, execute o seguinte comando no mesmo terminal para instalar o FlutterFire CLI:</p>
<pre><code class="lang-json">dart pub global activate flutterfire_cli
</code></pre>
<p>Em seguida, de volta ao terminal, vamos executar o seguinte comando para criar os aplicativos para Android e IOS no console do Firebase para cada projeto.</p>
<pre><code class="lang-json">flutterfire config \
  --project=fir-flavor-example-dev \
  --out=lib/firebase_options_dev.dart \
  --ios-bundle-id=org.cajuinaapps.br.dev \
  --android-app-id=org.cajuinaapps.br.dev
</code></pre>
<p>Este comando registrará um aplicativo iOS e terá <code>org.cajuinaapps.dev</code> como identificador de pacote. Ele também registrará um aplicativo Android com o nome do pacote sendo <code>org.cajuinaapps.dev</code>.</p>
<p>Assim que o comando for concluído, ele irá gerar uma classe de configuração em <code>lib/firebase_options_dev.dart</code> contendo a uma classe chamada <code>DefaultFirebaseOptions</code>.</p>
<h3 id="heading-gerando-a-configuracao-para-o-aplicativo-de-producao"><strong>Gerando a configuração para o aplicativo de produção</strong></h3>
<p>Com o mesmo comando utlizado anteriormente vamos configurar nossos apps no firebase de prod apenas trocando alguns dados.</p>
<p>Veja como ficou o novo comando abaixo:</p>
<pre><code class="lang-json">flutterfire config \
  --project=flavor-firebase-example \
  --out=lib/firebase_options_prod.dart \
  --ios-bundle-id=org.cajuinaapps.br \
  --android-app-id=org.cajuinaapps.br
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716032728265/9c900002-14cb-44c6-9afe-b0d512866993.png" alt="vs code" class="image--center mx-auto" /></p>
<p>De volta ao nosso editor de código, abra o arquivo <code>lib/flavors.dart</code> que nós criamos no início do artigo e adicione o seguinte trecho de código apartir dos comentários abaixo.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_core/firebase_core.dart'</span>;
<span class="hljs-comment">//Adicione esses novos imports</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flavor_example_config/firebase_options_dev.dart'</span> <span class="hljs-keyword">as</span> dev;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flavor_example_config/firebase_options_prod.dart'</span> <span class="hljs-keyword">as</span> prod;

<span class="hljs-keyword">enum</span> FlavorTypes { dev, prod }

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Flavor</span> </span>{
  Flavor._instance();

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">late</span> FlavorTypes flavorType;

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> <span class="hljs-keyword">get</span> flavorMessage {
    <span class="hljs-keyword">switch</span> (flavorType) {
      <span class="hljs-keyword">case</span> FlavorTypes.dev:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Development'</span>;
      <span class="hljs-keyword">case</span> FlavorTypes.prod:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Production'</span>;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Development'</span>;
    }
  }

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> <span class="hljs-keyword">get</span> apiBaseUrl {
    <span class="hljs-keyword">switch</span> (flavorType) {
      <span class="hljs-keyword">case</span> FlavorTypes.dev:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseDev'</span>;
      <span class="hljs-keyword">case</span> FlavorTypes.prod:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseProd'</span>;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">'apiUrlBaseDev'</span>;
    }
  }

  <span class="hljs-keyword">static</span> <span class="hljs-built_in">bool</span> isProduction() =&gt; flavorType == FlavorTypes.prod;
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">bool</span> isDevelopment() =&gt; flavorType == FlavorTypes.dev;
    <span class="hljs-comment">//Adicione esse novo trecho de código abaixo</span>
  <span class="hljs-keyword">static</span> FirebaseOptions <span class="hljs-keyword">get</span> firebaseConfigOptions {
    <span class="hljs-keyword">switch</span> (flavorType) {
      <span class="hljs-keyword">case</span> FlavorTypes.dev:
        <span class="hljs-keyword">return</span> dev.DefaultFirebaseOptions.currentPlatform;
      <span class="hljs-keyword">case</span> FlavorTypes.prod:
        <span class="hljs-keyword">return</span> prod.DefaultFirebaseOptions.currentPlatform;
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> dev.DefaultFirebaseOptions.currentPlatform;
    }
  }
}
</code></pre>
<p>Isso nos fornecerá a configuração correta conforme o <strong>flavor</strong> que estiver rodando no aplicativo em tempo de execução.</p>
<p>Para demonstrar o sucesso da integração eu ativei o banco de dados <a target="_blank" href="https://firebase.google.com/products/firestore?hl=pt-br">Cloud Firestore</a> para cada aplicativo onde estará exibindo dados de seu respectivo ambiente no Firebase.</p>
<p><mark>Atenção!! Não irei mostrar nesse post como configurar e usar o </mark> <a target="_blank" href="https://pub.dev/packages/cloud_firestore"><code>Cloud Firestore</code></a> <mark> mas tenho esse outro </mark> <a target="_blank" href="https://ianoliveira.hashnode.dev/crud-create-read-update-delete-com-firebase-cloud-firestore-no-flutter"><mark>artigo</mark></a> <mark> onde explico tudo em detalhes como fazer um crud completo com ele.</mark></p>
<p>Adicionei alguns dados simples de filmes ao banco de dados para ilustrar melhor. Se você quiser aprender mais sobre o assunto, confira este outro <a target="_blank" href="https://ianoliveira.hashnode.dev/crud-create-read-update-delete-com-firebase-cloud-firestore-no-flutter">artigo</a> onde explico todos os detalhes da integração.</p>
<p>Executando a aplicação podemos ver que o Firebase foi configurado com sucesso!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716067575143/d2b08c8d-e92a-460f-bda0-beed15f04426.png" alt="Aplicativo de prod a esquerda e aplicativo de dev a direita" class="image--center mx-auto" /></p>
<p>Nas imagens acima podemos ver nomes diferentes sobre filmes para cada aplicativo conforme cadastrado na base de dados 🎲 !</p>
<h3 id="heading-rodando-o-aplicativo-na-web">Rodando o aplicativo na web 👨🏻‍💻</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716067897084/9bdc427d-1e81-4b1d-b12d-3d01e5021a4f.png" alt class="image--center mx-auto" /></p>
<p>O uso do Flavors com Firebase funciona perfeitamente na web. Isso ocorre porque o arquivo de configuração do Firebase, na classe <code>DefaultFirebaseOptions</code>, já possui uma configuração específica para o ambiente web. Portanto, ao compilar nossa aplicação Flutter para a web, não é necessário realizar nenhuma configuração adicional. Isso é ótimo, não é mesmo?</p>
<p>Link do projeto no <a target="_blank" href="https://github.com/iang12/flutter_flavor_example">github aqui</a>. 🔗</p>
<p><strong>Referências</strong></p>
<p><a target="_blank" href="https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b">https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b</a></p>
<p><a target="_blank" href="https://codewithandrea.com/articles/flutter-flavors-for-firebase-apps/">https://codewithandrea.com/articles/flutter-flavors-for-firebase-apps/</a></p>
<p><a target="_blank" href="https://github.com/invertase/flutterfire_cli/issues/14">https://github.com/invertase/flutterfire_cli/issues/14</a></p>
<h3 id="heading-conclusaohttpsreferenciabibliograficanet"><a target="_blank" href="https://referenciabibliografica.net/">Conclusão</a></h3>
<p>Bom é isso 😎.</p>
<p>Autilização de Flavors no Flutter oferece uma solução elegante e eficiente para gerenciar múltiplos ambientes de desenvolvimento, teste e produção dentro de um único código-base.</p>
<p>Com a configuração adequada, é possível personalizar comportamentos, variáveis e até mesmo integrações específicas para cada ambiente, facilitando o desenvolvimento e a manutenção do aplicativo.</p>
<p>Além disso, a integração com serviços como o Firebase é simplificada, garantindo que cada Flavor possa operar com suas próprias configurações sem complicações adicionais.</p>
<p>Em artigos futuros, veremos como usar outros recursos combinado com os flavors para configurar apps como <a target="_blank" href="https://tecnoblog.net/responde/o-que-e-uma-plataforma-white-label/">white-label</a> por exemplo.</p>
<p>Espero que você tenha gostado e obrigado por acompanhar até aqui! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a><strong>(X)</strong> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Utilizando o Firebase App Distribution para distribuir e testar seus aplicativos]]></title><description><![CDATA[Fala, devs. Blz? Hoje vamos dar continuidade a série “Dominando o Firebase em Aplicativos Flutter” uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙
Seja para autenticação de usuá...]]></description><link>https://ianoliveira.dev/utilizando-o-firebase-app-distribution-para-distribuir-e-testar-seus-aplicativos</link><guid isPermaLink="true">https://ianoliveira.dev/utilizando-o-firebase-app-distribution-para-distribuir-e-testar-seus-aplicativos</guid><category><![CDATA[app distribution]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[Dart]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Wed, 24 Apr 2024 14:56:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1713960931792/9d1a5140-672e-405f-93de-db8898375a09.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, devs. Blz? Hoje vamos dar continuidade a <a target="_blank" href="https://ianoliveira.hashnode.dev/serie-dominando-o-firebase-em-aplicativos-flutter"><strong>série</strong></a> “Dominando o Firebase em Aplicativos Flutter” uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙</p>
<p>Seja para autenticação de usuários, armazenamento de dados, envio de notificações push ou captura e análise de erros, seus produtos sempre me ofereceram a solução perfeita.</p>
<p>Segundo o <a target="_blank" href="https://firebase.blog/posts/2022/05/whats-new-at-google-io"><strong>blog oficial do Firebase</strong></a> “Mais de 3 milhões de desenvolvedores, de startups a empresas, usam o Firebase para alcançar e envolver bilhões de usuários”</p>
<p>Hoje meu objetivo é abordar o uso do <strong>App Distribution</strong>, uma ferramenta que ajuda você rapidamente a distribuir seus aplicativos para os testadores sem ter que passar pelo estresse de subir o arquivo compilado do app para duas plataformas separadas, como Testflight para iOS e Google Play Console para Android.</p>
<p>O Firebase App Distribution faz parte do Firebase assim como outros serviços.</p>
<p>Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-o-que-e-firebase-app-distribution">O que é Firebase App Distribution?</h3>
<p>Segundo a <a target="_blank" href="https://firebase.google.com/docs/app-distribution?hl=pt-br">documentação</a> oficial "O Firebase App Distribution é um serviço que facilita a distribuição dos seus aplicativos para trusted testers (testadores confiáveis). Ao disponibilizar seus apps para os testers rapidamente, é possível receber feedback com antecedência e frequência.</p>
<p>Além disso, se você usar o Crashlytics nos seus aplicativos, receberá automaticamente métricas de estabilidade para todos os seus builds, para saber quando está tudo pronto para o envio."</p>
<p>Depois de concluir a configuração, o upload e a distribuição de apps geralmente são bem rápidos.</p>
<h3 id="heading-utilizando-o-firebase-app-distribution">Utilizando o Firebase App Distribution</h3>
<p><strong>Passo #1: Adicionando Firebase ao seu aplicativo</strong></p>
<p>Nesse artigo não irei ensinar a configurar o firebase pois fiz isso em outro post, você pode ler-lo <a target="_blank" href="https://ianoliveira.dev/configurando-o-firebase-no-flutter">aqui</a>.</p>
<p><strong>Passo #2: Ativando a distribuição de aplicativos no Firebase Console</strong></p>
<p>Acesse <a target="_blank" href="https://console.firebase.google.com/">o Firebase Console</a> em seu projeto e ative o App Distribution. Você pode encontrar o App Distribution no painel esquerdo em <strong>Liberar e Monitorar.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713960101312/84958c67-6d2f-45a1-a770-479a8525115d.png" alt="Firebase App Distribution" class="image--center mx-auto" /></p>
<p>Depois de clicar em <strong>Vamos começar,</strong> você chegará à página inicial do App Distribution, que se parece com o seguinte:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713960211529/877aa00d-9ac9-486e-a183-f5a84cc796c0.png" alt="Firebase App Distribution" class="image--center mx-auto" /></p>
<h3 id="heading-distribuindo-uma-compilacao-para-android">Distribuindo uma compilação para Android</h3>
<p>Para distribuir seu app aos testadores android, faça upload do arquivo APK usando o Firebase console:</p>
<ol>
<li><p>Abra a <a target="_blank" href="https://console.firebase.google.com/project/_/appdistribution?hl=pt-br">página App Distribution</a> do Firebase console. Selecione seu projeto do Firebase quando solicitado.</p>
</li>
<li><p>Na Aba <strong>Lançamentos</strong>(Releases), selecione o aplicativo que deseja distribuir no menu suspenso.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713831653191/65b395e0-74f1-4868-82a3-3a203d19827f.png" alt class="image--center mx-auto" /></p>
<p>Gere o arquivo APK do seu aplicativo com o comando <strong>flutter build apk --release e</strong> depois de gerá-lo com sucesso faça o upload dele.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713923360510/8714f3e8-91a5-430d-a3f3-2d0fa31dcece.png" alt class="image--center mx-auto" /></p>
<p>Com o arquivo gerado, na aba <strong>lançamentos</strong>, arraste e solte ou navegue pela compilação (APK/AAB/IPA) no Firebase App Distribution. Aguarde até que seu aplicativo seja carregado no Firebase Console. Veja o print abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713960629582/44ccee00-9f35-4be7-8784-b3a5775d6f8f.png" alt="Adicionar testadores" class="image--center mx-auto" /></p>
<p>Assim que a compilação for carregada com sucesso, você será convidado a adicionar quem vão ser os testadores dessa versão. A aba <strong>Testadores e Grupos</strong> pode ser usada para essa configuração onde você irá cadastrar um tester ou um grupo com vários testers.</p>
<p>A compilação que você carrega será distribuída a esses testadores. Você pode verificar a <a target="_blank" href="https://firebase.google.com/docs/app-distribution/add-remove-testers?platform=ios&amp;hl=pt-br">documentação</a> para obter mais detalhes sobre o assunto.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713923924972/504c5c50-febf-4370-98de-af2c9790e2df.png" alt class="image--center mx-auto" /></p>
<p>A última etapa é adicionar as notas de versão e clicar em <strong>Distribuir</strong> e ele estará disponível para todos os seus testadores.</p>
<p>É isso. Seu aplicativo é enviado para seus testadores 👨🏼‍🔧.</p>
<p><mark>OBS: Depois de distribuir seu build, ele ficará disponível no painel App Distribution do Firebase console por 150 dias. Quando faltam 30 dias para a compilação expirar, um aviso de expiração aparece no console e na lista de compilações do testador em seu dispositivo de teste.</mark></p>
<h3 id="heading-como-testar">Como testar?</h3>
<p>Os testadores irão receber um email com um convite enviado pelo Firebase App Distribution, abra o email e clique no link. Você será redirecionado para o aplicativo da Web do testador <strong>do Firebase App Distribution</strong>, faça login com sua conta do Google e toque em <strong>Aceitar convite.</strong></p>
<p>Agora você pode ver o aplicativo para o qual foi convidado a testar.</p>
<p>Se você quiser também pode de forma opcional instalar e utilizar <strong>o Firebase App Tester,</strong> que evita que as versões baixadas sejam adicionadas à pasta <code>Downloads</code> do seu celular.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713960722715/4fb591a4-7e30-45e4-bb1a-2daf49ba7370.png" alt class="image--center mx-auto" /></p>
<p>Toque em <strong>Fazer o download</strong> e assim que o download for concluído, seu lançamento aparecerá automaticamente como um atalho na tela inicial do seu dispositivo.</p>
<h3 id="heading-distribuindo-uma-compilacao-para-ios">Distribuindo uma compilação para IOS</h3>
<p>Para distribuir seu app aos testadores IOS, teremos que fazer algumas configurações extras no portal do desenvolvedor Apple. A primeira coisa é registrar os dispositivos do testador.</p>
<p>Um <a target="_blank" href="https://developer.apple.com/videos/play/wwdc2019/304/"><strong><em>build ad-hoc</em></strong></a> não é assinado com um perfil Enterprise. Um dispositivo só vai conseguir instalar um build ad-hoc se o identificador exclusivo do dispositivo (UDID, na sigla em inglês) estiver incluído no perfil de provisionamento do build.</p>
<p>Faça login em sua <strong>conta de desenvolvedor Apple</strong> e selecione <strong><em>Certificados, identificadores e perfis</em></strong> . Em seguida, selecione a seção <strong>Dispositivos</strong> à esquerda.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713961329805/9a991631-bbab-433c-a7c1-fdb903561302.png" alt class="image--center mx-auto" /></p>
<p>Clique em registrar um novo dispositivo e você chegará a uma tela parecida com essa abaixo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713958112547/7faad22b-80d0-48f0-a9a0-194a761d51f6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-encontrando-seu-udid-com-finder-macos"><strong>Encontrando seu</strong> UDID <strong>com Finder (macOS)</strong></h3>
<p>Plugue seu Iphone no seu mac e navegue até o Finder e selecione-o, você verá algumas informações sobre o celular conectado. Para mim tive que clicar algumas vezes nos dados abaixo do nome do Iphone para mostrar o UDID com sucesso!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713958906414/149704e4-524d-47bc-869a-fc1bc19174a6.png" alt="Finder" class="image--center mx-auto" /></p>
<h3 id="heading-maneira-alternativa-de-encontrar-udid-com-o-xcode"><strong>Maneira alternativa de encontrar UDID com o Xcode</strong></h3>
<ul>
<li><p>Conecte seu dispositivo iOS ao Xcode</p>
</li>
<li><p>Abra o menu <strong>Janela</strong> &gt; <strong>Dispositivos e Simuladores</strong></p>
</li>
<li><p>Encontre o seu dispositivo exibido nesta lista e visualize-o no <strong>Identifier</strong> “identificador” que é o mesmo <strong>UDID.</strong></p>
</li>
</ul>
<p>Depois de inserir com sucesso <em>o UUID</em> e o nome, continue o processo. Em seguida, <em>aceite</em> e <em>registre</em> o dispositivo.</p>
<p><strong>Aceitando o convite e Instalando o Certificado</strong></p>
<ol>
<li><p>Em seu dispositivo iOS de teste, abra o e-mail enviado pelo Firebase App Distribution e toque no link <strong>Get Started</strong>. Certifique-se de abrir o link no Safari.</p>
</li>
<li><p>No aplicativo da Web do testador <strong>do Firebase App Distribution</strong> exibido, faça login com sua conta do Google e toque em <strong>Aceitar convite.</strong></p>
</li>
<li><p>Toque em <strong>Registrar dispositivo</strong> para compartilhar seu UDID com o Firebase para que você possa atualizar o perfil de provisionamento do seu aplicativo posteriormente.</p>
</li>
<li><p>Siga as instruções e vá para configurações para baixar o perfil e compartilhar seu UDID.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713966783817/bf0a9284-21e5-4af5-9884-1ab293946894.png" alt class="image--center mx-auto" /></p>
<p> Quando seu dispositivo for registrado com sucesso deve aparecer um popup como esse abaixo.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713967147211/8803a2a4-2a7d-478b-ac41-e1b89e2dd5c7.png" alt class="image--center mx-auto" /></p>
<p> Agora envie uma nova versão do aplicativo para o testador e ele poder baixar e instalar com sucesso.</p>
</li>
</ol>
<h3 id="heading-gerando-o-ipa-de-compilacao">Gerando o IPA de compilação</h3>
<p>Para criar um arquivo IPA, abra o Xcode, navegue até <strong>Assinatura e Recursos</strong> e selecione uma equipe de desenvolvimento.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713963265122/e060c67a-317f-4029-a258-5fc43e885c8c.png" alt="Xcode" class="image--center mx-auto" /></p>
<p>Quando estiver pronto para distribuir uma versão de pré-lançamento de seu aplicativo para testadores, selecione "Qualquer dispositivo iOS (arm64)" como destino de compilação e <strong>Produto</strong>-&gt;<strong>Arquivo</strong>. Depois que o arquivo for criado, crie uma distribuição assinada com o perfil de distribuição de desenvolvimento.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713965815553/31c18f87-6453-472f-830c-9865293faca0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713965925376/0101288f-3ea7-45ec-8818-08131204c231.png" alt="Gerando o Archive" class="image--center mx-auto" /></p>
<p>Quando a compilação for concluída, será mostrado uma tela como essa abaixo onde contém o arquivo de compilação gerado:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713967691622/d2f81845-b4a7-4588-88b3-b528fc3d870c.png" alt="Distribuindo a compilação" class="image--center mx-auto" /></p>
<p>Clique em <strong>Distribute App.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713967763148/ad36aec2-4c8f-489f-a732-45978e4aa246.png" alt class="image--center mx-auto" /></p>
<p>Selecione o método de distribuição correto que para o nosso caso será <strong>Debugging</strong> e em seguida prossiga para distribuição. Espere o processamento.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713967912516/6504a0da-3a46-4f14-8527-a620c9c11906.png" alt class="image--center mx-auto" /></p>
<p>Será salvo um arquivo IPA e alguns arquivos de log na pasta especificada.</p>
<p>Agora você distribui o arquivo IPA para seus testadores fazendo o upload no Firebase e selecionando os testadores para essa compilação. 🛠️🎉</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713968209070/eac8b9d1-e19f-4d65-81d8-2eb817b362be.png" alt class="image--center mx-auto" /></p>
<p>Ufa, é isso, chegamos ao fim de mais um super tutorial 😎📲</p>
<h3 id="heading-conclusao"><strong>Conclusão</strong></h3>
<p>Bom é isso 😎.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718681471575/c663b56d-cc60-40a8-ba7c-b2fb9aaf4f2e.gif" alt class="image--center mx-auto" /></p>
<p>O Firebase App Distribution se destaca como uma ferramenta robusta e completa para a distribuição de aplicativos móveis, oferecendo diversos benefícios para desenvolvedores e testadores além da rapidez e eficiência para simplificar o processo de distribuição de aplicativos.</p>
<p>Em última análise, ao adotar o Firebase App Distribution, as equipes de desenvolvimento estão posicionadas para alcançar maior produtividade.</p>
<p>Onde eu trabalho usamos o Firebase App Distribution ativamente para enviar compilações para os QAs.</p>
<p>Em artigos futuros da série, veremos como usar outros recursos do Firebase como: Authentication, Crashlytics, Remote Config e muito mais com Flutter.</p>
<p>Espero que você tenha gostado e obrigado por acompanhar até aqui! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a><strong>(X)</strong> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[CRUD (Create, Read, Update, Delete) com Firebase Cloud Firestore no Flutter]]></title><description><![CDATA[Fala, devs. Blz? Hoje vamos dar continuidade a série "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙
Seja para autenticação de usuá...]]></description><link>https://ianoliveira.dev/crud-create-read-update-delete-com-firebase-cloud-firestore-no-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/crud-create-read-update-delete-com-firebase-cloud-firestore-no-flutter</guid><category><![CDATA[Firebase]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[serverless]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Dart]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Sun, 31 Mar 2024 19:58:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1711895150403/0bd6f2ff-5548-4fd5-beb9-2983bcd5766b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, devs. Blz? Hoje vamos dar continuidade a <a target="_blank" href="https://ianoliveira.hashnode.dev/serie-dominando-o-firebase-em-aplicativos-flutter"><strong>série</strong></a> "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙</p>
<p>Seja para autenticação de usuários, armazenamento de dados, envio de notificações push ou captura e análise de erros, seus produtos sempre me ofereceram a solução perfeita.</p>
<p>Segundo o <a target="_blank" href="https://firebase.blog/posts/2022/05/whats-new-at-google-io"><strong>blog oficial do Firebase</strong></a> "Mais de 3 milhões de desenvolvedores, de startups a empresas, usam o Firebase para alcançar e envolver bilhões de usuários"</p>
<p>Hoje meu objetivo é abordar o uso do Cloud Firebase um banco de dados NoSQL flexível e escalonável, criado com a infraestrutura do Google Cloud, para armazenar e sincronizar dados no desenvolvimento do cliente e do servidor.</p>
<p>Construiremos um aplicativo de lista de tarefas de exemplo usando o Flutter e Firebase onde executaremos algumas operações com dados.</p>
<p>Vamos usar o design criado por <a target="_blank" href="https://dribbble.com/Diaa_Mohamed_2"><strong>Diaa Mohamed</strong></a> disponível no <a target="_blank" href="https://dribbble.com/shots/22781589-Todo-List-App">Dribbble</a> para nos inspirar na construção do nosso app usando firebase.</p>
<p>Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-o-que-e-um-crud">O que é um Crud?</h3>
<p>CRUD é um acrônimo que representa as quatro operações básicas usadas em sistemas de gerenciamento de banco de dados relacionais ou em serviços de API que interagem com recursos. As operações são:</p>
<ol>
<li><p><strong>Create (Criar)</strong>: Envolve a criação de novos registros ou recursos no banco de dados ou sistema.</p>
</li>
<li><p><strong>Read (Ler)</strong>: Envolve a recuperação de dados existentes do banco de dados ou sistema.</p>
</li>
<li><p><strong>Update (Atualizar)</strong>: Envolve a modificação dos dados existentes no banco de dados ou sistema.</p>
</li>
<li><p><strong>Delete (Excluir)</strong>: Envolve a remoção de registros ou recursos existentes do banco de dados ou sistema.</p>
</li>
</ol>
<p>Essas operações são essenciais em muitas aplicações de software para realizar operações básicas de manipulação de dados. Quando se fala em desenvolvimento web, por exemplo, CRUD é uma abordagem comum para a implementação de funcionalidades de back-end que permitem aos usuários criar, ler, atualizar e excluir dados em um sistema.</p>
<p>No contexto do Firebase, um CRUD refere-se às operações básicas que podem ser realizadas em seu banco de dados em tempo real, que geralmente é o Firebase Realtime Database ou o Firestore 🔥.</p>
<h3 id="heading-o-que-e-cloud-firestore">O que é Cloud Firestore?</h3>
<p><a target="_blank" href="https://www.youtube.com/watch?v=v_hR4K4auoQ&amp;list=PLl-K7zZEsYLluG5MCVEzXAQ7ACZBCuZgZ">O Cloud Firestore</a> é um banco de dados flexível e escalonável para desenvolvimento focado em dispositivos móveis, Web e servidores pelo Firebase e do Google Cloud.</p>
<p>Ele mantém seus dados sincronizados entre aplicativos clientes por meio de ouvintes em tempo real e oferece suporte off-line para que você possa criar aplicativos responsivos que funcionam independentemente da latência da rede ou da conectividade com a Internet.</p>
<p>Alguns dos principais recursos são:</p>
<p><strong>Sincronização em tempo real</strong>: O Firestore oferece atualizações em tempo real para os clientes conectados. Isso significa que os dados são sincronizados automaticamente entre os diferentes dispositivos e plataformas em tempo real, permitindo uma experiência de usuário fluida e em tempo real.</p>
<p><strong>Consultas ricas</strong>: O Firestore suporta uma variedade de consultas, incluindo consultas simples, consultas compostas e ordenação. Isso permite que os desenvolvedores recuperem dados de maneira eficiente e flexível.</p>
<p><strong>Estrutura de dados escalável</strong>: O Firestore organiza os dados em coleções e documentos. Ele permite uma estrutura hierárquica flexível, o que facilita a organização e a consulta de dados.</p>
<p><strong>Escalabilidade automática</strong>: O Firestore é altamente escalável e gerenciado pelo Google Cloud Platform. Ele escala automaticamente para atender às demandas de tráfego e armazenamento, garantindo alta disponibilidade e desempenho.</p>
<p><strong>Suporte off-line:</strong> Armazena em cache os dados ativamente usados pelo aplicativo. Dessa maneira, o aplicativo poderá escrever, ler, detectar e consultar dados, mesmo que o dispositivo esteja desconectado. Quando o dispositivo retorna ao estado on-line, as alterações locais são sincronizadas novamente no Cloud Firestore.</p>
<p><mark>Se você quiser se aprofundar um pouco mais no funcionamento deixo essa </mark> <a target="_blank" href="https://www.youtube.com/watch?v=v_hR4K4auoQ&amp;list=PLl-K7zZEsYLluG5MCVEzXAQ7ACZBCuZgZ"><mark>playlist</mark></a> <mark> muito completa sobre o assunto.</mark></p>
<h3 id="heading-modelo-de-dados-do-cloud-firestore">Modelo de dados do Cloud Firestore</h3>
<p>O Cloud Firestore utiliza um modelo de dados NoSQL orientado a documentos, o que significa que ele difere de um banco de dados relacional SQL. Ao invés de tabelas e linhas, você armazena dados em documentos que posteriormente são organizados em coleções.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710988444587/42b5d498-e8db-42a7-80ec-788dbbef70f2.png" alt="Coleções contem vários documentos" class="image--center mx-auto" /></p>
<p>Veja alguns pontos-chave sobre o modelo de dados do Firestore:</p>
<ul>
<li><p><strong>Documentos:</strong> Cada documento age como uma unidade de dados auto-contida, similar a uma linha em uma tabela relacional. Documentos contêm pares chave-valor, onde a chave é uma string que identifica o dado e o valor pode ser de diversos tipos como strings, números, booleanos, objetos, arrays, referências a outros documentos, entre outros.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711244196562/1dc63c6e-3e81-4473-9de0-36244d41caac.png" alt="Exemplo de documento" class="image--center mx-auto" /></p>
</li>
<li><p><strong>Coleções:</strong> Documentos relacionados logicamente são agrupados em coleções. Pense em coleções como pastas que organizam seus documentos. Por exemplo, você pode ter uma coleção "usuarios" para armazenar documentos de usuários do sistema, e cada documento representaria um usuário individual</p>
</li>
<li><p><a target="_blank" href="https://firebase.google.com/docs/firestore/data-model?hl=pt-br"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711244386200/4397b99a-55dd-4c55-b7db-59a88742b0bb.png" alt class="image--center mx-auto" /></a></p>
</li>
<li><p><strong>Sem Esquema:</strong> Firestore é schemaless, ou seja, não possui um esquema rígido que define a estrutura dos dados. Isso oferece flexibilidade, pois você pode adicionar novos campos a documentos existentes sem precisar modificar toda a coleção.</p>
</li>
<li><p><strong>Hierarquia:</strong> Documentos podem conter subcoleções, permitindo uma modelagem hierárquica dos seus dados. Por exemplo, a coleção "usuarios" poderia conter uma subcoleção "pedidos" para armazenar os pedidos realizados por cada usuário.</p>
</li>
</ul>
<h2 id="heading-cloud-firestore-x-realtime-database-qual-devo-usar">Cloud Firestore X Realtime Database: qual devo usar?</h2>
<p>O Realtime Database é um banco de dados que usa documentos JSON para armazenar os dados em pares de chave-valor enquanto o Cloud Firestore é uma versão mais recente do banco de dados que usa coleções de documentos para armazenar dados.</p>
<p>Existe algumas diferenças entre eles e abaixo vou citar 2 dos principais.</p>
<ul>
<li><p><strong>Modelo de Dados</strong>:</p>
<ul>
<li><p><strong>Realtime Database</strong>: Utiliza um modelo de dados JSON em tempo real. Isso significa que os dados são sincronizados em tempo real entre todos os clientes que estão conectados ao banco de dados.</p>
</li>
<li><p><strong>Cloud Firestore</strong>: Usa um modelo de dados de documentos coleções. Isso permite uma estrutura hierárquica mais flexível para dados, onde os documentos podem conter coleções aninhadas.</p>
</li>
</ul>
</li>
<li><p><strong>Preço</strong>:</p>
<ul>
<li><p><strong>Realtime Database</strong>: O modelo de preços é baseado na largura de banda e no espaço de armazenamento utilizados.</p>
</li>
<li><p><strong>Cloud Firestore</strong>: O modelo de preços é baseado na quantidade de leituras, gravações, exclusões e largura de banda utilizadas. Nesse caso um ponto de atenção ao modelar sua base 🚨🚨.</p>
</li>
</ul>
</li>
</ul>
<p><strong>OBS</strong>. Qual usar depende muito das necessidades específicas do seu projeto:</p>
<ul>
<li><p><strong>Realtime Database</strong> é uma boa escolha se você precisa de sincronização em tempo real de dados simples e tem requisitos de escalabilidade moderados.</p>
</li>
<li><p><strong>Cloud Firestore</strong> é preferível para aplicativos que requerem uma estrutura de dados mais complexa, consultas flexíveis e alta escalabilidade.</p>
</li>
</ul>
<p>Em resumo, se você precisa de uma estrutura de dados mais flexível, consultas poderosas e escalabilidade robusta, o Cloud Firestore é provavelmente a melhor opção. Se você precisa de uma sincronização em tempo real simples e não tem requisitos de consulta muito complexos, o Realtime Database pode ser mais adequado.</p>
<p>Se você quiser se aprofundar um pouco mais nesse assunto acesse os links abaixo.</p>
<ol>
<li><p><a target="_blank" href="https://firebase.google.com/docs/firestore/rtdb-vs-firestore?hl=pt-br">https://firebase.google.com/docs/firestore/rtdb-vs-firestore?hl=pt-br</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/46549766/whats-the-difference-between-cloud-firestore-and-the-firebase-realtime-database">https://stackoverflow.com/questions/46549766/whats-the-difference-between-cloud-firestore-and-the-firebase-realtime-database</a></p>
</li>
</ol>
<h3 id="heading-ativando-o-firestore">Ativando o Firestore</h3>
<p>Vamos utilizar o projeto <strong>flutter-firebase-app</strong> que criamos e configuramos no artigo passado, se você é novo <a target="_blank" href="https://ianoliveira.dev/configurando-o-firebase-no-flutter">acesse aqui.</a></p>
<p>1 - Vá até o console do Firebase e clique no seu projeto. No menu <strong>Criação</strong> , clique em <strong>Firestore Database &gt; Criar banco de dados</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711310955432/826163b4-e3da-4166-988e-68722fee48d4.png" alt="Ativação do cloud firestore" class="image--center mx-auto" /></p>
<p>2 - A próxima tela aparecerá solicitando que você selecione o local que será hospedado o banco de dados. Você pode usar o padrão mas fique certo que não poderá alterar o local posteriormente.<br />Selecionar o local do banco de dados do Firestore durante a ativação é crucial por várias razões como:</p>
<ol>
<li><p><strong>Latência</strong>: Escolher um local próximo aos usuários finais reduz a latência e melhora a experiência do usuário.</p>
</li>
<li><p><strong>Conformidade</strong>: Pode ser necessário garantir que os dados estejam armazenados em uma região específica devido a requisitos legais ou regulatórios.</p>
</li>
<li><p><strong>Resiliência</strong>: Distribuir os dados em vários locais aumenta a resiliência da aplicação, garantindo disponibilidade mesmo em caso de falhas em um data center.</p>
</li>
<li><p><strong>Custo</strong>: Escolher o local mais econômico pode reduzir os custos operacionais, já que alguns provedores de nuvem podem cobrar taxas diferentes com base na localização dos servidores.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711311251876/eadf4c4f-50dc-48e6-bcfa-8cd4047b2842.png" alt class="image--center mx-auto" /></p>
<p>3 - Selecione <strong>Iniciar em modo de teste</strong> e leia a isenção de responsabilidade sobre as regras de segurança. O modo de teste garante que você possa gravar livremente no banco de dados durante o desenvolvimento. Em seguida, clique no botão <strong>Criar</strong> para prosseguir.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711311489053/95d1cd55-5c6a-4652-ae58-28fb658eb7d2.png" alt class="image--center mx-auto" /></p>
<p><mark>🚨 Para seus aplicativos, especialmente aplicativos de produção, é importante proteger seu banco de dados com regras de segurança. Para saber mais sobre regras de segurança, consulte </mark> <a target="_blank" href="https://firebase.google.com/docs/rules?hl=pt-br"><mark>Regras de segurança do Firebase .</mark></a></p>
<h3 id="heading-fazendo-o-crud-no-firestore"><strong>Fazendo o CRUD no Firestore</strong></h3>
<p>Adicione o package do cloud firestore no seu projeto</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-attr">cloud_firestore:</span> <span class="hljs-string">^4.15.10</span>
</code></pre>
<p>No Firestore teremos uma coleção chamada <code>todos</code> que seria usada para armazenar dados relacionados a cada um dos itens de tarefas que os usuários podem adicionar, editar ou remover.</p>
<p>Cada item consistirá nos seguintes campos (os tipos de dados são escritos entre colchetes):</p>
<ul>
<li><p><code>title</code> (String): armazena o nome da tarefa pendente</p>
</li>
<li><p><code>createdAt</code> (Timestamp): data de criação da pendência</p>
</li>
<li><p><code>completed</code> (Booleano): se a tarefa pendente foi concluída</p>
</li>
<li><p><code>id</code>(String): identificador exclusivo de uma tarefa</p>
</li>
</ul>
<p>No Dart, vamos desenvolver um objeto para manipular esses dados e facilitar a integração com o Firestore. No entanto, os dados são intercambiados com o Firestore no formato JSON. Portanto, nosso modelo deve incluir uma funcionalidade para converter os dados de e para um objeto Dart.</p>
<p>Para essa conversão, podemos implementar um método <code>toMap()</code> que será responsável por retornar um <code>Map</code> quando dado um objeto Dart, e também podemos utilizar um construtor de fábrica <code>fromJson</code> para facilitar a conversão de JSON para objetos Dart. Aqui está um exemplo de como isso pode ser feito:</p>
<p>Com esse código, você pode facilmente criar objetos <code>Todo</code> a partir de dados JSON usando o construtor <code>fromJson</code>, e também pode converter objetos <code>Todo</code> em um formato que pode ser armazenado ou transmitido como JSON usando o método <code>toMap()</code>.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:cloud_firestore/cloud_firestore.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoModel</span> </span>{
  <span class="hljs-built_in">String?</span> id;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> title;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> completed;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">DateTime</span> createdAt;

  TodoModel({
    <span class="hljs-keyword">this</span>.id,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.title,
    <span class="hljs-keyword">this</span>.completed = <span class="hljs-keyword">false</span>,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.createdAt,
  });

  <span class="hljs-comment">// Construtor Factory para converter JSON em objeto Dart</span>
  <span class="hljs-keyword">factory</span> TodoModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> TodoModel(
      id: json[<span class="hljs-string">'id'</span>],
      title: json[<span class="hljs-string">'title'</span>],
      completed: json[<span class="hljs-string">'completed'</span>],
      createdAt: <span class="hljs-built_in">DateTime</span>.fromMicrosecondsSinceEpoch(
        (json[<span class="hljs-string">'createdAt'</span>] <span class="hljs-keyword">as</span> Timestamp).microsecondsSinceEpoch,
      ),
    );
  }
  <span class="hljs-comment">// Método para converter objeto Dart em um Map</span>
  <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; toMap() {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-string">'title'</span>: title,
      <span class="hljs-string">'completed'</span>: completed,
      <span class="hljs-string">'createdAt'</span>: createdAt,
    };
  }

  TodoModel copyWith({
    <span class="hljs-built_in">String?</span> id,
    <span class="hljs-built_in">String?</span> title,
    <span class="hljs-built_in">bool?</span> completed,
    <span class="hljs-built_in">DateTime?</span> createdAt,
  }) {
    <span class="hljs-keyword">return</span> TodoModel(
      id: id ?? <span class="hljs-keyword">this</span>.id,
      title: title ?? <span class="hljs-keyword">this</span>.title,
      completed: completed ?? <span class="hljs-keyword">this</span>.completed,
      createdAt: createdAt ?? <span class="hljs-keyword">this</span>.createdAt,
    );
  }
}
</code></pre>
<h3 id="heading-gravando-dados">Gravando dados</h3>
<ul>
<li><p><a target="_blank" href="https://firebase.google.com/docs/rules?hl=pt-br"><strong>Creat</strong></a><strong>e (Criar)</strong>: No Firebase, você pode criar novos registros no banco de dados usando uma operação de escrita, como <code>.set()</code> ou <code>.add()</code> dependendo do tipo de banco de dados que você está usando.</p>
<p>  Ao usar <code>set()</code> para criar um documento, você precisa especificar um ID para ele. Exemplo:</p>
<pre><code class="lang-dart">  db.collection(<span class="hljs-string">"cities"</span>).doc(<span class="hljs-string">"new-city-id"</span>).<span class="hljs-keyword">set</span>({<span class="hljs-string">"name"</span>: <span class="hljs-string">"Chicago"</span>});
</code></pre>
<p>  No entanto, às vezes não há um ID significativo para o documento. É mais prático que o Cloud Firestore gere um automaticamente para você. Para fazer isso, podemos usar o <code>add()</code> na hora de criar o novo registro. Em nosso aplicativo de exemplo vamos utilizar-lo.</p>
<p>  <strong>Adicionar uma tarefa (todo) (CRIAR):</strong></p>
<p>  O método <strong>addTodo</strong> é definido para adicionar uma nova tarefa à coleção ‘todos’ no Firestore. Veja o exemplo abaixo.</p>
</li>
</ul>
<pre><code class="lang-dart">  Future&lt;<span class="hljs-built_in">String</span>&gt; addTodo(TodoModel model) <span class="hljs-keyword">async</span> {
     <span class="hljs-keyword">try</span> {
          <span class="hljs-keyword">var</span> snapshot = <span class="hljs-keyword">await</span> firestore.collection(<span class="hljs-string">'todos'</span>).add(model.toMap());
          <span class="hljs-keyword">return</span> snapshot.id;
        } <span class="hljs-keyword">on</span> FirebaseException <span class="hljs-keyword">catch</span> (e) {
          debugPrint(<span class="hljs-string">"Failed with error '<span class="hljs-subst">${e.code}</span>': <span class="hljs-subst">${e.message}</span>"</span>);
          <span class="hljs-keyword">throw</span> Exception(e.message);
        }
   }
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711910459592/9828ea05-8655-47f9-9135-cfa02219fb8b.gif" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Read (Ler)</strong>: Você pode ler dados do banco de dados usando operações de leitura, como <code>.get()</code> para Futures ou <code>.snapshots()</code> para Streams, que permitem recuperar dados de um caminho específico no banco de dados em tempo real.</p>
<p>  <strong>Obtenha tarefas (LER):</strong></p>
<p>  O método <strong>getTodos</strong> é implementado para recuperar a lista de dados da coleção de '<strong>todos</strong>'.</p>
<ul>
<li><pre><code class="lang-dart">    Future&lt;<span class="hljs-built_in">List</span>&lt;TodoModel&gt;&gt; getTodos() <span class="hljs-keyword">async</span> {
        <span class="hljs-keyword">try</span> {
          <span class="hljs-keyword">var</span> snapshot = firestore.collection(<span class="hljs-string">'todos'</span>).<span class="hljs-keyword">get</span>();
          <span class="hljs-keyword">return</span> snapshot.then(
            (querySnapshot) {
              <span class="hljs-keyword">return</span> querySnapshot.docs.map((todo) {
                <span class="hljs-keyword">var</span> mapData = todo.data();
                mapData[<span class="hljs-string">'id'</span>] = todo.id;
                <span class="hljs-keyword">return</span> TodoModel.fromJson(mapData);
              }).toList();
            },
          );
        } <span class="hljs-keyword">on</span> FirebaseException <span class="hljs-keyword">catch</span> (e) {
          debugPrint(<span class="hljs-string">"Failed with error '<span class="hljs-subst">${e.code}</span>': <span class="hljs-subst">${e.message}</span>"</span>);
          <span class="hljs-keyword">throw</span> Exception(e.message);
        }
      }
</code></pre>
</li>
</ul>
</li>
</ul>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711910831452/6c832c69-8eca-471f-84f4-16ada08b4d38.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Update (Atualizar)</strong>: Para atualizar dados existentes no Firebase, você pode usar a função <code>.update()</code> para fazer alterações em campos específicos de um registro, ou a função <code>.set()</code> com a opção <code>merge: true</code> para mesclar dados novos e existentes.</p>
<p>  Para atualizar alguns campos de um documento sem substituir o documento inteiro, o <code>update()</code> é o ideial pois em nosso app atualizaremos o campo <em>completed</em> quando finalizarmos uma task em nosso aplicativo.</p>
<p>  É possível configurar um campo no documento como um carimbo de data/hora do servidor que detecta quando o servidor recebe a atualização basta usar o <strong>FieldValue.serverTimestamp()</strong>. Veja o exemplo abaixo.</p>
<p>  <strong>Atualização de um todo (ATUALIZAÇÃO):</strong></p>
<p>  O método <strong>updateTodo</strong> é definido para atualizar um todo existente na coleção 'todos'. O método *.*<strong><em>doc(docId)</em></strong> : Obtém uma referência a um documento específico usando seu ID.</p>
<pre><code class="lang-dart">  Future&lt;<span class="hljs-keyword">void</span>&gt; updateTodo(<span class="hljs-built_in">String</span> id) <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">var</span> snapshot = firestore.collection(<span class="hljs-string">'todos'</span>).doc(id);
        <span class="hljs-keyword">await</span> snapshot.update({
          <span class="hljs-string">'completed'</span>: <span class="hljs-keyword">true</span>,
          <span class="hljs-string">'updateAt'</span>: FieldValue.serverTimestamp(),
        });
      } <span class="hljs-keyword">on</span> FirebaseException <span class="hljs-keyword">catch</span> (e) {
        debugPrint(<span class="hljs-string">"Failed with error '<span class="hljs-subst">${e.code}</span>': <span class="hljs-subst">${e.message}</span>"</span>);
        <span class="hljs-keyword">throw</span> Exception(e.message);
      }
    }
</code></pre>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711910595843/4f11bcce-2154-4506-9086-a0d6ed7897b6.gif" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Delete (Excluir)</strong>: Para excluir dados do Firebase, você pode usar a função <code>.delete()</code> para remover um registro específico do banco de dados.</p>
<p>  <strong>Excluir todo (DELETE):</strong></p>
<p>  O método <strong>deleteTodo</strong> é implementado para excluir um registro da coleção ‘todos’.</p>
</li>
<li><pre><code class="lang-dart">         Future&lt;<span class="hljs-keyword">void</span>&gt; deleteTodo(<span class="hljs-built_in">String</span> id) <span class="hljs-keyword">async</span> {
            <span class="hljs-keyword">try</span> {
              <span class="hljs-keyword">final</span> snapshot = firestore.collection(<span class="hljs-string">'todos'</span>).doc(id);
              <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> snapshot.delete();
            } <span class="hljs-keyword">on</span> FirebaseException <span class="hljs-keyword">catch</span> (e) {
              debugPrint(<span class="hljs-string">"Failed with error '<span class="hljs-subst">${e.code}</span>': <span class="hljs-subst">${e.message}</span>"</span>);
              <span class="hljs-keyword">throw</span> Exception(e.message);
            }
          }
</code></pre>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711911007177/d4017e0c-cd6e-49f4-b40c-076ac8500751.gif" alt class="image--center mx-auto" /></p>
<p>Essas operações CRUD são fundamentais para interagir com o banco de dados do Firestore e são usadas para criar, recuperar, atualizar e excluir dados em aplicativos desenvolvidos com o Firebase.</p>
<p>No nosso app de exemplo criamos uma classe chamada <strong><em>FirestoreService</em></strong> que fornece uma forma estruturada e modular de interagir com o banco de dados Firestore, implementando todas as operações necessárias.</p>
<p>Para mais informações sobre gerenciar dados no Firestore <a target="_blank" href="https://firebase.google.com/docs/firestore/manage-data/structure-data?hl=pt-br">clique aqui.</a></p>
<h3 id="heading-excluir-colecoes">Excluir coleções?</h3>
<p>O Firebase não nos dá um método diretamente para excluir toda uma coleção de dados. Uma forma que temos de excluir uma coleção ou subcoleção completa no banco, seria recuperar (leia) todos os documentos dentro da coleção ou subcoleção e os excluir. Abaixo deixo um exemplo de como fazer isso 😎.</p>
<p><mark>OBS: Esse processo gera custos de leitura e exclusão.</mark></p>
<pre><code class="lang-dart"> Future&lt;<span class="hljs-keyword">void</span>&gt; deleteAllData() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> snapshot = <span class="hljs-keyword">await</span> firestore.collection(<span class="hljs-string">'todos'</span>).<span class="hljs-keyword">get</span>();
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">List</span>&lt;DocumentSnapshot&gt; docs = snapshot.docs;
      <span class="hljs-keyword">for</span> (DocumentSnapshot doc <span class="hljs-keyword">in</span> docs) {
        <span class="hljs-keyword">await</span> doc.reference.delete();
      }
    } <span class="hljs-keyword">on</span> FirebaseException <span class="hljs-keyword">catch</span> (e) {
      debugPrint(<span class="hljs-string">"Failed with error '<span class="hljs-subst">${e.code}</span>': <span class="hljs-subst">${e.message}</span>"</span>);
      <span class="hljs-keyword">throw</span> Exception(e.message);
    }
  }
</code></pre>
<p>Para explorar o código completo do aplicativo de exemplo e se aprofundar nos detalhes da implementação, você pode encontrar o projeto completo no <a target="_blank" href="https://github.com/iang12/firebase-flutter-example">GitHub</a>. Fique à vontade para acessar o repositório através do seguinte <a target="_blank" href="https://github.com/iang12/firebase-flutter-example">link</a>:</p>
<p>Minha recomendação é que você baixe o projeto e dê uma olhada em toda a implementação pois além de Firebase, usei coisas como <a target="_blank" href="https://pub.dev/packages/provider/example">provider</a> e <a target="_blank" href="https://docs.flutter.dev/data-and-backend/state-mgmt/simple">change notifier</a> para termos um aplicativo mais completo.</p>
<h3 id="heading-conclusao"><strong>Conclusão</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711909968408/f295a1d1-37dc-4cd2-9a43-ef501195b200.gif" alt class="image--center mx-auto" /></p>
<p>Bom é isso 😎.</p>
<p>Neste artigo, você aprendeu como utilizar o Firestore em um aplicativo real realizando operações na base de dados.</p>
<p>Em artigos futuros da série, veremos como usar outros recursos do Firebase como: Authentication, Crashlytics, Remote Config e muito mais com Flutter.</p>
<p>Espero que você tenha gostado e obrigado por acompanhar até aqui! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Configurando o Firebase no Flutter]]></title><description><![CDATA[Fala, devs. Blz? Hoje vamos dar continuidade a série "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙
O Firebase realmente é uma fer...]]></description><link>https://ianoliveira.dev/configurando-o-firebase-no-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/configurando-o-firebase-no-flutter</guid><category><![CDATA[Firebase]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[android app development]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Wed, 13 Mar 2024 14:55:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709997567154/d4c5f7a2-2974-4dd8-8962-279b7902e600.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fala, devs. Blz? Hoje vamos dar continuidade a <a target="_blank" href="https://ianoliveira.hashnode.dev/serie-dominando-o-firebase-em-aplicativos-flutter">série</a> "Dominando o Firebase em Aplicativos Flutter" uma sequência de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙</p>
<p>O <a target="_blank" href="https://firebase.google.com/?hl=pt-br">Firebase</a> realmente é uma ferramenta muito boa e que acelera muito o desenvolvimento de novos aplicativos, ele é de fácil integração com o Flutter.</p>
<p>Seja para autenticação de usuários, armazenamento de dados, envio de notificações push ou captura e análise de erros, seus produtos sempre me ofereceram a solução perfeita.</p>
<p>Segundo o <a target="_blank" href="https://firebase.blog/posts/2022/05/whats-new-at-google-io">blog oficial do Firebase</a> "Mais de 3 milhões de desenvolvedores, de startups a empresas, usam o Firebase para alcançar e envolver bilhões de usuários"</p>
<p>Hoje meu objetivo é abordar a instalação do Firebase da maneira certa. Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-criando-um-novo-projeto-flutter">Criando um novo projeto Flutter</h3>
<p>Antes de instalar o Firebase vamos criar uma aplicação Flutter nova do zero para esse tutorial. Caso você não tenha ainda o SDK do Flutter instalado clique <a target="_blank" href="https://docs.flutter.dev/get-started/install">aqui</a>. Depois de configurar seu ambiente para desenvolder em Flutter, você pode executar o seguinte comando para criar um novo aplicativo:</p>
<pre><code class="lang-bash">flutter create --org com.labs flutterfirebaseapp --platform=ios,android
</code></pre>
<p>No comando acima o <strong><mark>--org</mark></strong> é o nome da sua organização responsável pelo seu novo projeto Flutter, em notação reversa de nome de domínio. Essa string é usada em nomes de pacotes Java e como prefixo no identificador de pacote configurável do iOS. (o padrão é "com.example") mas nós nomeamos para <strong>com.labs</strong> como nome de exemplo de domínio para esse app.</p>
<p>💡 Outra coisa que fiz para minimizar o tamanho do projeto é definir apenas as plataformas para as quais vamos construir o aplicativo. Nesse caso especifiquei android/ios. Esse comando <strong><mark>--platform=ios,android</mark></strong> impedirá a criação de dependências de aplicativos em outras plataformas como <code>Web</code>, <code>Desktop</code>etc.</p>
<h3 id="heading-instalacao-do-firebase">Instalação do Firebase 🔥</h3>
<p>Para instalar o Firebase em um aplicativo Flutter costumava envolver muitas etapas de configuração <a target="_blank" href="https://www.digitalocean.com/community/tutorials/flutter-firebase-setup">manual</a> específicas para cada plataforma, mas apartir da versão 2.8 do Flutter agora podemos <a target="_blank" href="https://firebase.google.com/docs/flutter/setup?hl=pt-br&amp;platform=ios">inicializar o Firebase</a> de uma nova forma diretamente do Dart.</p>
<p>Isso é possível graças à nova ferramenta <strong>FlutterFire CLI</strong> , que pode gerar a configuração correta do Firebase para o nosso projeto.</p>
<p>Nesse post vamos ver a forma nova que é mais prática e rápida mas se você ainda quiser usar a maneira antiga <a target="_blank" href="https://www.digitalocean.com/community/tutorials/flutter-firebase-setup">clique aqui</a>. Bora?</p>
<p>Antes de qualquer serviço do Firebase poder ser usado, você deve primeiro instalar o <a target="_blank" href="https://pub.dev/packages/firebase_core"><code>firebase_core</code></a> plugin, que é responsável por conectar seu aplicativo ao Firebase.</p>
<p>Adicione o plugin no <strong>pubspec.yaml</strong> do seu app e depois execute o comando <code>flutter pub get</code> basta salvar o arquivo e ele executará automaticamente o download da dependência.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-attr">firebase_core:</span> <span class="hljs-string">^2.27.0</span>
</code></pre>
<h3 id="heading-1-instalando-as-ferramentas-de-linha-de-comando-necessarias">1 - Instalando as ferramentas de linha de comando necessárias</h3>
<ol>
<li><p>Como <strong>o FlutterFire CLI</strong> é uma ferramenta de linha de comando, precisamos instalá-lo primeiro: <a target="_blank" href="https://firebase.google.com/docs/cli?hl=pt-br#setup_update_cli">Instale aqui</a>, caso ainda não tenha feito isso.</p>
</li>
<li><p>Agora no terminal faça login no Firebase com sua Conta do Google executando o seguinte comando:</p>
<pre><code class="lang-bash"> firebase login
</code></pre>
</li>
<li><p>Depois de ter feito login com sucesso instale também para o Flutter com o comando:</p>
<pre><code class="lang-bash"> dart pub global activate flutterfire_cli
</code></pre>
</li>
</ol>
<h3 id="heading-2-criando-um-novo-projeto-do-firebase">2 - Criando um novo projeto do Firebase</h3>
<ol>
<li><p>Acesse o site do <a target="_blank" href="https://console.firebase.google.com/">firebase console</a> e faça login com a sua conta do Google e então, vamos criar um novo projeto.</p>
</li>
<li><p>No console, clique em <strong>Adicionar projeto</strong>.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710105405548/574a9a35-baf1-43fb-9ed4-6c0f78be4d64.png" alt="Criando um novo projeto do Firebase" class="image--center mx-auto" /></p>
<p> No campo <strong>Nome do projeto</strong>, insira <strong>flutter-firebase-app</strong> e clique em <strong>Continuar</strong> .</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710105582426/45c1a177-53a3-4950-a154-90242f1d1c16.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><p>Clique nas opções de criação do projeto. Se solicitado, aceite os termos do Firebase, mas ignore a configuração do Google Analytics porque você não o usará neste aplicativo.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710106241581/613046e1-2abf-4da7-9ca5-50571ca0e213.png" alt class="image--center mx-auto" /></p>
<p> No diretório do projeto do Flutter que criamos, execute o seguinte comando para iniciar o fluxo de trabalho de configuração do app:</p>
</li>
<li><pre><code class="lang-bash">    flutterfire configure
</code></pre>
</li>
<li><p>Supondo que já tenhamos feito login por meio da CLI do Firebase ( <code>firebase login</code>se não, execute-o), isso listará todos os projetos do Firebase disponíveis:</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710337460724/5508b635-17cc-4e72-9554-38a0ff49c83c.png" alt class="image--center mx-auto" /></p>
<p> Depois de escolher o projeto correto vamos selecionar para quais plataformas queremos configurar o firebase, no nosso caso escolha Android e IOS. A CLI registra automaticamente o aplicativo para essas plataformas no console do FIrebase.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710202057361/512ad7d2-7b6a-4aa1-bc4e-235b0f90c752.png" alt class="image--center mx-auto" /></p>
<p> Depois de escolher e apertar <strong>Enter</strong> podemos ver que a configuração foi feita com sucesso 😎.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710202293242/1e624c02-c1fc-4652-80e2-7349f37c1aad.png" alt class="image--center mx-auto" /></p>
<p> Para confirmar abra o console do Firebase e navegue até configurações veja que dois aplicativos foram criados para o nosso projeto.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710202398718/1fddac27-3797-4f40-ba4f-5cfda68171de.png" alt="Aplicativos Firebase criados nas configurações dos projetos" class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-3-inicializando-o-firebase-no-seu-aplicativo">3 - Inicializando o Firebase no seu aplicativo</h3>
<p>Após a conclusão da etapa anterior, navegue até o seu código da pasta <code>lib</code> e veja que foi criado um arquivo novo <code>firebase_options.dart</code> .</p>
<p>Esse arquivo geralmente contém informações como o ID do projeto do Firebase, a chave de API, o ID do aplicativo, a URL do banco de dados em tempo real, entre outros detalhes de configuração necessários para estabelecer a conexão entre o aplicativo e os serviços do Firebase.</p>
<p>Para finalizar a integração vamos inicializar o Firebase apartir do nosso método <code>main</code>.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:firebase_core/firebase_core.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'firebase_options.dart'</span>;

<span class="hljs-keyword">void</span> main() <span class="hljs-keyword">async</span> {
  WidgetsFlutterBinding.ensureInitialized();
  <span class="hljs-keyword">await</span> Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(MyApp());
}
</code></pre>
<p>o <code>WidgetsFlutterBinding</code> é uma parte importante do ciclo de vida do aplicativo Flutter e pode ser usado para inicializar o Firebase juntamente com o aplicativo Flutter.</p>
<p>O <code>DefaultFirebaseOptions.currentPlatform</code>é importado do nosso <code>firebase_options.dart</code>arquivo que foi gerado.</p>
<p>Agora rodando nosso aplicativo no simulador deu tudo certo ✅</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710208002514/8281f982-ee5e-40c1-a4ab-324e2621cf30.png" alt class="image--center mx-auto" /></p>
<p>Depois de inicializado, você estará pronto para começar a usar as funcionalidades do Firebase 🤩.</p>
<p>Se quiser conferir o código esse é o <a target="_blank" href="https://github.com/iang12/firebase-flutter-example">link</a> do repositório no <a target="_blank" href="https://github.com/iang12/firebase-flutter-example">github</a>!</p>
<h3 id="heading-conclusao"><strong>Conclusão</strong></h3>
<p>Bom é isso 😎.</p>
<p><a target="_blank" href="https://dribbble.com/shots/22627336-Flutter-Firebase-Festival-Google"><img src="https://cdn-images-1.medium.com/max/800/1*sE8kssKhfy8Hp0u4HfqCOQ.gif" alt="Dash e Spark " /></a></p>
<p>Neste artigo, você aprendeu como configurar e preparar nossos aplicativos Flutter para serem usados ​​com o Firebase.</p>
<p>Em artigos futuros da série, veremos como usar recursos do Firebase, como Cloud Firestore, Authentication, Crashlytics, Remote Config e muito mais com Flutter.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ianoliveirag12/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Série: Dominando o Firebase em Aplicativos Flutter]]></title><description><![CDATA[Olá, devs blz? Hoje vamos dar início a uma série super bacana de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙
O Firebase realmente é uma ferramenta muito boa e que acelera muito o desenvolvim...]]></description><link>https://ianoliveira.dev/serie-dominando-o-firebase-em-aplicativos-flutter</link><guid isPermaLink="true">https://ianoliveira.dev/serie-dominando-o-firebase-em-aplicativos-flutter</guid><category><![CDATA[Firebase]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[backend]]></category><category><![CDATA[serverless]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 04 Mar 2024 17:37:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709494206509/45ae0af9-0fa2-4066-b3c5-3fdfdee39971.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Olá, devs blz? Hoje vamos dar início a uma série super bacana de artigos sobre as principais funcionalidades do Firebase e como integrá-las ao seu aplicativo Flutter.💙</p>
<p>O <a target="_blank" href="https://firebase.google.com/?hl=pt-br">Firebase</a> realmente é uma ferramenta muito boa e que acelera muito o desenvolvimento de novos aplicativos, ele é de fácil integração com o Flutter pois os dois são mantidos pelo o Google.</p>
<p>Eu trabalho com Desenvolvimento Mobile desde de 2018 e pelo que o me lembro não teve um só app que não o utilizei rsrs. Em cada projeto, do mais simples ao mais complexo, essa plataforma robusta e versátil tornou-se minha parceira inseparável.</p>
<p>Seja para autenticação de usuários, armazenamento de dados, envio de notificações push ou captura e análise de erros, seus produtos sempre me ofereceram a solução perfeita.</p>
<p>Segundo o <a target="_blank" href="https://firebase.blog/posts/2022/05/whats-new-at-google-io">blog oficial do Firebase</a> "Mais de 3 milhões de desenvolvedores, de startups a empresas, usam o Firebase para alcançar e envolver bilhões de usuários"</p>
<p>Nessa série de posts meu objetivo é abordar separadamente cada funcionalidade/produto da ferramenta e ensiná-los como usar em seus aplicativos. Então vem comigo. 🤏🏻 👨🏻‍💻</p>
<h3 id="heading-introducao"><strong>Introdução</strong></h3>
<p>O Google Firebase é uma poderosa plataforma de back-end como serviço (BaaS)  que oferece um conjunto de ferramentas e serviços para ajudar os desenvolvedores a criar, dimensionar e manter aplicativos da web e móveis.</p>
<p>É suportado por várias linguagens de programação populares como: Dart/Flutter, JavaScript/Node.js, Java/Kotlin, Swift/Objective-C e Unity (C#) para o desenvolvimento de jogos.</p>
<p>Ele pode prover serviços de backend hospedados, como banco de dados em tempo real, armazenamento em nuvem, autenticação, relatórios de falhas, aprendizado de máquina, configuração remota e hospedagem para seus arquivos estáticos e muito mais 🔥.</p>
<p><strong>Um pouco da História…</strong></p>
<p>O Firebase nasceu em 2011 como uma startup independente fundada por Andrew Lee e James Tamplin. Inicialmente, oferecia hospedagem de arquivos estáticos e um banco de dados em tempo real para aplicativos móveis.</p>
<p>Após participar do programa de incubação Y Combinator em 2012, a empresa expandiu sua visão para facilitar o desenvolvimento de aplicativos em tempo real.</p>
<p>Em 2012, lançaram o Firebase 2.0 com o Firebase Realtime Database e outras ferramentas.</p>
<p>Em 2014, o Google adquiriu o Firebase, impulsionando sua evolução. Desde então, a ferramenta cresceu com uma ampla gama de recursos para desenvolvedores, incluindo autenticação de usuários, análise, mensagens em nuvem e muito mais, tornando-se uma das principais plataformas para o desenvolvimento de aplicativos móveis e web.</p>
<h3 id="heading-como-funciona"><strong>Como funciona?</strong></h3>
<p><a target="_blank" href="https://www.hammermarketing.com/what-is-firebase-and-how-does-it-work/"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709568364028/a042555c-a12c-44a8-a3b5-f4deb45c5406.webp" alt class="image--center mx-auto" /></a></p>
<p>A abordagem do Firebase se diferencia do método convencional de desenvolvimento de aplicativos, onde geralmente é necessário desenvolver um software tanto para o front-end quanto para o back-end.</p>
<p>No desenvolvimento tradicional, o front-end simplesmente chama os endpoints de API fornecidos pelo back-end, que é responsável por executar as operações e a regra de negócio.</p>
<p>No entanto, ao utilizar os produtos Firebase, o modelo de back-end convencional é contornado, e parte do trabalho é transferido para o cliente. A gestão administrativa desses produtos é facilitada pelo console do Firebase, fornecendo acesso direto e simplificado.</p>
<h3 id="heading-como-o-firebase-pode-ajudar-voce-desenvolvedor"><strong>Como o Firebase pode ajudar você desenvolvedor? 🛠️</strong></h3>
<ul>
<li><p><strong>Grátis para iniciar:</strong> O Firebase oferece um <a target="_blank" href="https://firebase.google.com/pricing?hl=pt-br">plano gratuito</a> com 1 GB de armazenamento de banco de dados em tempo real, o que lhe dá a chance de iniciar um <a target="_blank" href="https://endeavor.org.br/estrategia-e-gestao/mvp/">MVP</a> de alguma ideia sua de app sem nenhum custo.</p>
</li>
<li><p><strong>Velocidade:</strong> Acelere o desenvolvimento de aplicativos e chegue ao mercado mais rapidamente. Com tantos recursos prontos como por exemplo (Autenticação e Banco de dados), o Firebase permite que você se concentre mais na regra de negócios e na experiência do usuário, em vez de lidar com a complexidade da infraestrutura de backend.</p>
</li>
</ul>
<h3 id="heading-pontos-negativos">Pontos negativos</h3>
<ul>
<li><p><strong>Custos:</strong> Embora o Firebase ofereça um <a target="_blank" href="https://firebase.google.com/pricing">plano</a> básico gratuito, o uso extensivo dos recursos do Firebase como escrita e leitura em banco de dados pode se tornar caro, especialmente em aplicativos com muitos usuários ativos ou que exigem grande quantidade de armazenamento e largura de banda.</p>
</li>
<li><p><strong>Apenas NoSQL</strong>: O Firebase oferece suporte apenas a bancos de dados NoSQL, que podem não ser adequados para todos os tipos de aplicativos, especialmente aqueles que exigem consultas e transações complexas. Isso pode ser uma limitação ao lidar com certos tipos de dados ou requisitos em um app.</p>
</li>
<li><p><strong>A migração de dados:</strong> Com o Firebase, você não pode lidar facilmente com a migração de dados como faria com um banco de dados SQL simples.</p>
</li>
</ul>
<p><mark>"Minha opinião é que se você estiver desenvolvendo um aplicativo e não estiver utilizando todos os recursos do Firebase, aproveitar os recursos totalmente gratuitos, como o remote config, analytics e as notificações, pode ser uma ótima estratégia. Isso permite otimizar seus custos enquanto ainda aproveita os benefícios desses recursos para melhorar a experiência do usuário."</mark></p>
<h3 id="heading-principais-produtos">Principais Produtos</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709564179597/51a6b742-d14b-47f7-9514-275e13f91ac6.webp" alt class="image--center mx-auto" /></p>
<p>Vou comentar abaixo os principais.</p>
<ol>
<li><p><strong>Autenticação (Firebase Auth):</strong> Oferece uma maneira fácil e segura para os usuários fazerem login em seus aplicativos. Suporta autenticação usando senhas, números de telefone, Google, Facebook, Twitter e muito mais.</p>
</li>
<li><p><strong>Banco de dados em tempo real (Cloud Firestore/ Realtime Database):</strong> Os dados são sincronizados em tempo real entre todos os clientes. Isso facilita a criação de aplicativos sempre atualizados, mesmo quando os usuários estão offline.</p>
</li>
<li><p><strong>Hospedagem:</strong> Com o Firebase Hosting, você pode implantar facilmente um app da Web de uma só página, uma página de destino de apps para dispositivos móveis ou um Progressive Web App.</p>
</li>
<li><p><strong>Laboratório de testes:</strong> O aplicativo é testado em dispositivos virtuais e físicos localizados nos data centers do Google.</p>
</li>
<li><p><strong>Notificações (Cloud Messaging)</strong></p>
<p> As notificações podem ser enviadas com o Firebase sem codificação adicional.</p>
</li>
<li><p><strong>Remote Config</strong> : a Configuração remota do Firebase permite que os desenvolvedores modifiquem o comportamento e a aparência do aplicativo sem exigir atualizações do aplicativo.</p>
</li>
<li><p><strong>Crashlytics :</strong> Firebase Crashlytics é um repórter de falhas em tempo real que ajuda os desenvolvedores a identificar e corrigir problemas de estabilidade.‍</p>
</li>
<li><p><strong>Analytics :</strong> o Google Analytics é integrado ao Firebase, fornecendo informações valiosas sobre o comportamento do usuário e o desempenho do aplicativo.</p>
</li>
<li><p><strong>Teste A/B :</strong> O teste A/B do Firebase ajuda os desenvolvedores a otimizar experiências de aplicativos testando diferentes variações de interface do usuário, recursos e campanhas.</p>
</li>
<li><p><strong>Cloud functions:</strong> Uma ferramenta que permite executar código automaticamente em resposta a eventos acionados em seu aplicativo Firebase.</p>
</li>
<li><p><strong>ML Kit:</strong> SDK para tarefas comuns de Machine learning.</p>
</li>
</ol>
<h3 id="heading-alguns-aplicativos-que-usam-o-firebase"><strong>Alguns aplicativos que usam o Firebase</strong></h3>
<p><strong>Duolingo:</strong> É um aplicativo popular de aprendizagem de idiomas que usa infraestrutura Firebase para fornecer armazenamento, e funções em nuvem.</p>
<p><strong>Lyft:</strong> Oferece uma alternativa aos serviços convencionais de táxi. Os passageiros podem solicitar uma viagem em seus smartphones .</p>
<p><strong>O jornal New York Times:</strong> É uma organização de mídia americana que distribui e coleta notícias por meio de jornais, produtos digitais e aplicativos móveis.</p>
<h3 id="heading-conclusao"><strong>Conclusão</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709576729346/8481f8eb-5611-4dc1-a7da-8f6e9dc52411.gif" alt class="image--center mx-auto" /></p>
<p>Bom é isso 😎.</p>
<p>Hoje foi o primeiro artigo da série, vou tentar publicar os demais nas próximas semanas. Será algo mais prático com exemplos reais em Flutter.</p>
<p>O Firebase oferece um caminho fácil para desenvolver e construir um aplicativo móvel ou web escalável. O principal objetivo é simplificar o desenvolvimento full stack, reduzir a complexidade para ajudá-lo a ser mais produtivo e oferecer o caminho mais rápido para o sucesso do seu projeto.</p>
<p>Com o Firebase, você não precisa investir tempo e energia para desenvolver um backend do zero para sua aplicação. Você pode simplesmente usar a estrutura do Firebase e personalizá-la de acordo com suas necessidades.</p>
<p>Se você é do tipo que tem várias ideias de aplicativos e quer testar rapidamente em ação, acredito que o Firebase e Flutter juntos é uma dupla perfeita 🤩.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Juntos, vamos construir apps incríveis que transformam o mundo!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 📲 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12"><strong>GitHub</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/"><strong>Instagram</strong></a> | <a target="_blank" href="https://twitter.com/ianoliveirag12"><strong>Twitter</strong></a> | <a target="_blank" href="https://medium.com/@ianoliveirag12"><strong>Medium</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[10 dicas de como se destacar na carreira como Desenvolvedor de Software]]></title><description><![CDATA[Em um mundo cada vez mais tecnológico e necessitado de bons desenvolvedores, ter um destaque em uma área que todos os dias só cresce é essencial para o seu sucesso na indústria da tecnologia.
O que diferencia os desenvolvedores de software bem-sucedi...]]></description><link>https://ianoliveira.dev/10-dicas-de-como-se-destacar-na-carreira-como-desenvolvedor-de-software</link><guid isPermaLink="true">https://ianoliveira.dev/10-dicas-de-como-se-destacar-na-carreira-como-desenvolvedor-de-software</guid><category><![CDATA[Computer Science]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Ian Oliveira]]></dc:creator><pubDate>Mon, 11 Sep 2023 17:12:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694451960178/619dc22d-ae7c-4086-ade9-fcaec8fbf449.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Em um mundo cada vez mais tecnológico e necessitado de bons desenvolvedores, ter um destaque em uma área que todos os dias só cresce é essencial para o seu sucesso na indústria da tecnologia.</p>
<p>O que diferencia os desenvolvedores de software bem-sucedidos dos demais?</p>
<p>Como você pode conquistar não apenas um emprego, mas uma carreira sólida neste campo em constante evolução? Para responder a essas perguntas, vou te dar algumas dicas valiosas e essenciais, 10 dicas que o guiarão na jornada para se destacar como desenvolvedor de software.</p>
<p>A maioria delas eu aprendi sozinho ao longo da minha carreira, mas queria muito que alguém tivesse me dito isso lá atrás quando iniciei em 2016.</p>
<h3 id="heading-1-domine-a-base-e-os-fundamentos-da-programacao"><strong>1 - Domine a base e os fundamentos da programação.</strong></h3>
<p>No início de carreira não tem problema focar rapidamente em uma tecnologia ou framework.</p>
<p>Muitos desenvolvedores aprendem o básico de tecnologias como Flutter ou React, por exemplo, para entrar no mercado. Depois de conseguirem emprego, passam a utilizá-las como parte de seu trabalho cotidiano, mas acabam se esquecendo de retornar e continuar aprendendo os fundamentos de forma constante.</p>
<p>No entanto, quando essas tecnologias passam por mudanças significativas ou perdem relevância no mercado, esses profissionais frequentemente se veem em situações desesperadas para aprender algo novo rapidamente.</p>
<p>É importante lembrar que, embora as tecnologias possam mudar, os fundamentos e as bases da programação dificilmente sofrerão alterações significativas.</p>
<p>Se você souber a base e entender como as coisas funcionam, aprender qualquer ferramenta ou tecnologia será mais simples pois os fundamentos são os mesmos, o que varia é a sintaxe de linguagem para linguagem.</p>
<p>Bons desenvolvedores aprendem os princípios por trás das ferramentas e frameworks que utilizam, estude estrutura de dados, algoritmos, programação orientada a objetos, testes e design de software.</p>
<h3 id="heading-2-escreva-testes-automatizados"><strong>2 - Escreva testes automatizados.</strong></h3>
<p>Software é importante. Sempre que você entregar código escreva os testes juntos, pois isso vai garantir que sua solução é confiável e que funciona.</p>
<p>Um código sem testes nada vai garantir que funcionará e isso poderá gerar sérios problemas para você ou quem usará o software.</p>
<p>Entenda que os sistemas que construímos podem afetar o bem estar e o rendimento das pessoas.</p>
<p>Leia sobre <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_software_bugs">Lista de bugs em Software</a>.</p>
<p>Escreva testes não por obrigação, mas porque você acredita que um bom código deve ser testado. Fazer testes ajuda a pensarmos melhor na hora que formos construir o código.</p>
<p>Bons desenvolvedores aprendem sobre testes automatizados onde incluem unitários, testes de integração e testes de UI e muitos outros.</p>
<h3 id="heading-3-leia-livros-tecnicos"><strong>3 - Leia livros técnicos.</strong></h3>
<p>Os livros são verdadeiros poços de conhecimentos acessíveis para as pessoas. Na maioria das vezes os autores são grandes desenvolvedores e os livros são uma forma fácil de aprender como a experiência dessas pessoas.</p>
<p>Crie o hábito de ler pelo menos um livro a cada 2 meses, se você seguir o ritmo terá lido 6 livros em um ano, o que eu acho excelente. Os livros contêm conhecimentos incríveis.</p>
<p>Recomendo a leitura de alguns livros clássicos no mundo da programação que te farão evoluir muito na carreira.</p>
<ul>
<li><p><strong>Código Limpo.</strong></p>
</li>
<li><p><strong>Codificador Limpo</strong></p>
</li>
<li><p><strong>Refatoração</strong></p>
</li>
<li><p><strong>Programador Pragmático</strong></p>
</li>
<li><p><strong>Engenharia de software moderna.</strong></p>
</li>
</ul>
<h3 id="heading-4-pratique-e-aprenda-coisas-novas-constantemente"><strong>4 - Pratique e aprenda coisas novas constantemente.</strong></h3>
<p>Uma coisa essencial para se tornar um desenvolvedor melhor é praticar. Programação é uma área que exige muita prática, assim como, Música, Futebol ou qualquer outro esporte.</p>
<p>Reserve um tempo para praticar e aprender coisas novas sempre que possível, quanto mais você treinar melhor ficará na tecnologia que você escolheu.</p>
<p>Tenha pequenas metas de estudo ou projetos paralelos que o incitem a estudar e praticar cada vez mais. O mercado de desenvolvimento de software está em constante mudança e sempre haverá novas tecnologias para aprender.</p>
<p>Uma boa ideia é trabalhar em projetos pessoais que permitem que você aplique tudo que está estudando e vá testando o que funciona e o que não funciona, isso pode incluir aplicativos, sites ou projetos de código aberto.</p>
<p>O legal de projetos próprios é que você pode errar à vontade sem ter medo, o importante é aprender com os erros e não desistir, estude um pouco todo dia e logo você verá que já avançou bastante.</p>
<h3 id="heading-5-tenha-foco-e-se-organize"><strong>5 - Tenha foco e se organize.</strong></h3>
<p>Gerencie seu tempo para estudar e tenha foco, não tente aprender tudo logo de início, aprenda conforme a demanda, profundidade é melhor que velocidade.</p>
<p>Defina metas claras e prioridades: Saiba o que você precisa fazer e o que é mais importante ao longo prazo.</p>
<p>Para usar essa dica, considere usar ferramentas como aplicativos de lista de tarefas, calendários etc.</p>
<h3 id="heading-6-arquitetura-de-software-e-principios-solid"><strong>6 - Arquitetura de Software e Princípios SOLID.</strong></h3>
<p>Aprender sobre arquitetura de software e princípios SOLID é fundamental para qualquer desenvolvedor de software pois estes nos ajudam a projetar sistemas escaláveis, manuteníveis e testáveis além de promover a reutilização de código.</p>
<p>Praticamente todas as entrevistas para cargos de desenvolvedor esses assuntos são bastante cobrados, então aprenda sobre eles todos os dias.</p>
<p>Profissionais que dominam os conceitos de arquiteturas de software e aplicam os princípios SOLID geralmente são mais valorizados no mercado de trabalho.</p>
<h3 id="heading-7-participe-ativamente-de-eventos-e-comunidades-de-tecnologia"><strong>7 - Participe ativamente de eventos e comunidades de tecnologia.</strong></h3>
<p>Construir uma sólida rede profissional é essencial para o sucesso na área de engenharia de software.</p>
<p>Uma maneira eficaz de fazer isso é engajando-se ativamente em eventos como meetups, hackathons e conferências, bem como integrando-se a comunidades de desenvolvimento de software onde você poderá ajudar ou ser ajudado pelos membros da mesma.</p>
<p>Ao participar dessas oportunidades, você terá a chance de interagir com outros profissionais, o que não apenas proporcionará insights valiosos, mas também permitirá que você estabeleça conexões significativas que podem ser extremamente benéficas para o avanço de sua carreira.</p>
<h3 id="heading-8-invista-em-soft-skills"><strong>8 - Invista em Soft Skills</strong></h3>
<p>Desenvolva suas habilidades interpessoais, como comunicação, resolução de problemas e pensamento crítico. Isso vale para qualquer carreira.</p>
<p>Uma das principais que eu considero é comunicação, ser um bom desenvolvedor é saber também se comunicar com as pessoas que você trabalha de forma eficaz.</p>
<p>Quanto mais sênior você for na carreira, mais comunicação será exigido de você.</p>
<h3 id="heading-9-estude-ingles"><strong>9 - Estude inglês</strong></h3>
<p>Ter conhecimento em inglês é de extrema importância, não apenas porque a maioria da documentação e recursos de programação estão disponíveis nesse idioma, mas também porque a fluência em inglês pode abrir portas para oportunidades de emprego mais amplas e melhor remuneradas em todo o mundo.</p>
<p>Em resumo é uma habilidade crucial para os desenvolvedores de software, não apenas para melhorar as oportunidades de carreira, mas também para o desenvolvimento contínuo de habilidades e conhecimento na área.</p>
<h3 id="heading-10-contribuir-com-a-comunidade"><strong>10 - Contribuir com a comunidade</strong></h3>
<p>Você aprende muito vendo o código de outras pessoas, criando conteúdo ou palestrando em eventos de tecnologia.</p>
<p>Pessoalmente, tive muitas experiências excelentes enquanto palestrei em eventos ou criei conteúdos que ajudaram novas pessoas que estavam iniciando.</p>
<h3 id="heading-conclusao"><strong>Conclusão 🔥</strong></h3>
<p>Bom espero que essas dicas o ajude a ser um desenvolvedor melhor.</p>
<p>Gostaria de ressaltar que existem muitas outras dicas legais, mas acredito que essas são as principais e lembre se não existe fórmula pronta, aplique as dicas e veja o que melhor funciona para você.</p>
<p>O sucesso na engenharia de software não acontece da noite para o dia. Leva tempo e esforço contínuo para se destacar nesta carreira em constante evolução.</p>
<p>Espero que você tenha gostado! Compartilhe-o com seus amigos e colegas!</p>
<p>Se tiver alguma dúvida ou contribuição, deixe nos comentários!</p>
<p>Me siga para estar sempre por dentro dos próximos artigos 🚀</p>
<h1 id="heading-minhas-redes-sociais"><strong>🌐 Minhas redes sociais 🌐</strong></h1>
<p><a target="_blank" href="https://www.github.com/iang12">GitHub</a> | <a target="_blank" href="https://www.linkedin.com/in/ian-oliveira-0701a2130/">LinkedIn</a> | <a target="_blank" href="https://www.instagram.com/ianoliveira.dev/">Instagram</a> | <a target="_blank" href="https://twitter.com/ianoliveirag12">Twitter</a></p>
]]></content:encoded></item></channel></rss>