<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ashutosh, Android Developer, Computer Science Student, Linux &amp; Mobile Tech Enthusiast, Open-Source Explorer]]></title><description><![CDATA[Explore my journey as an Android Developer and Computer Science student passionate about Linux, Mobile Tech, and Open Source. Join me in the world of coding and creativity!]]></description><link>https://blog.ashutoshwahane.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1696243289849/gaLj2lMID.png</url><title>Ashutosh, Android Developer, Computer Science Student, Linux &amp;amp; Mobile Tech Enthusiast, Open-Source Explorer</title><link>https://blog.ashutoshwahane.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 21:50:08 GMT</lastBuildDate><atom:link href="https://blog.ashutoshwahane.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Wearable Wonders :  Wear OS Introduction]]></title><description><![CDATA[In recent years, wearable technology has boomed. Smartwatches, in particular, have become essential companions in our daily lives. They do more than just tell time—they help us track fitness goals and stay connected with notifications and apps. Smart...]]></description><link>https://blog.ashutoshwahane.dev/wearable-wonders-wear-os-introduction</link><guid isPermaLink="true">https://blog.ashutoshwahane.dev/wearable-wonders-wear-os-introduction</guid><category><![CDATA[watch app]]></category><category><![CDATA[wear os development]]></category><category><![CDATA[WearOS]]></category><category><![CDATA[Android]]></category><category><![CDATA[android development]]></category><dc:creator><![CDATA[Ashutosh Wahane]]></dc:creator><pubDate>Sun, 12 May 2024 13:00:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1711039647163/209217ac-62b2-4256-b043-37bd14739e45.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In recent years, wearable technology has boomed. Smartwatches, in particular, have become essential companions in our daily lives. They do more than just tell time—they help us track fitness goals and stay connected with notifications and apps. Smartwatches are like versatile sidekicks, offering us a range of functions all in one handy device.</p>
<p>If you're an Android developer, diving into Wear OS development is a breeze! Just like Android development, you'll find many similarities—whether it's designing UI using Compose, creating activities, managing notifications, and much more.</p>
<p><strong>There are two types of wear os application one is Standalone and Non Standalone App.</strong></p>
<ol>
<li><p><strong>Standalone</strong><br /> These apps operate independently on your Wear OS device, requiring no constant connection or syncing with a companion app on your smartphone. They offer full functionality directly from your smartwatch:</p>
<ul>
<li><p><strong>Google Fit</strong>: Tracks your activity and health metrics solely on your smartwatch, syncing data with your Google account when connected to the internet.</p>
</li>
<li><p><strong>Spotify</strong>: Enables you to stream music or podcasts directly from your smartwatch without needing your phone nearby. It operates over Wi-Fi or cellular data independently.</p>
</li>
</ul>
</li>
<li><p><strong>Non Standalone</strong><br /> These apps rely on a connection with a companion app on your smartphone to fully function. They offer limited functionality or require constant syncing with your smartphone.</p>
<ul>
<li><p><strong>Google Maps</strong>: While you can receive directions on your smartwatch, real-time navigation updates depend on a constant connection to your smartphone.</p>
</li>
<li><p><strong>WhatsApp</strong>: While you can receive and read messages on your Wear OS device, sending messages or media requires the smartphone app for full functionality and syncing.</p>
</li>
</ul>
</li>
</ol>
<p>When developing a Wear OS app using Compose for UI development, syncing data between the watch app and the Android app is crucial.</p>
<ol>
<li><p><strong>Data Client</strong>: The Data Client provides a streamlined approach to share data between the Wear OS app and the Android app. It enables seamless communication and synchronization of data across both platforms. With the Data Client, developers can efficiently send and receive data, ensuring consistency and real-time updates between the watch and the smartphone app.</p>
</li>
<li><p><strong>Message Client</strong>: The Message Client allows bidirectional communication between the Wear OS app and the Android app through message passing. Developers can use this method to send messages containing data payloads, enabling real-time updates and interactions between the watch and the smartphone.</p>
</li>
<li><p><strong>Channel Client</strong>: The Channel Client facilitates communication between the Wear OS app and the Android app through data channels. It provides a reliable and efficient way to transfer large amounts of data, such as files or images, between the two platforms. Developers can establish channels to transmit data seamlessly, enhancing the user experience across devices.</p>
</li>
</ol>
<p>Sample code Resources for each client:<br /><a target="_blank" href="https://github.com/android/wear-os-samples/tree/main/DataLayer">https://github.com/android/wear-os-samples/tree/main/DataLayer</a></p>
<p>If you have any questions, comments, or suggestions, please don't hesitate to reach out. Your feedback is invaluable as I continue to explore and share information on topics that matter.</p>
<p><strong>Please subscribe to my blog for more Android development tips and tricks.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Shielding Your Android App]]></title><description><![CDATA[Hi Guys! Do you recall learning in biology class about cells being the fundamental unit of life, with both structural and functional properties? Well, in today's world, mobile phones have become just as essential and fundamental to our daily lives.
H...]]></description><link>https://blog.ashutoshwahane.dev/shielding-your-android-app</link><guid isPermaLink="true">https://blog.ashutoshwahane.dev/shielding-your-android-app</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[android app security]]></category><category><![CDATA[vapt]]></category><dc:creator><![CDATA[Ashutosh Wahane]]></dc:creator><pubDate>Sun, 01 Oct 2023 07:27:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1696070887226/34296f35-1016-440d-ad06-c57508f038e0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi Guys! Do you recall learning in biology class about cells being the fundamental unit of life, with both structural and functional properties? Well, in today's world, mobile phones have become just as essential and fundamental to our daily lives.</p>
<p>However, with the rising number of cyber threats targeting mobile devices, developers must take measures to protect and safeguard our apps.</p>
<p>In this blog, we will learn about the VAPT security guidelines for Android and protecting the Android client ecosystem.</p>
<hr />
<h3 id="heading-what-is-vapt"><strong>What is VAPT?</strong></h3>
<p>Vulnerability Assessment and Penetration Testing (VAPT) for Android is like checking if your Android phone or tablet has any security problems and fixing them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696072399959/1e95037f-d38e-41e8-81fa-8dd7dafff0f0.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-for-better-understanding-lets-take-one-example"><strong>For better understanding let's take one example</strong></h3>
<p>Imagine your Android device is like a house, and VAPT is like checking if all the doors and windows are locked properly and if there are any hidden ways for bad people to get in. If we find any problems, we make sure to fix them so your device stays safe.</p>
<p>VAPT involves looking for things like weak spots in the software, unsafe ways your device talks to the internet, or any other issues that could make it easy for hackers to do bad things. It's all about making your Android device more secure and less vulnerable to cyber threats.</p>
<hr />
<h3 id="heading-here-are-the-common-vapt-security-guidelines-for-android">Here are the common VAPT security guidelines for Android</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696077820601/432f766a-3dbe-4c9f-b1d8-40799307ad50.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-root-detection">Root Detection</h3>
<p>Developers need to ensure that their apps can detect this security vulnerability. Hackers often use root devices or take advantage of devices that have been rooted by the owner to gain access to sensitive user data and other secrets stored in an app's source code</p>
<p><strong>Why is a rooted device potentially dangerous to users/apps?</strong></p>
<p>System security and safeguards cannot be guaranteed after the root. At root, device data is at risk, including gaining access to personal information such as contact lists, emails, and other data, or collecting data like credentials and passwords. With a rooted device, a user or malicious program can elevate their permissions to root and circumvent this protection giving them access to other apps’ private data.</p>
<p>So it is the best way to check in your application whether the device is rooted or not to avoid data theft.</p>
<h3 id="heading-solutions">Solutions</h3>
<h3 id="heading-free">Free:</h3>
<p>There are several open-source solutions for checking for root, such as RootBeer, AntiMagisk, JailMonkey, and others, but the solutions are not 100% effective since third-party apps, such as Magisk, can bypass the root detection.</p>
<p>Because all of these solutions are client-side implementations, the attacker can bypass the root detection with the Magisk app, which hides the root files of the selected app, and there is a tool called Frida available that brute forces code, such as updating boolean conditions during runtime.</p>
<p><a target="_blank" href="https://gist.github.com/Ashutoshwahane/b0b2eca58d21857e006401d9f58c051a">https://gist.github.com/Ashutoshwahane/b0b2eca58d21857e006401d9f58c051a</a></p>
<p><a target="_blank" href="https://github.com/GantMan/jail-monkey">https://github.com/GantMan/jail-monkey</a></p>
<p><a target="_blank" href="https://github.com/scottyab/rootbeer">https://github.com/scottyab/rootbeer</a></p>
<p><a target="_blank" href="https://stackoverflow.com/questions/18716808/how-to-check-usb-debugging-enabled-programmatically">https://stackoverflow.com/questions/18716808/how-to-check-usb-debugging-enabled-programmatically</a></p>
<h3 id="heading-paid">Paid:</h3>
<p>Play Integrity is a suite of tools and services that helps developers protect their apps and games from abuse and attacks. It provides a variety of signals and features that can be used to detect and prevent unauthorized access, cheating, fraud, and other malicious activity.</p>
<p>Developers can use Play Integrity in a variety of ways. For example, they can use the Play Integrity API to:</p>
<ul>
<li><p>Check that the app is running on a genuine Android device.</p>
</li>
<li><p>Check that the app has not been tampered with.</p>
</li>
</ul>
<p>It is the best way to secure the app because of server-side validation.</p>
<p>Official Documentation: <a target="_blank" href="https://developer.android.com/google/play/integrity">https://developer.android.com/google/play/integrity</a></p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696077959416/3baff330-ace8-49a0-b651-3a1418a1ba08.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-code-obfuscation">Code obfuscation</h3>
<p>Code obfuscation is a security technique that makes it more difficult for attackers to reverse engineer and understand your code. This can help to protect your app from being hacked or tampered with.</p>
<p>There are several different ways to obfuscate code for Android apps. One popular tool is ProGuard, which is a free and open-source tool that can be used to obfuscate Java code. ProGuard can rename classes, methods, and variables, and it can also remove unused code and resources.</p>
<p>In Simple words, Code Obfuscation is the process of converting the actual source code to unreadable and ununderstandable code.</p>
<p>How to obfuscate the code in app-level build.gradle file</p>
<pre><code class="lang-kotlin">android {
    buildTypes {
        getByName(<span class="hljs-string">"release"</span>) {
            <span class="hljs-comment">// Enables code shrinking, obfuscation, and optimization for only</span>
            <span class="hljs-comment">// your project's release build type. Make sure to use a build</span>
            <span class="hljs-comment">// variant with `isDebuggable=false`.</span>
            isMinifyEnabled = <span class="hljs-literal">true</span>

            <span class="hljs-comment">// Enables resource shrinking, which is performed by the</span>
            <span class="hljs-comment">// Android Gradle plugin.</span>
            isShrinkResources = <span class="hljs-literal">true</span>

            <span class="hljs-comment">// Includes the default ProGuard rules files that are packaged with</span>
            <span class="hljs-comment">// the Android Gradle plugin. To learn more, go to the section about</span>
            <span class="hljs-comment">// R8 configuration files.</span>
            proguardFiles(
                getDefaultProguardFile(<span class="hljs-string">"proguard-android-optimize.txt"</span>),
                <span class="hljs-string">"proguard-rules.pro"</span>
            )
        }
    }
    ...
}
</code></pre>
<p>For more detail please refer to the official documentation: <a target="_blank" href="https://developer.android.com/build/shrink-code">https://developer.android.com/build/shrink-code</a></p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696078091245/5db2a0d9-bd56-4c6f-b733-2cfb5f8d1e31.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-hardcoded-keys">Hardcoded Keys</h3>
<p>Never hard code the API keys and other sensitive information that are essential for many Android apps. However, it is important to keep these keys safe, as they can be used to access your app's data or resources. One way to do this is to store the keys in a <a target="_blank" href="http://local.properties/">local.properties</a> file.</p>
<p>The <a target="_blank" href="http://local.properties">local.properties</a> file is a hidden file that is located in the root directory of your Android project. It is not included in version control systems(It should be added in the git ignore file), so it will not be shared with others when you commit your code.</p>
<p>To store an API key in <a target="_blank" href="http://local.properties">local.properties</a>, simply add a line with the key name and value. For example:</p>
<pre><code class="lang-kotlin">API_KEY=YOUR_API_KEY
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-comment">// build.gradle.kts</span>
        <span class="hljs-keyword">val</span> apiKey = gradleLocalProperties(rootDir).getProperty(<span class="hljs-string">"API_KEY"</span>)
        buildConfigField(<span class="hljs-string">"String"</span>, <span class="hljs-string">"API_KEY"</span>, apiKey)
</code></pre>
<p>Clean and Re-Build the project</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//access the BuildConfig the API key field anywhere in the module and It gets generated in the compile time</span>
<span class="hljs-keyword">val</span> apiKey = BuildConfig.API_KEY
</code></pre>
<ul>
<li><p>Do not hard-code the key value in your code. This would make it easier for someone to steal the key.</p>
</li>
<li><p>Keep the <a target="_blank" href="http://local.properties">local.properties</a> file secure. Do not share it with anyone who does not need to have access to it.</p>
</li>
</ul>
<p>To make it more secure, we can fetch the keys from the backend server during runtime.</p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696078232005/b8181e8f-4d5d-4b24-a4bd-5728993e6eea.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-encrypted-shared-preference-and-local-storage"><strong>Encrypted shared preference and Local Storage</strong></h3>
<p>DataStore is a new and improved data storage solution aimed at replacing SharedPreferences. Built on Kotlin coroutines and Flow, DataStore provides two different implementations: Proto DataStore, which stores typed objects (backed by protocol buffers), and Preferences DataStore, which stores key-value pairs.</p>
<p>But there is a problem, DataStore creates a <strong>.preferences_pb</strong> file in the app’s internal storage. As of now, the data is stored in an unsecured manner. Hence, storing sensitive data with DataStore is not recommended.</p>
<p><img src="https://t3650425.p.clickup-attachments.com/t3650425/e5749daa-5252-4d00-9989-491ea0d63068/image.png" alt /></p>
<p>This can be exposed in the debug APK easily using the Android Studio device explorer. but for signed or released APK we won't be able to see this due to Android security policy and permission.</p>
<p>Only root devices can expose the signed or released APK, so If we are able to achieve 100% root detection It will be resolved or else we can encryption and decryption for dataStore values.</p>
<p>Check out the official documentation to encrypt and decrypt the shared preference or Datastore.<br /><a target="_blank" href="https://developer.android.com/topic/security/data">https://developer.android.com/topic/security/data</a></p>
<hr />
<p>If you have any questions, comments, or suggestions, please don't hesitate to reach out. Your feedback is invaluable as I continue to explore and share information on topics that matter.</p>
<p><strong>Please subscribe to my blog for more Android development tips and tricks.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Automate Android Development Workflow with GitHub Actions]]></title><description><![CDATA[Did you know that GitHub Actions is a powerful platform that enables you to automate your software development workflows directly in your repository? With this continuous integration and continuous delivery (CI/CD) tool, you can create, share, and di...]]></description><link>https://blog.ashutoshwahane.dev/automate-android-development-workflow-with-github-actions</link><guid isPermaLink="true">https://blog.ashutoshwahane.dev/automate-android-development-workflow-with-github-actions</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Ashutosh Wahane]]></dc:creator><pubDate>Sun, 24 Sep 2023 07:28:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695469065476/e513a557-82fe-4d37-ab13-835f52a41ffe.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Did you know that GitHub Actions is a powerful platform that enables you to automate your software development workflows directly in your repository? With this continuous integration and continuous delivery (CI/CD) tool, you can create, share, and discover actions to perform any task you need, from CI/CD to customized workflows.</p>
<p>The possibilities of GitHub Actions are vast, including building and testing your code, deploying it to production, releasing new versions of your software, managing your infrastructure, and even sending notifications and reports. Plus, it's entirely free for public and open use.</p>
<h3 id="heading-what-is-cicd">What is CICD?</h3>
<p>CI stands for continuous integration, which is an automated process that builds, tests, and integrates code changes. This helps teams identify and fix bugs early on, improve software quality, and release software more quickly and reliably.</p>
<p>CD stands for continuous deployment, which is a delivery process that automatically deploys code changes that pass automated tests to production. This means we are not required to publish the app manually on Play Store and Firebase distribution.</p>
<p><strong>When used together, these processes are called CICD, and there are numerous open-source CICD tools available in the market</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695469982522/9b7987cd-de18-4514-9584-545ec69be607.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-lets-continue-with-github-actions">Let's continue with GitHub Actions!</h3>
<p>GitHub Actions is a powerful tool that can help improve the quality and efficiency of your software development process. It is also user-friendly and easy to get started with, even if you're new to CICD.</p>
<p>Configure the repository with GitHub actions</p>
<ul>
<li><p>Create a GitHub repository for your Android project, if you don't already have one.</p>
</li>
<li><p>Create a <code>.github</code> folder in the root directory of your repository.</p>
</li>
<li><p>Inside the <code>.github</code> folder, create a <code>workflows</code> folder.</p>
</li>
<li><p>Inside the <code>workflows</code> folder, create a new file with the <code>.yml</code> extension. For example, you could name it <code>main.yml</code>.</p>
</li>
<li><p>In the <code>.yml</code> file, define your workflow steps</p>
</li>
</ul>
<p>Bonus Tip 🤩: You can try the suggested workflow option and this will create a basic workflow to help you get started with Actions</p>
<p>Let's create and run the basic workflow just to understand the actions</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695471527780/e661ded0-2c92-410c-8d30-7a8e4ad16ef6.png" alt class="image--center mx-auto" /></p>
<p>This workflow will run on every push to the <code>main</code> branch of your repository. It will first check out the code, and print the <strong>Hello, world!</strong> string</p>
<p>You can customize the workflow steps to meet your specific needs. For example, you could add steps to sign the APK, deploy the app to a test environment, or send notifications to your team members.</p>
<p>Once you have created the workflow file, push it to your repository. GitHub Actions will automatically start running the workflow for you.</p>
<p><a target="_blank" href="https://docs.github.com/en/actions/using-workflows/about-workflows#understanding-the-workflow-file">Checkout the official documentation to understand the workflow file and syntax</a></p>
<h2 id="heading-lets-automate-some-android-development-stuff">Let's automate some Android development stuff</h2>
<h3 id="heading-improve-your-code-with-lint-checks"><strong>Improve your code with lint checks</strong></h3>
<p>The lint tool helps find poorly structured code that can impact the reliability and efficiency of your Android apps and make your code harder to maintain. It is strongly recommended that you correct any errors that lint detects before publishing your app.  Lint can help you clean up these issues.</p>
<p>YAML code to run the lint job</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">CI</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
  <span class="hljs-attr">pull_request:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
  <span class="hljs-attr">workflow_dispatch:</span>
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">lint:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">the</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Java</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v2</span>
        <span class="hljs-attr">with:</span>
              <span class="hljs-attr">distribution:</span> <span class="hljs-string">"temurin"</span>
              <span class="hljs-attr">java-version:</span> <span class="hljs-number">17</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Lint</span> <span class="hljs-string">Test</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">./gradlew</span> <span class="hljs-string">lintDebug</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">html</span> <span class="hljs-string">test</span> <span class="hljs-string">report</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">name:</span> <span class="hljs-string">lint.html</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">app/build/reports/lint-results-debug.html</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695496598617/e0be4c19-2a6b-4afd-a4d7-5448f851fdc4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695496931545/c63409f0-c702-4e7f-bb55-f780d9edf875.png" alt class="image--center mx-auto" /></p>
<p><strong>When we push or merge pull requests to the dev branch. GitHub actions automatically run the workflow.</strong></p>
<hr />
<h3 id="heading-build-apk-and-upload-to-artifacts"><strong>Build APK and Upload to Artifacts</strong></h3>
<p>For immediate app testing and debugging, you can build a debug APK. The debug APK is signed with a debug key provided by the SDK tools.</p>
<p>To build a debug APK, using the command line <code>./gradlew assembleDebug</code> task:</p>
<p>YAML code to build the APK and upload it to Artifacts</p>
<pre><code class="lang-yaml">  <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">APK</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">Build-APK:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">Running</span> <span class="hljs-string">on</span> <span class="hljs-string">latest</span> <span class="hljs-string">ubuntu</span> <span class="hljs-string">machine</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
 <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">the</span> <span class="hljs-string">latest</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Java</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">distribution:</span> <span class="hljs-string">"temurin"</span>
          <span class="hljs-attr">java-version:</span> <span class="hljs-number">17</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">API_KEY</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">API_KEY:</span> <span class="hljs-string">${{secrets.API_KEY}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">API_KEY=\"$API_KEY\"</span> <span class="hljs-string">&gt;</span> <span class="hljs-string">local.properties</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Grant</span> <span class="hljs-string">Permission</span> <span class="hljs-string">to</span> <span class="hljs-string">Execute</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">chmod</span> <span class="hljs-string">+x</span> <span class="hljs-string">gradlew</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">debug</span> <span class="hljs-string">APK</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">bash</span> <span class="hljs-string">./gradlew</span> <span class="hljs-string">assembleDebug</span> <span class="hljs-string">--stacktrace</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">APK</span> <span class="hljs-string">to</span> <span class="hljs-string">Github</span> <span class="hljs-string">Artifacts</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">name:</span> <span class="hljs-string">app</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">presentation/build/outputs/apk/debug/presentation-debug.apk</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695534369025/75d2f8f1-ad46-461a-8939-20a09c754945.png" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-local-unit-test"><strong>Local Unit Test</strong></h3>
<p>A <em>local</em> test runs directly on your workstation, rather than an Android device or emulator. It uses your local Java Virtual Machine (JVM), rather than an Android device, to run tests. Local tests enable you to evaluate your app's logic more quickly</p>
<p>A <em>unit</em> test verifies the behaviour of a small section of code, the <em>unit under test</em>. It does so by executing that code and checking the result.</p>
<p>YAML code to run the local unit test case</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Unit</span> <span class="hljs-string">Test</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">Build-APK:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">Running</span> <span class="hljs-string">on</span> <span class="hljs-string">latest</span> <span class="hljs-string">ubuntu</span> <span class="hljs-string">machine</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">the</span> <span class="hljs-string">latest</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Java</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">distribution:</span> <span class="hljs-string">"temurin"</span>
          <span class="hljs-attr">java-version:</span> <span class="hljs-number">17</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">API_KEY</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">API_KEY:</span> <span class="hljs-string">${{secrets.API_KEY}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">API_KEY=\"$API_KEY\"</span> <span class="hljs-string">&gt;</span> <span class="hljs-string">local.properties</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Grant</span> <span class="hljs-string">Permission</span> <span class="hljs-string">to</span> <span class="hljs-string">Execute</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">chmod</span> <span class="hljs-string">+x</span> <span class="hljs-string">gradlew</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">unit</span> <span class="hljs-string">test</span> <span class="hljs-string">case</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">./gradlew</span> <span class="hljs-string">:domain:testDebugUnitTest</span> <span class="hljs-string">--tests</span> <span class="hljs-string">"dev.ashutoshwahane.domain.usecase.GetApodImageUseCaseTest"</span>
</code></pre>
<hr />
<h3 id="heading-code-static-analysis-using-mobsf">Code static analysis using MobSF</h3>
<p>mobsfscan is a static analysis tool that can find insecure code patterns in your Android and iOS source code. Supports Java, Kotlin, Swift, and Objective C Code. mobsfscan uses MobSF static analysis rules and is powered by semgrep and libsast pattern matcher.</p>
<p>YAML code to run code static analysis</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Mobsfscan</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
  <span class="hljs-attr">pull_request:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">"dev"</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">mobsfscan:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">mobsfscan</span> <span class="hljs-string">code</span> <span class="hljs-string">scanning</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">the</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Java</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-java@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">distribution:</span> <span class="hljs-string">"temurin"</span>
          <span class="hljs-attr">java-version:</span> <span class="hljs-number">17</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">API_KEY</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">API_KEY:</span> <span class="hljs-string">${{secrets.API_KEY}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">API_KEY=\"$API_KEY\"</span> <span class="hljs-string">&gt;</span> <span class="hljs-string">local.properties</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mobsfscan</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">MobSF/mobsfscan@main</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">args:</span> <span class="hljs-string">'. --sarif --output results.sarif || true'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">mobsfscan</span> <span class="hljs-string">report</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">github/codeql-action/upload-sarif@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">sarif_file:</span> <span class="hljs-string">results.sarif</span>
</code></pre>
<p><a target="_blank" href="https://github.com/MobSF/mobsfscan">For more details please check the official documentation</a></p>
<hr />
<p><a target="_blank" href="https://github.com/Ashutoshwahane/Cosmos-Compose">Get the Source Code from here!</a><br /><strong>Let me know in the comment section if you would like to know about publishing an app on the Play Store using GitHub actions ( CICD)</strong></p>
<p>If you have any questions, comments, or suggestions, please don't hesitate to reach out. Your feedback is invaluable as I continue to explore and share information on topics that matter.</p>
<p><strong>Please subscribe to my blog for more Android development tips and tricks.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Simplified Your Android Workflow]]></title><description><![CDATA[Why do we use Flavours | Android build variants?
Android build variants are a useful tool for developers who want to create multiple versions of their app from a single codebase. This can be helpful for various reasons, such as:

Making separate app ...]]></description><link>https://blog.ashutoshwahane.dev/simplified-your-android-workflow</link><guid isPermaLink="true">https://blog.ashutoshwahane.dev/simplified-your-android-workflow</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[#androiddevelopment #android #androiddeveloper #androidstudio #androiddev #androidapp #appdevelopment #androidapps #coding #kotlin #programming #iosdevelopment #programmer #webdevelopment #java #appdeveloper #mobileappdevelopment #androidgames #developer #androidonly #javaprogramming #mobiledevelopment #ios #androiddevelopers #daysofcode #androidography #flutter #iosdeveloper #softwaredeveloper #codinglife]]></category><category><![CDATA[Environment variables]]></category><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Ashutosh Wahane]]></dc:creator><pubDate>Sun, 27 Aug 2023 18:30:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1693196958423/e1f36f9c-0ef2-40ca-9b6e-c30e17f12fc6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-why-do-we-use-flavours-or-android-build-variants">Why do we use Flavours | Android build variants?</h3>
<p>Android build variants are a useful tool for developers who want to create multiple versions of their app from a single codebase. This can be helpful for various reasons, such as:</p>
<ul>
<li><p>Making separate app versions for different groups of users (e.g. free or paid)</p>
</li>
<li><p>Developing different app versions for different stages (e.g. testing or final release)</p>
</li>
</ul>
<p>One of the most common use cases for Android build variants is to build different versions of an app for different environments. For example, you can create a development version of your app with debug symbols enabled, making it easier to debug. Alternatively, you can create a production version of your app with debug symbols disabled for security reasons.</p>
<p>Finally, Android build variants can be utilized to test different features or configurations of the app. For instance, you can create a build variant that incorporates a new feature that is still undergoing testing and then deploy that build variant to a small group of users to receive feedback.</p>
<p>Different Use Cases for Android Build Flavors: A Quick Summary</p>
<ul>
<li><p>Free vs Paid</p>
</li>
<li><p>Different language builds</p>
</li>
<li><p>Development vs Production</p>
</li>
<li><p>Different screen sizes and resolutions</p>
</li>
<li><p>Different features and configurations</p>
</li>
</ul>
<p>Enough Theory Let's start with a Practical Example (the given example is for the build.gradle.kts which is recommended by google)</p>
<ol>
<li><p>Open the build.gradle file app level in your Android project.</p>
</li>
<li><p>In the <code>buildTypes</code> block, define two build types:<code>release</code> and <code>debug</code>.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693158616063/a491c07c-37ae-45ff-b45d-cca9d263ce61.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>For the <code>release</code> build type, set the following properties:</p>
<ul>
<li><p><code>debuggable</code> to <code>false</code>. This prevents you from debugging your app in Android Studio.</p>
</li>
<li><p><code>minifyEnabled</code> to <code>true</code>. This means that your app will be minified, which makes it smaller and faster.</p>
</li>
<li><p><code>proguardFiles</code> to an array of ProGuard files. These files will be used to obfuscate your app and remove unused code.</p>
</li>
</ul>
</li>
<li><p>For the <code>debug</code> build type, set the following properties:</p>
<ol>
<li><p><code>debuggable</code> to <code>true</code>. This allows you to debug your app in Android Studio.</p>
</li>
<li><p><code>minifyEnabled</code> to <code>false</code>. This means that your app will not be minified, which makes it easier to debug.</p>
</li>
</ol>
</li>
<li><p><strong>Product Flavors:</strong> Product flavors enable you to create different versions of your app for various use cases. For example, you might have flavors for "free" and "premium" versions of your app, each with unique features or branding. Each flavor can have its own resources, assets, and code.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693158978267/01ece80f-56bc-4184-8a07-ad4361cb6534.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<ul>
<li><p>I have created 4 different types of flavor ( for the different use cases )</p>
<ol>
<li><p><code>dev</code>: This is the development build variant, with the application ID <a target="_blank" href="http://com.ashutoshwahane.dev"><code>com.ashutoshwahane.dev</code></a> and the version name suffix <code>_dev</code>. It also defines a constant named <code>TEST_DEV_API</code> that stores the API key for the development environment.</p>
</li>
<li><p><code>production</code>: This is the production build variant, with the application ID <a target="_blank" href="http://com.ashutoshwahane.prod"><code>com.ashutoshwahane.prod</code></a> and the version name suffix <code>_prod</code>. It also defines a constant named <code>TEST_PROD_API</code> that stores the API key for the production environment.</p>
</li>
<li><p><code>free</code>: This is the free build variant, with the application ID <a target="_blank" href="http://com.ashutoshwahane.free"><code>com.ashutoshwahane.free</code></a> and the version name suffix <code>_free</code>.</p>
</li>
<li><p><code>paid</code>: This is the paid build variant, with the application ID <code>com.ashutoshwahane.paid</code> and the version name suffix <code>_paid</code>.</p>
</li>
</ol>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693159260549/729948f8-669a-4046-8095-0bd2208dd102.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>On gradle.properties define your API key or any other config data. ( Bonus TIP: Add gradle.properties file to .gitIgnore to secure your API key )</p>
</li>
<li><p>Once all the steps are done make sure to Re-Build your project.</p>
</li>
<li><p>Now the keys are accessible anywhere in the app for ex:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693159997265/d1dcb3a9-a84c-4692-b67d-bce5a6ea41e4.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p>The code <code>val api = BuildConfig.API_KEY</code> retrieves the API key for the current build variant in Kotlin. The <code>BuildConfig</code> class includes a static field named <code>API_KEY</code> that stores the API key for the current build variant. The <code>val</code>keyword declares a variable called <code>api</code>, which is initialized to the value of the <code>API_KEY</code> field.</p>
<ol>
<li><p>Now open your Build Variants on Android Studio and you will see all the different flavors in release and debug variants.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693160481224/0f08f3a2-10ad-4c2e-a9a0-6880d947a3fc.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>No more changing the config manually just select the build variants and run the app</p>
<p>To learn more about build variants in Android Studio, please visit the official documentation: <a target="_blank" href="https://developer.android.com/studio/build/build-variants">https://developer.android.com/studio/build/build-variants</a></p>
<p><strong>If you have any questions about build variants, please feel free to leave a comment below. I hope this blog post was helpful. Thank you for reading!</strong></p>
<p><strong>Please subscribe to my blog for more Android development tips and tricks.</strong></p>
]]></content:encoded></item></channel></rss>