<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cristovão F.</title>
    <description>The latest articles on DEV Community by Cristovão F. (@cristovoxdgm).</description>
    <link>https://dev.to/cristovoxdgm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F205338%2Fef49365c-a760-4e4f-9efe-d8b8108b38ac.jpg</url>
      <title>DEV Community: Cristovão F.</title>
      <link>https://dev.to/cristovoxdgm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cristovoxdgm"/>
    <language>en</language>
    <item>
      <title>How to Implement Video Casting in Flutter</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 24 Jul 2025 02:31:43 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/how-to-implement-video-casting-in-flutter-2j28</link>
      <guid>https://dev.to/cristovoxdgm/how-to-implement-video-casting-in-flutter-2j28</guid>
      <description>&lt;p&gt;Hey folks! Today I’ll show you how to implement a casting feature in your Flutter app —&lt;br&gt;
especially useful for video apps, courses, streaming platforms, or even fitness apps, like&lt;br&gt;
Netflix or YouTube.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Cast?
&lt;/h2&gt;

&lt;p&gt;"Cast" is the ability to send media (like video or audio) from your app to another device,&lt;br&gt;
such as a Chromecast-enabled TV or an AirPlay-compatible receiver. The content plays&lt;br&gt;
on the external screen, while your app becomes a remote control.&lt;/p&gt;
&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Casting protocols work mainly in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chromecast (Google Cast)&lt;/strong&gt;: The receiver device (usually a smart TV or dongle) runs
a player and receives control commands over the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AirPlay (Apple)&lt;/strong&gt;: Native on Apple TVs and compatible smart TVs. iOS can also
mirror the screen when casting isn't supported directly.
## Documentation and Useful Links&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cast package on pub.dev: &lt;a href="https://pub.dev/packages/cast" rel="noopener noreferrer"&gt;https://pub.dev/packages/cast&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google Cast SDK Developer Docs: &lt;a href="https://developers.google.com/cast/docs/developers" rel="noopener noreferrer"&gt;https://developers.google.com/cast/docs/developers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apple AirPlay Overview: &lt;a href="https://developer.apple.com/airplay/" rel="noopener noreferrer"&gt;https://developer.apple.com/airplay/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;flutter_to_airplay package: &lt;a href="https://pub.dev/packages/flutter_to_airplay" rel="noopener noreferrer"&gt;https://pub.dev/packages/flutter_to_airplay&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to implement it?
&lt;/h2&gt;

&lt;p&gt;First, add the necessary dependencies to your &lt;code&gt;pubspec.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;cast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^2.1.0&lt;/span&gt;
 &lt;span class="na"&gt;flutter_to_airplay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^2.0.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠&lt;br&gt;
 Important: Read the documentation for the &lt;code&gt;cast&lt;/code&gt; package carefully — you must&lt;br&gt;
configure AndroidManifest.xml, permissions, and iOS protocols as required.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the Cast Service
&lt;/h3&gt;

&lt;p&gt;To follow Clean Architecture, let’s encapsulate the cast logic in a service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoCastService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CastDevice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;searchDevices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CastDiscoveryService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="n"&gt;CastSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;forward10seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;seekMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"SEEK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"mediaSessionId"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"currentTime"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"resumeState"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PLAY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seekMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;backwards10seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;seekMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"SEEK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"mediaSessionId"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"currentTime"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"resumeState"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PLAY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seekMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stopSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"STOP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mediaSessionId"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;playMedia&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PLAY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;'mediaSessionId'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;setVolume&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isMuted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceReceiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"SET_VOLUME"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'volume'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"muted"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isMuted&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;pauseMedia&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'PAUSE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'mediaSessionId'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mediaSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="n"&gt;CastDevice&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CastSessionManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;minutes:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;launchDefaultMediaApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CastSessionState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;listenToStateStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;stateStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;listenToMessageStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;messageStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;launchDefaultMediaApp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceReceiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'LAUNCH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'appId'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'CC1AD845'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Default media device&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;getMediaStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GET_STATUS"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;getReceiverStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GET_STATUS"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;openMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="n"&gt;VideoCastParams&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'contentId'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;'contentType'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'video/dash'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;'streamType'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'BUFFERED'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;'metadata'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'metadataType'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'url'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thumb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentSession&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;currentSession&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CastSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kNamespaceMedia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'LOAD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;'autoPlay'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;'currentTime'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;'media'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can inject this service using GetIt, Riverpod, or any other DI solution and Create a Cubit or a bloc to consume it, also using a enum to simplify the flow of use for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  AirPlay support (iOS)
&lt;/h2&gt;

&lt;p&gt;As a fallback for iOS, when Google Cast is not supported, we can use&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flutter_to_airplay&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Displaying the AirPlay button:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;AirPlayRoutePickerView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nl"&gt;tintColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;activeTintColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This widget displays the native system button, opening the AirPlay or screen mirroring&lt;br&gt;
interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fallback: Native screen mirroring (iOS)
&lt;/h3&gt;

&lt;p&gt;If the device doesn’t support AirPlay directly, the &lt;code&gt;AirPlayRoutePickerView&lt;/code&gt; lets users&lt;br&gt;
enable screen mirroring instead — ensuring your video is still shown.&lt;br&gt;
✅ Tip: You can listen to the &lt;code&gt;CastService&lt;/code&gt; stream to detect when casting starts or stops,&lt;br&gt;
and adapt your UI accordingly (e.g., hiding local controls or changing the player view).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;cast&lt;/code&gt; and &lt;code&gt;flutter_to_airplay&lt;/code&gt; packages, you can implement a complete&lt;br&gt;
casting experience on Flutter — supporting both Google Cast and AirPlay on iOS. Even&lt;br&gt;
though Flutter doesn't natively handle all media controls, this solution gives you great&lt;br&gt;
flexibility.&lt;br&gt;
To make your app more robust, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Showing visual feedback when connected.&lt;/li&gt;
&lt;li&gt;Centralizing media controls (play, pause, seek).&lt;/li&gt;
&lt;li&gt;Displaying a casting icon in your app bar.
If you want the full example or have questions, feel free to reach out on Instagram
@kiustudios or comment below!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>learning</category>
      <category>code</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 10 Apr 2025 00:41:32 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/-62p</link>
      <guid>https://dev.to/cristovoxdgm/-62p</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/cristovoxdgm/some-of-my-projects-46pb" class="crayons-story__hidden-navigation-link"&gt;Some of my projects&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/cristovoxdgm" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F205338%2Fef49365c-a760-4e4f-9efe-d8b8108b38ac.jpg" alt="cristovoxdgm profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/cristovoxdgm" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Cristovão F.
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Cristovão F.
                
              
              &lt;div id="story-author-preview-content-2395095" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/cristovoxdgm" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F205338%2Fef49365c-a760-4e4f-9efe-d8b8108b38ac.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Cristovão F.&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/cristovoxdgm/some-of-my-projects-46pb" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 10 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/cristovoxdgm/some-of-my-projects-46pb" id="article-link-2395095"&gt;
          Some of my projects
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/flutter"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;flutter&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/portfolio"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;portfolio&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mobile"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mobile&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/cristovoxdgm/some-of-my-projects-46pb#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>flutter</category>
      <category>portfolio</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Some of my projects</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 10 Apr 2025 00:38:54 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/some-of-my-projects-46pb</link>
      <guid>https://dev.to/cristovoxdgm/some-of-my-projects-46pb</guid>
      <description>&lt;p&gt;Hey everyone! 👋&lt;/p&gt;

&lt;p&gt;I wanted to share a quick post to give you all a better idea of what I’ve been building lately! 🚀 Here’s a list of some of my projects from the past few years — whether personal projects, client work, or apps I’ve contributed to. Check out the links and, if possible, I’ll drop some screenshots too! 😁&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.kiustudios.link_generator_app&amp;amp;hl=pt_BR" rel="noopener noreferrer"&gt;Link Generator App (Android)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://link-gen-kiu-studios.netlify.app/" rel="noopener noreferrer"&gt;Link Generator App (Web)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.apple.com/br/app/fitdance-plus/id6444678335" rel="noopener noreferrer"&gt;FitDance Plus (iOS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=br.com.magnumbank" rel="noopener noreferrer"&gt;Magnum Bank (Android)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/search?q=prote%C3%A7%C3%A3o%20pix&amp;amp;c=apps&amp;amp;hl=pt_BR" rel="noopener noreferrer"&gt;Proteção Pix (Android)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cristovaoresume.netlify.app/" rel="noopener noreferrer"&gt;My Resume (Web)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kiustudios.netlify.app/" rel="noopener noreferrer"&gt;Kiu Studios Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://weather-kiustudios-app.netlify.app/" rel="noopener noreferrer"&gt;Weather App (Web)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cristovao-react-gallery.netlify.app/" rel="noopener noreferrer"&gt;React Gallery (Web)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And there’s a lot more over on my GitHub! They might not be live apps, but they’re open-source if you want to take a look:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/CristovoXDGM" rel="noopener noreferrer"&gt;https://github.com/CristovoXDGM&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you're into tech, mobile development, or just curious about my journey, feel free to connect! I’m always down to share experiences, ideas, or even collaborate on cool projects. 🚀✨&lt;/p&gt;

&lt;p&gt;You can also follow me here on dev.to, and on my other platforms for more updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧩 &lt;a href="https://github.com/CristovoXDGM" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📸 &lt;a href="https://instagram.com/kiustudios" rel="noopener noreferrer"&gt;Instagram @kiustudios&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s build cool stuff together! 💡&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>portfolio</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Discover the Secrets of Effective Learning</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 29 Aug 2024 01:23:02 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/discover-the-secrets-of-effective-learning-4d16</link>
      <guid>https://dev.to/cristovoxdgm/discover-the-secrets-of-effective-learning-4d16</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;I’m bringing you a topic that I believe is crucial, especially for those who are just starting out in the field. Having worked in the technology industry for several years now, I can say this to anyone who is just beginning or planning to enter this field: always study and stay updated. It may sound obvious, but it’s absolutely essential in our line of work.&lt;/p&gt;

&lt;p&gt;When I talk about "learning to learn," I don't just mean studying for the sake of it. It’s about studying with purpose, truly understanding what you’ve studied, and discovering your own learning style. Each person will develop or adopt a study method, whether it’s through writing, making videos, reading and repeating the content, or sharing the knowledge you’ve gained.&lt;/p&gt;

&lt;p&gt;"Your most dissatisfied customers are your best source of learning." – Bill Gates&lt;/p&gt;

&lt;p&gt;As odd as it may sound, this quote makes a lot of sense, especially because it’s from our mistakes that we learn the most. We understand our learning process, identify areas to improve, learn how to seek out content, and figure out what to study. All of this comes with time. Of course, learning efficiently is key, so here are some tips that I follow whenever I need to master something new.&lt;/p&gt;

&lt;p&gt;Tips for Effective Learning&lt;br&gt;
I won’t go into too much detail, so I’ll keep these tips concise:&lt;/p&gt;

&lt;p&gt;Choose a Study Technique: Find a method that works for you. Personally, I prefer sharing knowledge and creating practical projects to reinforce what I want to learn.&lt;br&gt;
Read Books: Never underestimate the power of reading. It broadens our horizons and deepens our knowledge.&lt;br&gt;
Create Your Own Roadmap: Have a clear vision of where you want to go in your career, how you want to evolve, and what you want to achieve in the future.&lt;br&gt;
Watch Videos from Industry Professionals: Influences matter. Learn from those who are actively working in the field. Even juniors can offer valuable insights.&lt;br&gt;
Accept Different Perspectives: There’s no absolute truth for everything. Be open to understanding other opinions and approaches to the problems or content you’re studying.&lt;br&gt;
Avoid Comparisons: Comparing yourself to others, especially to someone with over 11 years of experience, is a quick way to stall your progress. Focus on your own journey.&lt;br&gt;
Teach and Share: Sharing knowledge is the best way to identify your mistakes and improve, as it forces you to understand the subject deeply enough to explain it to others.&lt;br&gt;
Focus on One Thing at a Time: Don’t rush to learn everything at once. Take your time, as there will be phases where studying becomes repetitive.&lt;br&gt;
Build Projects: In the tech field, having a portfolio and personal projects is vital. Use these projects as opportunities to gain experience.&lt;br&gt;
Finish What You Start: Completing a project, even if it’s not perfect, is essential for designing better ones in the future. Learn from your mistakes and keep improving.&lt;br&gt;
Know When to Rest: Resting is crucial for consolidating what you’ve learned. It’s not about playing games or watching movies, but taking a shower, going for a walk, or even taking a nap.&lt;/p&gt;

&lt;p&gt;I’m not here to be a coach; I just want to share this knowledge because I believe it’s essential for everyone. If you've made it this far, don't forget to follow me here and on my other social networks.&lt;/p&gt;

&lt;p&gt;@kiustudios - Instagram, YouTube, and Twitter&lt;/p&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>code</category>
      <category>newbie</category>
    </item>
    <item>
      <title>Make flutter builds easier</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 06 Jun 2024 13:45:30 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/make-flutter-builds-easier-17ab</link>
      <guid>https://dev.to/cristovoxdgm/make-flutter-builds-easier-17ab</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil7sjwlowmz6olc92q8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil7sjwlowmz6olc92q8x.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>developer</category>
      <category>newbie</category>
    </item>
    <item>
      <title>The joy of the Service pattern and Dependency inversion</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Sat, 04 May 2024 02:41:21 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/the-joy-of-the-service-pattern-and-dependency-inversion-5a7n</link>
      <guid>https://dev.to/cristovoxdgm/the-joy-of-the-service-pattern-and-dependency-inversion-5a7n</guid>
      <description>&lt;p&gt;I believe that every Dev has come across the situation of needing to do something and having to look for something ready to solve their problem, such as libs and database packages, external services that seek to facilitate our day-to-day lives as developers.&lt;br&gt;
Eventually the Dev will come across an update that breaks the current code to use a new implementation or etc. For small projects, this doesn't have such an impact, but for large projects, it can cost you your job or hours of time updating and hoping that something doesn't break in the process.&lt;/p&gt;

&lt;p&gt;For this we have a Project Pattern and a rule that helps a lot, they are the Service pattern and the Depency inversion of solid, together they help us to make a structure that allows us to scale the system and not depend on packages or external changes, only ours.&lt;/p&gt;

&lt;p&gt;I don't intend to put the whole pattern here to encourage you to study it, but believe me, it's very worthwhile. My recommendation is always Uncle Bob's book and the refactoring guru's website. Finally, studying solid will help you understand more about it.&lt;/p&gt;

&lt;p&gt;Site mentioned:&lt;br&gt;
&lt;a href="https://refactoring.guru/" rel="noopener noreferrer"&gt;https://refactoring.guru/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>mid</category>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>How to create a similar to Google maps pan an a zoom movement in Flutter flame</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Sun, 11 Feb 2024 01:42:03 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/how-to-create-a-similar-pan-an-a-zoom-movement-in-flutter-flame-1ccj</link>
      <guid>https://dev.to/cristovoxdgm/how-to-create-a-similar-pan-an-a-zoom-movement-in-flutter-flame-1ccj</guid>
      <description>&lt;p&gt;Hello everyone, how are you? Here I am with another mini-tutorial that I learned in my day-to-day work. Recently, we needed a camera movement in our app similar to what Google does in Google Maps, and since we are using Flutter and, in conjunction, Flame, there wasn't much material available on this. So, with this challenge in mind, I researched extensively and tested various possibilities until one day I decided to try ScaleDetector and Pandetect from Flame. I discovered that ScaleDetector was nothing more than a superset of PanDetector.&lt;/p&gt;

&lt;p&gt;In summary, we were able to create the solution, and here I am to document this code for you.&lt;/p&gt;

&lt;p&gt;Note: Remember to check the Flutter Flame documentation to implement everything correctly, using the ScaleDetector mixin.&lt;/p&gt;

&lt;p&gt;Flame doc -&amp;gt; &lt;a href="https://docs.flame-engine.org/" rel="noopener noreferrer"&gt;https://docs.flame-engine.org/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void clampZoom() {
    camera.viewfinder.zoom = camera.viewfinder.zoom.clamp(0.8, 5);
  }

  static const zoomPerScrollUnit = 0.01;
  late double startZoom;
  @override
  void onScaleStart(info) {
    startZoom = camera.viewfinder.zoom;
  }

  @override
  void onScaleUpdate(ScaleUpdateInfo info) {
    final currentScale = info.scale.global;
    if (!currentScale.isIdentity()) {
      camera.viewfinder.zoom = startZoom * currentScale.y;
      camera.moveBy(info.delta.global);
      clampZoom();
    } else {
      final delta = -info.delta.global;
      camera.moveBy(delta);
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would also like to thank Lukas (&lt;a class="mentioned-user" href="https://dev.to/spydon"&gt;@spydon&lt;/a&gt; ), who has been doing an excellent job in the development of Flame and its community.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is use for work as a developer - Basic Flutter setup</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Sat, 27 Jan 2024 17:09:50 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/what-is-use-for-work-as-a-developer-basic-flutter-setup-3e7n</link>
      <guid>https://dev.to/cristovoxdgm/what-is-use-for-work-as-a-developer-basic-flutter-setup-3e7n</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PiJzxikGxQQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>setup</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Mobile Dev Roadmap</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 07 Sep 2023 13:49:12 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/mobile-dev-roadmap-hoh</link>
      <guid>https://dev.to/cristovoxdgm/mobile-dev-roadmap-hoh</guid>
      <description>&lt;h1&gt;
  
  
  Programming Foundation
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Get a clear idea of what an algorithm is.&lt;/li&gt;
&lt;li&gt;Learn the difference between data, information, knowledge, and intelligence.&lt;/li&gt;
&lt;li&gt;Understand the basics of programming logic.&lt;/li&gt;
&lt;li&gt;Explore common data structures.&lt;/li&gt;
&lt;li&gt;Get familiar with databases (both relational and non-relational) at a basic level.&lt;/li&gt;
&lt;li&gt;Learn how RESTful APIs work (GraphQL is a nice extra if you want).&lt;/li&gt;
&lt;li&gt;Dive into Object-Oriented Programming (OOP), especially if your language focuses on it.&lt;/li&gt;
&lt;li&gt;Study some design patterns.&lt;/li&gt;
&lt;li&gt;Understand the SOLID principles (like Single Responsibility, Open/Closed, and the others).&lt;/li&gt;
&lt;li&gt;Get to know the idea of Clean Code and why it matters for writing maintainable code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Choose Your Development Stack
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Pick your mobile programming language (like Swift for iOS or Kotlin for Android).&lt;/li&gt;
&lt;li&gt;Learn the language well — its syntax and core concepts.&lt;/li&gt;
&lt;li&gt;Choose a framework for mobile development (like SwiftUI for iOS or Flutter for cross-platform).&lt;/li&gt;
&lt;li&gt;Understand how the app lifecycle works on your chosen platform.&lt;/li&gt;
&lt;li&gt;Learn how to style components and build user interfaces.&lt;/li&gt;
&lt;li&gt;Practice breaking your code into components and modules.&lt;/li&gt;
&lt;li&gt;Check out the design guidelines for your platform (like Material Design for Android or Human Interface Guidelines for iOS).&lt;/li&gt;
&lt;li&gt;Get the basics of state management (like Flutter's State Management or Android's ViewModels).&lt;/li&gt;
&lt;li&gt;Explore reactive programming with things like Streams and Observables (depending on your platform).&lt;/li&gt;
&lt;li&gt;Spend time reading the official docs for your language and framework.&lt;/li&gt;
&lt;li&gt;Build small projects to practice and solidify what you’ve learned.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Architecture and Beyond
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Start digging into mobile architecture patterns (like MVVM, MVP, MVC, and Clean Architecture).&lt;/li&gt;
&lt;li&gt;Go deeper into Clean Architecture and how to use it in real projects.&lt;/li&gt;
&lt;li&gt;Keep improving your Clean Code skills — naming things right, refactoring, following best practices.&lt;/li&gt;
&lt;li&gt;Learn more design patterns (like Singleton, Observer, and Factory).&lt;/li&gt;
&lt;li&gt;Get a good sense of UX/UI principles to make your apps feel intuitive and smooth.&lt;/li&gt;
&lt;li&gt;Master layouts on your platform (like ConstraintLayout on Android or SwiftUI layouts on iOS).&lt;/li&gt;
&lt;li&gt;Make sure your app works well on different devices and screen sizes (responsiveness and adaptability).&lt;/li&gt;
&lt;li&gt;Learn about accessibility so your app is usable for everyone.&lt;/li&gt;
&lt;li&gt;Level up your state management skills with advanced tools (like Redux, MobX, or Provider).&lt;/li&gt;
&lt;li&gt;Stay up to date with what's happening in mobile development — join communities, attend events, and take courses.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  And remember:
&lt;/h3&gt;

&lt;p&gt;Mobile development is always changing. Stay curious, keep learning, and tweak your roadmap as new tech and tools come out. That’s how you stay ahead!&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>codenewbie</category>
      <category>coding</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Resolve your routes</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Tue, 16 May 2023 11:29:56 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/resolve-your-routes-13k5</link>
      <guid>https://dev.to/cristovoxdgm/resolve-your-routes-13k5</guid>
      <description>&lt;p&gt;There are times when we want to work with a login feature and need to create different routes based on the user's status, redirecting them to the registration page or even identifying a user with a bonus. In these cases, we often place the code directly on the page and send the user to the appropriate route based on their state or status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AuthState {
  final bool isAuthenticated;

  AuthState(this.isAuthenticated);
}

void main() {
  final authState = AuthState(isAuthenticated: false);

  String initialRoute;
  if (authState.isAuthenticated) {
    initialRoute = '/home';
  } else {
    initialRoute = '/login';
  }

  runApp(MyApp(initialRoute: initialRoute));
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this is not always the best solution because, depending on the number of routes, the logic in the view can become extensive and unwieldy if there is no standard or pattern in place. With this in mind, we can consider a solution to the problem, something that allows for unit testing if necessary.&lt;/p&gt;

&lt;p&gt;We will create a simple abstraction using generic types, where we will have a method that returns the route string. The method's return can be an enum of routes or something similar, as long as we have control over it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class RouteResolver&amp;lt;T&amp;gt; {
  String resolveRoute(T states);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our abstraction created, let's now implement our Resolver by module. This way, we separate the logic from the view, allowing us to inject our resolver as a dependency or, for simpler cases, instantiate it on the page where we need to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AuthState {
  bool isAuthenticated;

  AuthState(this.isAuthenticated);
}

class AuthRouteResolver implements RouteResolver&amp;lt;AuthState&amp;gt; {
  @override
  String resolveRoute(AuthState states) {
    if (states.isAuthenticated) {
      return '/home';
    } else {
      return '/login';
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantiating our route resolver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  final authState = AuthState(isAuthenticated: true);

  final routeResolver = AuthRouteResolver();
  final initialRoute = routeResolver.resolveRoute(authState);

  runApp(MyApp(initialRoute: initialRoute));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe this is a simple solution to a common problem. Of course, there are other ways to work with routes. In this particular case, we are working based on a state, status, or even a class type, hence the importance of using generic types. To better understand the topic discussed here, I recommend reading about clean architecture, clean code, and code refactoring.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Mastering Conventional Commits: A Guide to Consistent and Clear Commit Messages</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Sun, 26 Feb 2023 03:45:25 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/mastering-conventional-commits-a-guide-to-consistent-and-clear-commit-messages-1nhh</link>
      <guid>https://dev.to/cristovoxdgm/mastering-conventional-commits-a-guide-to-consistent-and-clear-commit-messages-1nhh</guid>
      <description>&lt;p&gt;Let's say you're a software development team working on a codebase. Clear and consistent commit messages are essential to keep track of changes over time. However, maintaining a standardized format for commit messages can be challenging when multiple developers are involved. Without a consistent standard, it can be harder to understand the context and impact of each change. That's where Conventional Commits come in. They provide a naming convention that makes it easier to understand the changes made and their purpose. In this post, we'll explore what Conventional Commits are, why they matter, and how to use them in your development workflow.&lt;/p&gt;

&lt;p&gt;Conventional Commits is a commit message naming convention that focuses on providing a consistent standard for commits in a source code repository. The goal is to make it easier to read and interpret changes made to a project, helping understand what was changed and the impact of those changes.&lt;/p&gt;

&lt;p&gt;The convention follows a specific pattern of message prefixes that indicate the nature of the change and its intention. The prefix is followed by a descriptive text that details the change made.&lt;/p&gt;

&lt;h2&gt;
  
  
  The most common prefixes are:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;feat&lt;/code&gt;: a new feature or significant improvement was added&lt;br&gt;
&lt;code&gt;fix&lt;/code&gt;: a problem was fixed&lt;br&gt;
&lt;code&gt;docs&lt;/code&gt;: changes were made to the project documentation&lt;br&gt;
&lt;code&gt;style&lt;/code&gt;: changes were made to code formatting without changing its function&lt;br&gt;
&lt;code&gt;refactor&lt;/code&gt;: the code was refactored without adding or removing functionality&lt;br&gt;
&lt;code&gt;test&lt;/code&gt;: tests were added or modified&lt;br&gt;
&lt;code&gt;chore&lt;/code&gt;: changes to files or settings that do not affect the code itself (e.g. updating dependencies)&lt;/p&gt;

&lt;p&gt;By following this convention, it is possible to use automated tools to generate change logs, version histories, and even to perform automated deployment actions in production environments, for example.&lt;/p&gt;

&lt;p&gt;In summary, the use of Conventional Commits is a best practice for maintaining organization and clarity in the change history of a software project, making communication between development team members and external contributors easier.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>vscode</category>
      <category>flutter</category>
    </item>
    <item>
      <title>How to internationalize your Flutter app for a global audience</title>
      <dc:creator>Cristovão F.</dc:creator>
      <pubDate>Thu, 23 Feb 2023 02:57:56 +0000</pubDate>
      <link>https://dev.to/cristovoxdgm/how-to-internationalize-your-flutter-app-for-a-global-audience-2jca</link>
      <guid>https://dev.to/cristovoxdgm/how-to-internationalize-your-flutter-app-for-a-global-audience-2jca</guid>
      <description>&lt;p&gt;In today's globalized world, developing an app that caters to a diverse audience is critical. This is where internationalization comes in - the process of designing an app to support different languages, regions, and cultures. In this video, we'll show you how to internationalize a Flutter app to reach a wider audience. You'll learn the step-by-step process of integrating localization, translation, and language support in your app's user interface. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/O9W1dEonvXM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
