<?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: Burhanuddin Rashid</title>
    <description>The latest articles on DEV Community by Burhanuddin Rashid (@burhanrashid52).</description>
    <link>https://dev.to/burhanrashid52</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%2F96223%2F3b244508-f14a-4d82-8770-a7cfa51b2ae6.jpeg</url>
      <title>DEV Community: Burhanuddin Rashid</title>
      <link>https://dev.to/burhanrashid52</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/burhanrashid52"/>
    <language>en</language>
    <item>
      <title>Creating A Habit: Reading Books</title>
      <dc:creator>Burhanuddin Rashid</dc:creator>
      <pubDate>Wed, 06 Jan 2021 02:37:11 +0000</pubDate>
      <link>https://dev.to/burhanrashid52/creating-a-habit-reading-books-4dc3</link>
      <guid>https://dev.to/burhanrashid52/creating-a-habit-reading-books-4dc3</guid>
      <description>&lt;p&gt;&lt;em&gt;For more visibility posting this here. The &lt;a href="http://burhanrashid52.com/2021/01/04/creating-a-habit-reading-books/" rel="noopener noreferrer"&gt;original&lt;/a&gt; article is posted on my &lt;a href="//HTTP://burhanrashid52.com"&gt;website&lt;/a&gt;. Let's get started :)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This year 2020, I tweeted about my reading.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1344553122522284033-360" src="https://platform.twitter.com/embed/Tweet.html?id=1344553122522284033"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1344553122522284033-360');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1344553122522284033&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Many people reach out and asked me "How did you pull this off? ". Since I like the DRY(Don't Repeat Yourself) principle I thought of putting this into a blog post so I don't have to repeat myself 😂&lt;/p&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I started reading books
&lt;/h2&gt;

&lt;p&gt;I was one of those kids who loves to read comics. My parents brought me one comic book of &lt;a href="https://en.wikipedia.org/wiki/Chacha_Chaudhary" rel="noopener noreferrer"&gt;Chacha Chaudhary&lt;/a&gt; while visiting Udaipur. We don't get such kind of comics in the village. So I was excited.&lt;/p&gt;

&lt;p&gt;After that whenever they went outside the village I asked for more comic books. I read &lt;a href="https://en.wikipedia.org/wiki/Chacha_Chaudhary" rel="noopener noreferrer"&gt;Chacha Chaudary,&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Billoo" rel="noopener noreferrer"&gt;Billoo&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Pinki_(comics)" rel="noopener noreferrer"&gt;Pinki&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Nagraj" rel="noopener noreferrer"&gt;Nagraj&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Super_Commando_Dhruva" rel="noopener noreferrer"&gt;Dhruv&lt;/a&gt;a(For Non-Indian this are all Indian superheroes and character). As I grew up, I started playing more video games and lost my interest in reading comics.&lt;/p&gt;

&lt;p&gt;The point is that most people have a reading habit. It can be in form of comics, storybooks, and newspapers. I always had an interest in reading but somewhere I lost it.&lt;/p&gt;

&lt;p&gt;Fast-forward 15 years, I was about to complete my two years as an android developer in the software industry. Most of the things I learned from videos and technical blogs. I realized those things are most helpful to get things done. But I wanted to have a deeper understanding of it&lt;/p&gt;

&lt;p&gt;One day I saw the book "Zero to One" on my colleague's desk and Borrowed it.&lt;/p&gt;

&lt;p&gt;In excitement, I completed half of the book in 4 days. As we know excitement and motivation do not last long. I stopped reading in a few weeks. I picked up again. Read for 2 days and stopped. It went on for 3 months,  just to read a 250-page book.&lt;/p&gt;

&lt;p&gt;I realized two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My Reading was &lt;strong&gt;not consistent&lt;/strong&gt;. I was reading on random days as I feel.&lt;/li&gt;
&lt;li&gt;I did &lt;strong&gt;not value the book because I got it free&lt;/strong&gt; from my colleague. I won't lose anything from not reading it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the same time, I was struggling to write clean code (I Still do :)). One of my colleague suggested reading "Clean Code" book.&lt;/p&gt;

&lt;p&gt;At that time, my monthly salary was not sufficient enough to afford this book. But I brought it anyway thinking this as an investment to grow my skills professionally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwowhnwt128oj1dr54gtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwowhnwt128oj1dr54gtz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar thing happened again. I was not able to read consistently. But this time the gap was less because now I've invested my money in it which forces me to read 10-15 min regardless of my "Mood".&lt;/p&gt;

&lt;p&gt;One day I was scrolling through Twitter and saw a tweet by Donn Felker on reading 10 pages daily.&lt;br&gt;
It hit me. I thought "okay, Reading 10 pages daily is not that hard ". I can do that.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1040289491297161217-7" src="https://platform.twitter.com/embed/Tweet.html?id=1040289491297161217"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1040289491297161217-7');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1040289491297161217&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;So keeping the consistency of reading daily 10 pages regardless of my "Mood". I was able to complete the book in 5 months.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1073983454797316097-694" src="https://platform.twitter.com/embed/Tweet.html?id=1073983454797316097"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1073983454797316097-694');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1073983454797316097&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;It was the beginning. After that, I read &lt;a href="https://twitter.com/burhanrashid52/status/1111930366682648580?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed&amp;amp;ref_url=notion%3A%2F%2Fwww.notion.so%2Fburhanrashid52%2FCreating-A-Habit-Reading-Books-dc9a5a2569c447638281885a1e21ab1f" rel="noopener noreferrer"&gt;Working Effectively with Legacy Code&lt;/a&gt;, &lt;a href="https://twitter.com/burhanrashid52/status/1165203580472758272?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed&amp;amp;ref_url=notion%3A%2F%2Fwww.notion.so%2Fburhanrashid52%2FCreating-A-Habit-Reading-Books-dc9a5a2569c447638281885a1e21ab1f" rel="noopener noreferrer"&gt;Refactoring&lt;/a&gt;, &lt;a href="https://twitter.com/burhanrashid52/status/1200629506018398208?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed&amp;amp;ref_url=notion%3A%2F%2Fwww.notion.so%2Fburhanrashid52%2FCreating-A-Habit-Reading-Books-dc9a5a2569c447638281885a1e21ab1f" rel="noopener noreferrer"&gt;The Pragmatic Programmer&lt;/a&gt; , and the list goes on.&lt;/p&gt;

&lt;p&gt;I found that reading was not that difficult. As a developer, we read a lot of code and documentation. We are used to it. The challenging part is to have discipline and consistency which eventually leads to creating a good habit.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Discipline is doing what you know needs to be done even if you don't want to do it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why creating a good habit is important.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Habits are the compound interest of self-improvement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many things in life are not in our control except habits.&lt;/p&gt;

&lt;p&gt;Habit is not created in day or week. It takes time, consistency, and discipline.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We as a human are not design or born with good habits. We need to learn and develop habits. Like child who is born will do all sort wrong or not good things. The child need to understand and develop new habits and as parents it's our responsibility to let them teach them properly.&lt;br&gt;
James Clear, Atomic Habits&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading 10 pages per day is nothing but doing 1% better every day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Improving by 1 percent isn’t particularly notable—sometimes it isn’t even noticeable — but it can be far more meaningful, especially in the long run. The difference, a tiny improvement can make over time, is astounding.&lt;br&gt;
James Clear, Atomic Habits&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Habit is not a one time job. It's a never-ending process. In the beginning, it looks difficult, but over a periods of time, it becomes easy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All big things come from small beginnings. The seed of every habit is a single, tiny decision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything has a trade-off. Reading books have as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of reading books.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open One's Mind:&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Books help us to understand different ideas or ways of thinking. Creativity is nothing but combining different ideas in your own unique way.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connecting Dots:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;I used to avoid refactoring the code because of the fear that I will break something. I knew I was missing something, but did not know exactly what?. Then I read the book Refactoring where it mentioned to "having a test before refactoring". That's where it clicked me on how to properly refactor the code. I've experienced many examples of such instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning from other people mistakes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;I have not failed. I've just found 10,000 ways that won't work.
Thomas A. Edison&lt;/li&gt;
&lt;li&gt;There are two ways to learn anything. First from your own mistake, and seconds from someone else mistake. I would prefer the second one.&lt;/li&gt;
&lt;li&gt;If we're trying to do something for the first time, we better ask someone who already did that. Most of the time, it will save a lot of trouble and time for us.&lt;/li&gt;
&lt;li&gt;Reading on the subject before we dive completely into it helps.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writing Well:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Improving writing by reading is like, watch and learn.&lt;/li&gt;
&lt;li&gt;Reading more will help us understand how to form a sentence, making your point, when to give an example, when it's appropriate to make a joke, how to ask a question and how to explain the answers, what's the part we should leave for audience's imagination, etc.&lt;/li&gt;
&lt;li&gt;Reading opens one's mind and helps one to write down their thoughts in an organized manner.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Disadvantage of reading books.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Few books are good:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Best selling does not mean a great book. I've read a few of them and they were not even close to a decent book. Most of those book can be turned into 2-3 blog posts.&lt;/li&gt;
&lt;li&gt;You have to be picky. The checklist I follow before reading a book is

&lt;ol&gt;
&lt;li&gt;Watch 10-15 minute summary on Youtube.&lt;/li&gt;
&lt;li&gt;Check how old the book is.&lt;/li&gt;
&lt;li&gt;Read reviews.&lt;/li&gt;
&lt;li&gt;Check the index of the book.&lt;/li&gt;
&lt;li&gt;You can also check &lt;a href="http://burhanrashid52.com/reading/" rel="noopener noreferrer"&gt;my reading list&lt;/a&gt; where I write short summaries.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Analysis paralysis :&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Now we know 50 ways of doing one thing, sometimes we overanalyze or overthink a situation which can make our decision-making to become "paralyzed". Earlier I used to get sucked into this a lot. As time passes I learned that we need to balance things out. This is something we learn as we go.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Tracking Knowledge:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;If you are reading just for fun then you might wanna skip this. If that's not the case then you need to preserve all the knowledge in the form of writing. &lt;a href="https://www.buildingasecondbrain.com/" rel="noopener noreferrer"&gt;Building your second brain&lt;/a&gt;. Our brains have a very limited memory. It keeps forgetting stuff. There are a few tools that can help. Will talk more about it in the next section.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Myths of Reading Books
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Readers Never Makes a Mistake:&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;People assume that you are hardly going to make a mistake if you read a lot. I still do a lot of silly mistakes. Does that mean whatever I read is a waste? Definitely No.&lt;/li&gt;
&lt;li&gt;You don't run fast instantly by reading a book on "How to run fast." Once you start practicing, you will fall and will go through a lot of pain. Those books are there to give you a good head start. Books can show you the doors. But you have to open it yourself and while doing that you make a lot of mistakes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More Knowledgeable:&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;In some context it's true. But just knowing is not enough. Most of the time we misunderstand "Knowledge" with "Understanding". We understand something when we experience it or put it into practice.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1338626702264582146-175" src="https://platform.twitter.com/embed/Tweet.html?id=1338626702264582146"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1338626702264582146-175');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1338626702264582146&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Theory without practice is empty, practice without theory is blind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Organize and Tracking Knowledge
&lt;/h2&gt;

&lt;p&gt;I used the combination of &lt;a href="https://evernote.com/" rel="noopener noreferrer"&gt;Evernote&lt;/a&gt; and &lt;a href="https://www.notion.so/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking Tools
&lt;/h3&gt;

&lt;p&gt;I used Notion to keep track of my reading. You don't need any advanced tech knowledge to use notion. You can use any reading &lt;a href="https://www.notion.so/Book-tracker-e5f700ce2a1e40c0accf9b825ad0dfbb" rel="noopener noreferrer"&gt;template&lt;/a&gt; in notion to get started.&lt;/p&gt;

&lt;p&gt;I started with a simple book name and status. As I progressed I added a few more fields and kept improving. Now it looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu1y17vhh3sv2nijrckpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu1y17vhh3sv2nijrckpr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a more advanced use case, I linked my reading's table to the my daily Bullet Journal. This helps me to understand how much time and the number of days I take to finish a book.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe4a333vhynwz16sdkokh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe4a333vhynwz16sdkokh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like a lot of work. But in reality it's not. It will take only 5 min per day to log the entry. We just need to be consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Highlighting Notes
&lt;/h3&gt;

&lt;p&gt;Highlighting notes help to take out important points to remember. For the physical book, we usually use a pencil or a highlighter. But please don't do this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo4jgnn3me4p0pzyv8xw6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo4jgnn3me4p0pzyv8xw6.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We highlight notes to reference back the important points in the book.&lt;/p&gt;

&lt;p&gt;But searching notes from a physical book is time-consuming. We need to convert those notes into digital format. I use Evernote for its offline supports and powerful search.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5mdy1c28zzpq1woqnui0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5mdy1c28zzpq1woqnui0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you might be wondering how do I convert the physical notes into digital ones. The answer is simple. Type notes manually. Now, this is a lot of work. If you earning well then hire someone to do it. If not then you can ask any family member or friend to help you out. In my case, my father does this for me.&lt;/p&gt;

&lt;p&gt;To ease the process, I  use &lt;a href="https://play.google.com/store/apps/details?id=com.google.ar.lens&amp;amp;hl=en_IN&amp;amp;gl=US" rel="noopener noreferrer"&gt;Google lens&lt;/a&gt; to scan app and convert the page into text format. It won't be accurate all the time. But 90% of the time it gives accurate text. If you have any better ways or suggestions for doing this, let me know in the comment section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcy68wyosiyciztshs3i0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcy68wyosiyciztshs3i0.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are living in a digital era. Now someone might argue to buy a kindle and avoid all this task.&lt;br&gt;
Yes, that will save a lot of time and space.&lt;br&gt;
Also, I would recommend to create the reading habit first and then go for kindle when you are confident enough.&lt;br&gt;
If you are a person who travels a lot then kindle will save a lot of space in your bag. But I don't see any much of traveling in 2021 or anytime soon.&lt;/p&gt;
&lt;h3&gt;
  
  
  Short Review
&lt;/h3&gt;

&lt;p&gt;After completing each book. I write short summary of my learnings, takeaways, and action items. Sometimes I share that on social media as well.&lt;/p&gt;
&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Reading books has helped me to think, write, and speak more clearly. The habit creation process is long and needs patience. It took me &lt;strong&gt;2 years&lt;/strong&gt; to build this habit and the tracking system. I will repeat it. It took me &lt;strong&gt;TWO YEARS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't just read this blog and move on. Execute it. I will be happier to hear stories from people who have created the reading habit.&lt;/p&gt;

&lt;p&gt;If you are still finding it hard to read. The best way is to start with small storybooks or even comics. Once you get used to it then you can pick up more technical or lengthy books.&lt;/p&gt;

&lt;p&gt;Don't give up if you don't see a result in the first few months/weeks. &lt;/p&gt;

&lt;p&gt;Just keep it consistent and remember to Read 10 pages regularly and become "1% better every day".&lt;/p&gt;

&lt;p&gt;Finally, I will conclude this by Naval Tweet.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1002068699761659905-538" src="https://platform.twitter.com/embed/Tweet.html?id=1002068699761659905"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1002068699761659905-538');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1002068699761659905&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read my blog.&lt;/p&gt;

&lt;p&gt;In case of any question, you can reach me on &lt;a href="https://twitter.com/burhanrashid52" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="//mailto:burhanrashid5253@gmail.com"&gt;Email&lt;/a&gt; me.&lt;/p&gt;

&lt;p&gt;If you like this kind of content then you can subscribe to my blog and be the first one to get notified when any new content is published.&lt;/p&gt;

&lt;p&gt;If you like this article, please like and share it with your friends/colleagues and help me to spread the word.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@alfonsmc10?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Alfons Morales&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/library?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>books</category>
      <category>reading</category>
      <category>habit</category>
      <category>developer</category>
    </item>
    <item>
      <title>Manually Generate apk using Github Actions</title>
      <dc:creator>Burhanuddin Rashid</dc:creator>
      <pubDate>Sun, 03 Jan 2021 07:02:05 +0000</pubDate>
      <link>https://dev.to/burhanrashid52/manually-generate-apk-using-github-actions-2c64</link>
      <guid>https://dev.to/burhanrashid52/manually-generate-apk-using-github-actions-2c64</guid>
      <description>&lt;p&gt;For more visibility posting this on dev.to. The &lt;a href="http://burhanrashid52.com/2020/11/28/manually-generate-apk-using-github-actions/"&gt;original&lt;/a&gt; article is posted on my &lt;a href="http://burhanrashid52.com"&gt;website&lt;/a&gt;. Let's get started :)&lt;/p&gt;

&lt;p&gt;Have you been in a situation where you want to test a feature from a specific branch? But you don't have an environment set up in the local? Or you are out somewhere and don't have access to your PC? Or your client/QA is pinging you all the time to provide APK with specific configuration and features?&lt;/p&gt;

&lt;p&gt;In this blog, we will talk about how we can solve above problems by manually generating APK using Github actions. So Let's get started.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://wkrzywiec.medium.com/github-actions-for-android-first-approach-f616c24aa0f9"&gt;Github actions.&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Basic understanding of android build using &lt;a href="https://developer.android.com/studio/build/building-cmdline"&gt;gradle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Basic of &lt;a href="https://www.taniarascia.com/how-to-create-and-use-bash-scripts/"&gt;bash&lt;/a&gt; scripting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  What problem we are trying to solve?
&lt;/h1&gt;

&lt;p&gt;The problem might differ based on your working environment, team size, and clients. Let's try to understand each of them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Indie Developer: 

&lt;ul&gt;
&lt;li&gt;If you are an Indie developer working solely on the project, then you might be overwhelmed by this approach. The reason might be

&lt;ol&gt;
&lt;li&gt;Fewer dependencies of people on you. &lt;/li&gt;
&lt;li&gt;You have the environment set up in your local. &lt;/li&gt;
&lt;li&gt;No one asking for the APK to test on daily basis.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;You can skip this whole article. But it's good to be aware of this approach because eventually, your team size will grow, and you need be well prepared for it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setting up the environment:

&lt;ul&gt;
&lt;li&gt;Let say our non-technical client wants to test a feature on the stagging environment which we have pushed to a specific branch. There are two solutions to this.

&lt;ol&gt;
&lt;li&gt;Call the developer and ask for the apk with the required parameters.&lt;/li&gt;
&lt;li&gt;Setup the android environment in the client local machine, check out the branch, tweak the parameters, and build the apk. (I don't think a non-technical client will like this solution)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;We can avoid this by providing a GUI to build the apk with configurable parameters. That's exactly what run workflow UI does. (More on this next section)&lt;/li&gt;
&lt;li&gt;The same problem mention above can be applied to QA as well. The major difference is QA is technically sound. They can get the apk by using GitHub trigger like push, pull_request, etc. The problem here is why to create this unnecessary push and pull request trigger to just generate apk. It will clutter the git history and unnecessary PR requests.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Configurability :

&lt;ul&gt;
&lt;li&gt;The ability to build apk with configured parameters is something I find very useful. The most common parameters we configure in apps are.

&lt;ol&gt;
&lt;li&gt;API Endpoints&lt;/li&gt;
&lt;li&gt;Secret/Access Keys.&lt;/li&gt;
&lt;li&gt;Other business based params like Threshold values, Number of Re attempts. etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How do we solve this problem ?
&lt;/h1&gt;

&lt;p&gt;Github Actions provides various trigger events to run your workflow. Following is an example of some of the trigger events, like pushing a commit on the main branch, creating pull requests, tags, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Trigger the workflow on push or pull request,&lt;/span&gt;
  &lt;span class="c1"&gt;# but only for the main branch&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    
      &lt;span class="c1"&gt;# Push events on main branch&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
      &lt;span class="c1"&gt;# Push events to branches matching refs/heads/mona/octocat&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mona/octocat'&lt;/span&gt;
      &lt;span class="c1"&gt;# Push events to branches matching refs/heads/releases/10&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;releases/**'&lt;/span&gt;

    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;             &lt;span class="c1"&gt;# Push events to v1 tag&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1.*&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;To trigger an event manually, Github actions have added a new trigger event called workflow_dispatch. Below is the sample code and UI. (More in the next section)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Log&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;level'&lt;/span&gt;     
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;warning'&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;scenario&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tags'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s4-vff6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wbnxscjfwlwo9d7gerf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s4-vff6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wbnxscjfwlwo9d7gerf7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;First we need to setup a configurable parameters in android and then we can update those params using GitHub inputs in the workflow. So will start with android first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurable properties in android.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;We need to set up the configurable parameters in a file. In this case, we are putting this into &lt;code&gt;local.properties&lt;/code&gt; file, which we usually &lt;strong&gt;do not check-in&lt;/strong&gt; VCS.
&lt;strong&gt;Note:&lt;/strong&gt; It can be any file. We just to point to that file in &lt;code&gt;build.gradle&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create or update the &lt;code&gt;local.properties&lt;/code&gt; file like &lt;a href="https://github.com/burhanrashid52/SampleWorkflow/blob/update_existing_properties/local.properties"&gt;this&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;BASE_URL="https://production.example.com/api/v1"&lt;/span&gt;
&lt;span class="s"&gt;MAP_KEY="production_sample_key"&lt;/span&gt;
&lt;span class="s"&gt;RETRY_ATTEMPTS=3&lt;/span&gt;
&lt;span class="s"&gt;THRESHOLD_VALUE=0.05&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update &lt;code&gt;build.gradle&lt;/code&gt; in the app like &lt;a href="https://github.com/burhanrashid52/SampleWorkflow/blob/main/app/build.gradle#L6"&gt;this&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;localProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;localProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"local.properties"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;

&lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;defaultConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//...&lt;/span&gt;
        &lt;span class="n"&gt;buildConfigField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"String"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"APP_BASE_URL"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;localProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'BASE_URL'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;buildConfigField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"int"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"APP_RETRY_ATTEMPTS"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;localProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'RETRY_ATTEMPTS'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;buildConfigField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"float"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"APP_THRESHOLD_VALUE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;localProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'THRESHOLD_VALUE'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;buildTypes&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"maps_key"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;localProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'MAP_KEY'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="c1"&gt;//..&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can refer local properties using &lt;code&gt;BuildConfig&lt;/code&gt; in this app like this.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;txtConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findViewById&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txtConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;configText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
            BASE URL :  ${BuildConfig.APP_BASE_URL}
            MAP_KEY :  ${getString(R.string.maps_key)}
            RE-ATTEMPT :  ${BuildConfig.APP_RETRY_ATTEMPTS}
            THRESHOLD VALUE :  ${BuildConfig.APP_THRESHOLD_VALUE}
        """&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimIndent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;txtConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configText&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;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Sometimes the &lt;code&gt;local.properties&lt;/code&gt; do not create &lt;code&gt;BuildConfig&lt;/code&gt; on sync. It will get generated when we build the apk. &lt;a href="https://stackoverflow.com/a/60430117/5301119"&gt;Ref&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The output will look like this when we run the apk.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GnsW0yJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u57ooxsrgaij3yhmk3ld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GnsW0yJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u57ooxsrgaij3yhmk3ld.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are facing any issues. You can check out the sample workflow app &lt;a href="https://github.com/burhanrashid52/SampleWorkflow/"&gt;here&lt;/a&gt;. For setting the &lt;a href="http://local.properties"&gt;local.properties&lt;/a&gt; please checkout this &lt;a href="https://blog.mindorks.com/using-local-properties-file-to-avoid-api-keys-check-in-into-version-control-system"&gt;mindork&lt;/a&gt; blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Github workflow
&lt;/h2&gt;

&lt;p&gt;We create yaml file inside &lt;code&gt;.github/workflow&lt;/code&gt; folder. To trigger the workflow manually we will use &lt;code&gt;workflow_dispatch&lt;/code&gt; as a trigger. This will show the Run Workflow UI which we have seen above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Manual Generate APK&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;/....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To show the input config values, we use inputs here. The &lt;code&gt;baseUrl&lt;/code&gt; is an input key which we will use to read the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Manual Generate APK&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Base&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;URL'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://production.example.com/api/v1'&lt;/span&gt;

      &lt;span class="na"&gt;mapKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Map&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Key'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production_sample_key'&lt;/span&gt;

      &lt;span class="na"&gt;reAttempt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Number&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;re-attempts'&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

      &lt;span class="na"&gt;thresholdValue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Threshold&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;value'&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.05'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting &lt;code&gt;required&lt;/code&gt; params as &lt;code&gt;true&lt;/code&gt; show an asterisk indicating a mandatory field. The &lt;code&gt;description&lt;/code&gt; is shown as the field name in the UI. The &lt;code&gt;default&lt;/code&gt; param will set the default value in the input field.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lsr2Lq-g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/klr3o8lr8n9jh06o1jot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lsr2Lq-g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/klr3o8lr8n9jh06o1jot.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will add command to build the apk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Assemble app debug APK&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash ./gradlew assembleDebug --stacktrace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up bash script
&lt;/h3&gt;

&lt;p&gt;If we try to run this workflow now, it will fail with error &lt;a href="http://local.properties"&gt;local.properties&lt;/a&gt; not found. This is because we have not checked-in that file in our VCS. We can fix this by creating local.properties on the fly while running the github workflow. We can do this by running the linux command in the workflow which creates &lt;code&gt;local.properties&lt;/code&gt; file with all config values. &lt;/p&gt;

&lt;p&gt;It's a better to wrap this sequence of linux command into bash script. It will avoid the clutter code in the workflow and provide more flexibility to update the script.&lt;/p&gt;

&lt;p&gt;Now we will create and checked in the bash script file &lt;code&gt;update_properties.sh&lt;/code&gt; in the VCS which will look this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;local.properties
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"BASE_URL=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local.properties
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"MAP_KEY=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local.properties
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"RETRY_ATTEMPTS=&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local.properties
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"THRESHOLD_VALUE=&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$1, $2,$3, and $4 are the 4 arguments that will be passed into the script from the inputs values.&lt;/p&gt;

&lt;p&gt;We need to run the bash script with input values before building the apk. We get these values by using &lt;code&gt;github.event.inputs.{key}&lt;/code&gt; properties. You can find the source file &lt;a href="https://github.com/burhanrashid52/SampleWorkflow/blob/main/.github/workflows/manual_generate_apk.yml#L37"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Print Params Values&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;bash update_properties.sh ${{ github.event.inputs.baseUrl }} ${{ github.event.inputs.mapKey }} ${{ github.event.inputs.reAttempt }} ${{ github.event.inputs.thresholdValue }}&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Assemble app debug APK&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash ./gradlew assembleDebug --stacktrace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fun Fact: I was able to run the script after 17 failed attempts. So don't worry if the script does not work for the first time. Keep googling as I did 😂&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xarjidvr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h35w82b0hox3easpqcoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xarjidvr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h35w82b0hox3easpqcoo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Run the workflow
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;We can now run the workflow from UI in github action tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KpbeGYK9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mc9k7lt8ouqmi1his2sn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KpbeGYK9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mc9k7lt8ouqmi1his2sn.gif" alt="Alt Text"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uyb_WMiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/piv14astm52t5cux9aey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uyb_WMiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/piv14astm52t5cux9aey.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want to update the existing &lt;code&gt;local.properties&lt;/code&gt; or any other file which you are already using then you need to change your script. Please check this &lt;a href="https://github.com/burhanrashid52/SampleWorkflow/blob/update_existing_properties/update_properties.sh"&gt;branch&lt;/a&gt; for example.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Key things to remember
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;The workflow UI won't show up if the workflow is pushed into a separate branch but not in the &lt;code&gt;main/master&lt;/code&gt; branch. The workflow will only be visible if it is pushed to &lt;code&gt;main/master&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;It  won't run on a branch that does not have the workflow. The UI will look like this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tstAxyLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/13ohexyd96jzgohwa391.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tstAxyLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/13ohexyd96jzgohwa391.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The linux text replace &lt;code&gt;sed -i&lt;/code&gt; command will work on github action which runs on the linux. For mac we need use &lt;code&gt;sed -i ""&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sometimes the &lt;code&gt;local.properties&lt;/code&gt; do not create &lt;code&gt;BuildConfig&lt;/code&gt; on sync. It will get generated when we build the apk. &lt;a href="https://stackoverflow.com/a/60430117/5301119"&gt;Ref&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The GitHub manually trigger was something the dev asked for when the action was initially launched. Because it provides more flexibility and ease of use, especially for clients/QA's. They also have an API to trigger this workflow which opens the door for more automation.&lt;/p&gt;

&lt;p&gt;In case of any question and issue, you can reach me on &lt;a href="https://www.twitter.com/burhanrashid52"&gt;Twitter&lt;/a&gt;. Stay updated by subscribing to my blog. Thank you for taking the time to read this article. If you like this article, please like and share it with your friends/colleagues and spread the word.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/"&gt;https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.mindorks.com/using-local-properties-file-to-avoid-api-keys-check-in-into-version-control-system"&gt;https://blog.mindorks.com/using-local-properties-file-to-avoid-api-keys-check-in-into-version-control-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/16745988/sed-command-with-i-option-in-place-editing-works-fine-on-ubuntu-but-not-mac"&gt;https://stackoverflow.com/questions/16745988/sed-command-with-i-option-in-place-editing-works-fine-on-ubuntu-but-not-mac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://abelsquidhead.com/index.php/2020/07/29/manually-trigger-actions-workflow-in-github-how-did-i-not-know-about-this/"&gt;https://abelsquidhead.com/index.php/2020/07/29/manually-trigger-actions-workflow-in-github-how-did-i-not-know-about-this/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.community/t/workflow-dispatch-event-not-working/128856"&gt;https://github.community/t/workflow-dispatch-event-not-working/128856&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>github</category>
      <category>actions</category>
      <category>cicd</category>
      <category>android</category>
    </item>
    <item>
      <title>Getting started with Firebase emulators suite for Android</title>
      <dc:creator>Burhanuddin Rashid</dc:creator>
      <pubDate>Fri, 25 Sep 2020 06:51:29 +0000</pubDate>
      <link>https://dev.to/burhanrashid52/getting-started-with-firebase-emulators-suite-for-android-l4o</link>
      <guid>https://dev.to/burhanrashid52/getting-started-with-firebase-emulators-suite-for-android-l4o</guid>
      <description>&lt;p&gt;&lt;em&gt;For more visibility posting this on dev.to. The &lt;a href="http://burhanrashid52.com/2020/09/21/getting-started-with-firebase-emulators-suite-for-android/"&gt;original&lt;/a&gt; article is posted on my &lt;a href="http://burhanrashid52.com"&gt;website&lt;/a&gt;.Let's get started :)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do you know a friend/colleague who tests their application directly in the production environment?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lBwGZtgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/images.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lBwGZtgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/images.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yeah, that’s a bad practice. We should have a local or staging environment where we test our code before we push to the production. That’s where the Firebase emulator comes into the picture. Firebase emulator is a tool that helps us to test various firebase services in our local environment altogether.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Firebase Emulator?
&lt;/h1&gt;

&lt;p&gt;According to the official documentation&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Firebase Local Emulator Suite consists of individual service emulators built to accurately mimic the behavior of Firebase services. This means you can connect your app directly to these emulators to perform integration testing or QA without touching production data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DmSv_vp7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/emulator_suite_block.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DmSv_vp7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/emulator_suite_block.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, there are 5 services available in the emulator.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud Firestore&lt;/li&gt;
&lt;li&gt;Realtime database&lt;/li&gt;
&lt;li&gt;Cloud Functions&lt;/li&gt;
&lt;li&gt;Hosting&lt;/li&gt;
&lt;li&gt;Cloud Pub/Sub&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; However your app will still continue to communicate with production Firebase services when emulators are not available or configured.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why do we need Firebase Emulator? What problem does it solve?
&lt;/h1&gt;

&lt;p&gt;We need the Firestore emulator to safely read and write documents in testing. Since all services are connected to the local environment, these trigger the events in each other’s services.&lt;/p&gt;

&lt;p&gt;For example, The realtime database writes may trigger the cloud functions in the emulator.&lt;/p&gt;

&lt;p&gt;Because of a lack of testing we face the following issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Time Consuming
&lt;/h3&gt;

&lt;p&gt;No one writes a perfect code in the first attempt. It’s an iterative process. We need a fast feedback loop. Let’s say that if we are writing a cloud function without an emulator, then every time we do a change we need to push to the server which will take around 20-30 seconds which is a waste of time, causes distraction, and hamper the productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Debugging
&lt;/h3&gt;

&lt;p&gt;While developing we make a lot of assumptions and mistakes which are fixed by debugging. Without a local setup, debugging directly on the server is a nightmare. No, having &lt;code&gt;console.log()&lt;/code&gt; in each line of the code is not a good solution either. Having a local environment allows us to debug more effectively using our favorite IDE.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Data Modeling
&lt;/h3&gt;

&lt;p&gt;The most FAQ on firebase is about data modeling for the database. We keep experimenting with the structure of the database and if we don’t have a local environment then it’s become very difficult to define a clear boundary between the test data and the production data.&lt;/p&gt;

&lt;p&gt;The chances of messing up the production data are very high, by doing a typo, using the wrong key, or deleting a document by mistake.&lt;/p&gt;

&lt;p&gt;There is one workaround for this which I am going to talk about in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Integration testing using CI/CD
&lt;/h3&gt;

&lt;p&gt;Each individual product emulator in the Emulator Suite responds to SDK and REST API calls just like production Firebase services. So we can use our own testing tools integrating into our CI/CD to write self-contained integration tests that use the Local Emulator Suite as the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cost Real Money
&lt;/h3&gt;

&lt;p&gt;The first thing we need to check for any third-party services is “pricing”. I hope you have already checked for the firebase. If not then please visit &lt;a href="https://firebase.google.com/pricing."&gt;pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The pricing won’t cause any problem if you are working on a project as a hobby which does not have any real users. But if you plan for the real customers/users then you will reach a point where you have let say, 10K users. Due to the increase in the number of users, the usage of services will grow proportionally.&lt;/p&gt;

&lt;p&gt;Realtime DB will have a thousand simultaneous connections. Firestore will have more read/write/deletes. The cloud function will have high invokes which eventually cost you a lot of money.&lt;/p&gt;

&lt;p&gt;So we should be aware of any unnecessary reads and downloads from the firebase especially while testing because we used to push all kinds of junk data to test various scenarios.&lt;/p&gt;

&lt;p&gt;I recommend watching this video for firestore pricing.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/6NegFl9p_sE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

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

&lt;h3&gt;
  
  
  6. Work-around with Multiple Projects
&lt;/h3&gt;

&lt;p&gt;Since we have one database per project most developers create multiple projects to handle production and test environments separately.&lt;/p&gt;

&lt;p&gt;For example, I will create a Firebase project with the name “My Prod App” adding my app with package &lt;code&gt;com.burhanrashid52.firebase.sampleapp&lt;/code&gt;, and then I’ll create another project called “My Test App” with package name &lt;code&gt;com.burhanrashid52.firebase.sampleapp.testing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will help to avoid the issue because firebase &lt;a href="https://stackoverflow.com/questions/42609983/does-the-firebase-spark-free-plan-work-on-a-per-project-basis"&gt;pricing is project-based, not account-based&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to get started?
&lt;/h1&gt;

&lt;p&gt;When I was writing the first draft of this section. I wrote the entire step by step command in order to set up the firebase emulator suite, which firebase documentation already has. So why reinvent the wheel? Please go through the official &lt;a href="https://firebase.google.com/docs/emulator-suite/connect_and_prototype#locally_initialize_a_firebase_project"&gt;documentation&lt;/a&gt; for setting this up. If you are a person who understands things more visually. Please check out this video.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pkgvFNPdiEs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here is my short version of that steps with given commands:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup the CLI → &lt;code&gt;npm install -g firebase-tools&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Login to the firebase account → &lt;code&gt;firebase login&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Select the project.&lt;/li&gt;
&lt;li&gt;Initialize firebase for the project → &lt;code&gt;firebase init&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Select the products you need.&lt;/li&gt;
&lt;li&gt;Start the emulator → &lt;code&gt;firebase emulators:start&lt;/code&gt; 

&lt;ul&gt;
&lt;li&gt;(Optional) Rum specific feature using —only&lt;/li&gt;
&lt;li&gt;Firestore: &lt;code&gt;firebase emulators:start --only firestore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;RealtimeDB : &lt;code&gt;firebase emulators:start --only database&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Cloud Functions : &lt;code&gt;firebase emulators:start --only functions&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Uqxyszy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/Screenshot_2020-09-09_at_8.14.03_AM-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Uqxyszy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/Screenshot_2020-09-09_at_8.14.03_AM-2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7.Run localhost:4000 in the browser and you will see an emulator suite console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2T3h60-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/Screenshot_2020-09-09_at_8.15.17_AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2T3h60-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://burhanrashid52.com/wp-content/uploads/2020/09/Screenshot_2020-09-09_at_8.15.17_AM.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More details &lt;a href="https://firebase.google.com/docs/emulator-suite/install_and_configure"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dashboard displays the status(On/Off) of each service emulator with a port number. We connect our client app to those port numbers. (More on this later).&lt;/p&gt;

&lt;p&gt;We can also &lt;a href="https://github.com/firebase/quickstart-nodejs/issues/65"&gt;change&lt;/a&gt; the port if any of the default ports are occupied.&lt;/p&gt;

&lt;h1&gt;
  
  
  Connect Android (client) to firebase emulator
&lt;/h1&gt;

&lt;p&gt;Our firebase emulator suite is up and running. Now we need to connect our client to the emulator suite. After that our client will be able to push and pull the data of this emulator and we can observe the changes on the emulator UI page.&lt;/p&gt;

&lt;p&gt;I am using Android as the client here. If you are using the iOS or Web as a client then check out this official &lt;a href="https://firebase.google.com/docs/emulator-suite/connect_and_prototype"&gt;document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we run android on the “android emulator” we cannot use &lt;code&gt;localhost:8080&lt;/code&gt; as a host. We need to use &lt;code&gt;10.0.2.2:8080&lt;/code&gt; as the “android emulator” IP. We can test that by running &lt;code&gt;10.0.2.2:8080&lt;/code&gt; in the android emulator browser and verify that firebase emulator UI is displayed in the android emulator browser.&lt;/p&gt;

&lt;p&gt;Following are code snippets to set the host. The port is different for each service.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Firestore for Android
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FirebaseFirestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FirebaseFirestoreSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"10.0.2.2:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSslEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPersistenceEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firestoreSettings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Realtime database for Android
&lt;/h3&gt;

&lt;p&gt;For realtime DB we need to add a project-id in the URL. We can find this in the firebase project setting or directly copy from the realtime database tab from the firebase emulator UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FirebaseDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://10.0.2.2:9000?ns=projectId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Cloud Function for Android
&lt;/h3&gt;

&lt;p&gt;In case of &lt;a href="https://firebase.google.com/docs/functions/callable#java"&gt;manually&lt;/a&gt; calling cloud function from the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val instance = FirebaseFunctions.getInstance();
instance.useEmulator("10.0.2.2", 5001)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;We just need to make sure that we operating on the created instance. Otherwise it will get connect to the production firebase db. A better practice would be to injecting a singleton class which provide the same instance throughout the application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Dependency Injection using Koin
&lt;/h3&gt;

&lt;p&gt;We are using &lt;a href="https://insert-koin.io/"&gt;koin&lt;/a&gt; module and making all the dependency as a singleton using &lt;code&gt;single {}&lt;/code&gt; Lamba and injecting that same instance where it required using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;firebaseModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FirebaseFirestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;settings&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;isFirebaseLocal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;FirebaseFirestoreSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"10.0.2.2:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSslEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPersistenceEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;FirebaseFirestoreSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSslEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPersistenceEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firestoreSettings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;single&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;isFirebaseLocal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;FirebaseDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://10.0.2.2:9000?ns=projectId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;FirebaseDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&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="nf"&gt;single&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FirebaseFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&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;isFirebaseLocal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEmulator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"10.0.2.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFirebaseLocal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We used a flag &lt;code&gt;isFirebaseLocal&lt;/code&gt; and set at &lt;code&gt;MyApp&lt;/code&gt; class. It helps to toggle between local and production database. We can put this flag in the gradle setting as well.&lt;/p&gt;

&lt;p&gt;We can inject using Koin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;firestore&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FirebaseFirestore&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Release builds
&lt;/h3&gt;

&lt;p&gt;For release build, I always make this flag as false. For that, I’ve done something like this. So that I don’t accidentally put true for the release build. There are better ways to do this. But for simplicity, I am going with this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&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="nc"&gt;BuildConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;isFirebaseLocal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Start Koin&lt;/span&gt;
        &lt;span class="nf"&gt;startKoin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;androidLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firebaseModule&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;h1&gt;
  
  
  Key things to remember.
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Double-check your host IP and port on a client-side. I wasted 3 hours of debugging on “why my client app is not connecting to the emulator suite”.&lt;/li&gt;
&lt;li&gt;Firebase emulator does not persist data locally. It clears all the data when we restart the server. A similar action can be achieved by clicking on the clear data button on firestore tab. This will be a pain if we have a huge amount of data and various scenarios to test. I’ve referred a fix in the know issue section.&lt;/li&gt;
&lt;li&gt;We might see this error if we try to update real-time database using cloud functions.&lt;/li&gt;
&lt;li&gt;If we want to perform an operation on the realtime database from the cloud function then we need to set the local URL of the realtime database when we initialize the app. More &lt;a href="https://firebase.google.com/docs/admin/setup#initialize-sdk"&gt;here&lt;/a&gt;. Don’t forget to switch back to the production URL when you are deploying.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;applicationDefault&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;databaseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:9000?ns=projectId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;5.Double-check your keys which we are using for firestore and realtime time. A typo can drain all your mental, physical, and spiritual energy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Known Issues
&lt;/h1&gt;

&lt;p&gt;Firebase emulator suite is new and far from perfect and sometimes it has bugs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/firebase/firebase-tools-ui/issues/327"&gt;Firestore UI bug&lt;/a&gt;: When we push data using the client we are not able to see the data in the firestore emulator page. But our data is pushed correctly from the client and the functionality is working as expected. I’ve already filed an issue here. Please upvote if you find the same.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/firebase/firebase-tools/issues/1167"&gt;Persist data locally&lt;/a&gt;: Already discuss this in the above section. The Import/Export button on UI might help as we do for realtime using the JSON file.&lt;/li&gt;
&lt;li&gt;Authentication is not available &lt;a href="https://github.com/firebase/firebase-tools/issues/1677"&gt;locally&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I’ve developed an app using firebase before and believe me this feature saves a lot of time and energy.&lt;/p&gt;

&lt;p&gt;Now tell your friend/colleague that we have a better way of testing the code using a firebase emulator instead of doing in production. It’s just beginning.&lt;/p&gt;

&lt;p&gt;Looking forward to more features and bugs fixes. Thanks to Firebase Team&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this article. If you like this article, please like and share it with your friends/colleagues, and stay updated for this kind of post by subscribing to my blog. In case of any question/doubts hit me on any social media platform &lt;a href="https://twitter.com/burhanrashid52"&gt;@burhanrashid52&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>testing</category>
      <category>android</category>
      <category>emulator</category>
    </item>
    <item>
      <title>Testing in Flutter</title>
      <dc:creator>Burhanuddin Rashid</dc:creator>
      <pubDate>Fri, 11 Sep 2020 10:45:33 +0000</pubDate>
      <link>https://dev.to/burhanrashid52/testing-in-flutter-4869</link>
      <guid>https://dev.to/burhanrashid52/testing-in-flutter-4869</guid>
      <description>&lt;p&gt;If you are struggling to write tests for legacy codebase in a flutter then yesterday I talked about "Testing in Flutter" for legacy codebase at Mobile Z-days.&lt;/p&gt;

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

&lt;p&gt;The more features your flutter app has, the harder it is to test manually. Automated tests help ensure that your app performs correctly before you publish it while retaining your feature and bug-fix velocity.&lt;/p&gt;

&lt;p&gt;Writing these tests for your Flutter app can help you create a resilient and bug-free code.&lt;/p&gt;

&lt;p&gt;In this talk, we will take about how to do unit, integration, and widget testing in a flutter with live demo while discussing the fact that there are trade-offs between different kinds of testing.&lt;/p&gt;

&lt;p&gt;We will also look into multiple Continuous integration (CI) services that are available for flutter to get started, which allows us to run the tests automatically when pushing new code changes.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>flutter</category>
      <category>legacy</category>
      <category>codebase</category>
    </item>
  </channel>
</rss>
