<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Shibin on Medium]]></title>
        <description><![CDATA[Stories by Shibin on Medium]]></description>
        <link>https://medium.com/@shibin_sv?source=rss-4fbdb34a2c86------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*bEO_AHiwXyqnJCd3</url>
            <title>Stories by Shibin on Medium</title>
            <link>https://medium.com/@shibin_sv?source=rss-4fbdb34a2c86------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 22 May 2026 13:48:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shibin_sv/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[From Zero to Hilt: Clean Dependency Injection in Android Explained]]></title>
            <link>https://medium.com/@shibin_sv/from-zero-to-hilt-clean-dependency-injection-in-android-explained-c9f26c6af3ca?source=rss-4fbdb34a2c86------2</link>
            <guid isPermaLink="false">https://medium.com/p/c9f26c6af3ca</guid>
            <category><![CDATA[dependency-injection]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[hilts]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[android-development]]></category>
            <dc:creator><![CDATA[Shibin]]></dc:creator>
            <pubDate>Sat, 28 Mar 2026 06:17:26 GMT</pubDate>
            <atom:updated>2026-03-28T06:17:26.734Z</atom:updated>
            <content:encoded><![CDATA[<p>If you have ever worked with Android dependencies or passed objects through several layers, you know how messy things can get in a hurry.</p><p>I know from experience. When I first started developing Android apps, I thought it was easy to create objects manually.<br>But as the app grew, so did the mess. I had tight coupling, boilerplate code, and code that was harder to test than to write.</p><p>And then I stumbled upon Hilt. Game. Changer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*obo4F3qL7BzIOZmdqAaTuA.png" /></figure><h3>🧠 What is Hilt?</h3><p><strong>Hilt is a dependency injection library for Android built on top of Dagger.</strong></p><p>It helps you manage how objects are created and shared across your app — without writing a lot of boilerplate code.</p><h3>🤔 Why do we even need Hilt?</h3><p>In a typical Android app, you often:</p><ul><li>Create objects manually (repositories, APIs, databases)</li><li>Pass them through multiple layers</li><li>Handle lifecycle yourself</li></ul><p>As your app grows, this becomes:</p><ul><li>Hard to maintain ❌</li><li>Hard to test ❌</li><li>Easy to break ❌</li></ul><h3>🧩 Simple Analogy</h3><p>Think of Hilt like a <strong>smart delivery system</strong>.</p><p>Instead of building and carrying objects everywhere, you simply:</p><p><em>“Ask for what you need”</em>…and Hilt delivers it at the right time.</p><h3>⚙️ Step 1: Adding Hilt to Your Project</h3><p>In your <strong>project-level </strong><strong>build.gradle</strong>:</p><pre>plugins {<br>    alias(libs.plugins.android.application) apply false<br>    alias(libs.plugins.android.library) apply false<br>    alias(libs.plugins.kotlin.android) apply false<br>    alias(libs.plugins.kotlin.compose) apply false<br>    alias(libs.plugins.hilt) apply false<br>    alias(libs.plugins.ksp) apply false<br>}</pre><p>In your <strong>app-level </strong><strong>build.gradle</strong>:</p><pre>plugins {<br>    alias(libs.plugins.android.application)<br>    alias(libs.plugins.kotlin.compose)<br>    alias(libs.plugins.hilt)<br>    alias(libs.plugins.ksp)<br>}<br><br>dependencies {<br>    implementation(libs.hilt.android)<br>    ksp(libs.hilt.compiler)<br>    implementation(libs.androidx.hilt.navigation.compose)<br>}</pre><h3>libs.versions.toml</h3><pre>[versions]<br>hilt = &quot;2.59.2&quot;<br>ksp = &quot;2.0.21-1.0.27&quot;<br><br>[libraries]<br>hilt-android = { module = &quot;com.google.dagger:hilt-android&quot;, version.ref = &quot;hilt&quot; }<br>hilt-compiler = { module = &quot;com.google.dagger:hilt-compiler&quot;, version.ref = &quot;hilt&quot; }<br><br>[plugins]<br>hilt = { id = &quot;com.google.dagger.hilt.android&quot;, version.ref = &quot;hilt&quot; }<br>ksp = { id = &quot;com.google.devtools.ksp&quot;, version.ref = &quot;ksp&quot; }</pre><p>With the setup complete, the next step is to <strong>initialize Hilt in our application class</strong>, which acts as the entry point for dependency injection.</p><h3>🧩 Step 2: Initialize Hilt in Application Class</h3><pre>@HiltAndroidApp<br>class MyApp : Application()</pre><h3>💡 Why this matters</h3><ul><li>Initializes Hilt</li><li>Creates the dependency graph</li><li>Required entry point for injection</li></ul><h3>Don’t forget in AndroidManifest.xml:</h3><pre>&lt;application<br>    android:name=&quot;.MyApp&quot;<br>    ... &gt;<br>&lt;/application&gt;</pre><h3>🚪 Step 3: Enable Injection in Android Components</h3><p><em>Now that Hilt is set up, we need to tell it </em><strong><em>where</em></strong><em> dependencies can be injected — like Activities, Fragments, etc.</em></p><h3>📍 Add @AndroidEntryPoint to Your Activity</h3><pre>@AndroidEntryPoint<br>class MainActivity : AppCompatActivity() {<br>    // We’ll inject dependencies here next 👀<br>}</pre><h3>💡 What this does</h3><ul><li>Enables dependency injection in Android components</li><li>Connects Activity to Hilt</li></ul><h3>🧪 Step 4: Create Your First Dependency</h3><pre>class UserRepository @Inject constructor() {<br>fun getUserName(): String {<br> return &quot;Jane Doe&quot;<br> }<br>}</pre><h3>💡 What’s happening here?</h3><blockquote><em>The </em><em>@Inject annotation tells Hilt: “Hey, you can create an instance of this class whenever it’s needed.”</em></blockquote><ul><li>Hilt now knows <strong>how to construct </strong><strong>UserRepository</strong></li><li>No need to manually create it using UserRepository()</li><li>This works as long as all dependencies inside it are also known to Hilt</li></ul><h3>💉 Step 5: Injecting the Dependency</h3><pre>@AndroidEntryPoint<br>class MainActivity : AppCompatActivity() {<br><br>    @Inject lateinit var userRepository: UserRepository<br><br>    override fun onCreate(savedInstanceState: Bundle?) {<br>        super.onCreate(savedInstanceState)<br><br>        println(userRepository.getUserName())<br>    }<br>}</pre><h3>💡 What’s happening here?</h3><blockquote><em>The </em><em>@Inject keyword tells Hilt: “Give me an instance of </em><em>UserRepository here.”</em></blockquote><ul><li>No manual creation (UserRepository()) needed</li><li>Hilt automatically provides the instance</li></ul><h3>🧠 Step 6: Using Hilt with ViewModel</h3><blockquote><em>In real-world Android apps, most of your logic lives inside ViewModels.<br> So let’s see how Hilt helps inject dependencies there cleanly.</em></blockquote><pre>@HiltViewModel<br>class MainViewModel @Inject constructor(<br>    private val userRepository: UserRepository<br>) : ViewModel() {<br><br>    fun getUserName(): String {<br>        return userRepository.getUserName()<br>    }<br>}</pre><pre>private val viewModel: MainViewModel by viewModels()</pre><p>👉 No factory, no boilerplate — just clean injection.</p><h3>🧩 Step 7: Using Modules (@Module, @Provides)</h3><p>Use this when Hilt <strong>cannot create objects automatically</strong>.</p><pre>@Module<br>@InstallIn(SingletonComponent::class)<br>object AppModule {<br><br>    @Provides<br>    fun provideUserRepository(): UserRepository {<br>        return UserRepository()<br>    }<br>}</pre><h4>🧠 When to use Modules?</h4><ul><li>Retrofit</li><li>Room Database</li><li>Third-party libraries</li></ul><p>🔁 Real-world example (Retrofit style)</p><pre>@Provides<br>fun provideApiService(): ApiService {<br>    return Retrofit.Builder()<br>        .baseUrl(&quot;https://example.com&quot;)<br>        .build()<br>        .create(ApiService::class.java)<br>}</pre><h3>🚀 Final Thoughts</h3><p>With Hilt in place, you’ve taken a big step toward building a clean and scalable Android architecture.</p><p>No more:</p><ul><li>Manual object creation</li><li>Passing dependencies everywhere</li><li>Confusing initialization logic</li></ul><blockquote><em>Hilt quietly handles all of it — so you can focus on building features, not wiring objects.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c9f26c6af3ca" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From $2 to Millions: Building an Android Explain App with DeepSeek API]]></title>
            <link>https://medium.com/@shibin_sv/from-2-to-millions-building-an-android-explain-app-with-deepseek-api-9d7e223cc831?source=rss-4fbdb34a2c86------2</link>
            <guid isPermaLink="false">https://medium.com/p/9d7e223cc831</guid>
            <category><![CDATA[deepseek]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-development]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Shibin]]></dc:creator>
            <pubDate>Thu, 12 Mar 2026 14:25:39 GMT</pubDate>
            <atom:updated>2026-03-12T14:25:39.069Z</atom:updated>
            <content:encoded><![CDATA[<p>Every parent knows the moment. You’re cooking dinner, tired from work, when suddenly: <em>“Why is the sky blue?”</em> You take a breath and start explaining. Then: <em>“Who is the PM of India?”</em> Then: <em>“What is gravity?”</em> Then: <em>“How do fish breathe?”</em> The questions never stop — and honestly, that curiosity is beautiful. But here’s the problem: kids don’t just ask once. They ask the exact same questions tomorrow, next week, and next month. I tried using AI apps, but at $0.002 per answer, 50 daily questions would cost me $36/month — for just ONE child. I needed something smarter. So I built my own “Explain Like I’m 10” app using DeepSeek API, and somehow made $2 stretch to millions of explanations. Here’s exactly how.</p><p><strong>So let me start the journey I followed to guide you as well</strong></p><h3>STEP 1: Create Your Account</h3><p>Go to <a href="https://platform.deepseek.com/">platform.deepseek.com</a> and click “Sign Up.” Use your email — takes 30 seconds.</p><p>Bonus: New accounts get 5 million free tokens automatically. Enough for thousands of test calls without spending anything.</p><h3>STEP 2: Get Your API Key</h3><p>Once logged in:</p><ul><li>Click on “API Keys” in the left menu</li><li>Click “Create new API key”</li><li>Give it a name (like “explain-app”)</li><li>Copy the key immediately and save it somewhere safe</li></ul><h3>STEP 3: Created my android application (Basic)</h3><p>I opened Android Studio and created a new project with an Empty Views Activity.</p><p>Using Jetpack Compose I created an sample input view.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/494/1*Yipb9Kg7zvea1Vl-eNnsWw.png" /></figure><h3>STEP 4: Advanced DeepSeek Integration in Android</h3><p>Now for the real magic — connecting our simple app to DeepSeek API. Here’s how I set it up:</p><h3>Adding Dependencies</h3><p>In app/build.gradle.kts:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ebvZpKCcSoWuS2VT5rRPuw.png" /></figure><h3>Building the API Service</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dJWNOnn97vP7irbln5XOng.png" /></figure><h3>Creating the Repository</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*-bh1wxWPd5auJw6lBhks2g.png" /></figure><h3>Connecting to MainActivity</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wyUHKODoVshoJ-F-uAFemg.png" /></figure><h3>API Call Structure</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4P62aMwpNtQC9J2y99ogKQ.png" /></figure><h3>API Key Storage in local.properties</h3><p>In local.properties (root level):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9ACDQ-_IG1snJn9kG8UWAw.png" /></figure><p>Important: Added local.properties to .gitignore so API keys never get committed!</p><h3>Loading API Key in build.gradle.kts</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cet2b16sY7LbYBgKY81kjQ.png" /></figure><h3>Using the Key in Code</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5KmHKc-ab3A0S4gf67BHPw.png" /></figure><h3>ADDITIONAL STEP: Making Your Integration Production-Ready</h3><p><em>Error Handling — Try-catch blocks for network failures and API errors</em></p><p><em>Loading States — Progress indicator while waiting for response</em></p><p><em>Input Validation — Check for empty questions before calling API</em></p><p><em>Timeout Config — 30-second connect/read timeouts in OkHttp</em></p><p><em>API Key Security — Stored in BuildConfig, not hardcoded</em></p><p><em>User Feedback — Toast messages for errors and empty inputs</em></p><p><strong>🔗 SEE IT IN ACTION</strong></p><p>Before I explain why I chose DeepSeek over other models, here&#39;s the working app:<br><br>📱 GitHub Repository<br><a href="https://github.com/shibinsv/Explain_It">https://github.com/yourusername/explain-like-im-10</a><br>(Fully open-source code for you to explore)</p><p><strong>Why Deepseek and not others?</strong></p><p>Before building my “Explain Like I’m 10” app, I compared every major AI model. OpenAI’s GPT-4.1 cost $0.0008 per explanation, Claude was $0.0025, and even Gemini ran $0.0009. But DeepSeek? Just $0.00012 per answer. At first I thought Llama 4 was even cheaper, but it required complicated self-hosting. Then I found the feature that broke the bank — in a good way. DeepSeek offers context caching: send the same system message repeatedly, and they remember it, giving you 90% off on those parts. For an app where every question starts with “Explain like I’m 10,” this meant my $2 would stretch so far it might never run out.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9d7e223cc831" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Supercharge Your Android App with Dialogflow CX: Here’s How]]></title>
            <link>https://medium.com/@shibin_sv/integrating-dialogflow-cx-with-android-93b0b17110af?source=rss-4fbdb34a2c86------2</link>
            <guid isPermaLink="false">https://medium.com/p/93b0b17110af</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[dialogflow]]></category>
            <category><![CDATA[android-development]]></category>
            <dc:creator><![CDATA[Shibin]]></dc:creator>
            <pubDate>Sat, 01 Mar 2025 04:46:11 GMT</pubDate>
            <atom:updated>2026-03-12T13:52:14.465Z</atom:updated>
            <content:encoded><![CDATA[<p>Hello all,<br>This post discusses implementing a Dialogflow CX agent into an Android app in Kotlin.</p><p>I had the thrilling chance to implement my mobile app with the Gemini AI to provide responses from Firebase Firestore data.</p><p>When I embarked on integrating Dialogflow and using its agent’s features, I could find a lot of resources for web applications but hardly any for mobile apps. Therefore, I had to conduct a lot of research and testing to get it done. I’m creating this blog to make it easier for fellow mobile developers.</p><p>First things first, we need to integrate our Firebase database and generate a service.json file for integration. Please follow the steps in this video to obtain the service.json file.<br>Here is the link to the video: <a href="https://www.youtube.com/watch?v=dj9fxiuz4WM"><em>Generate service account key in Google Cloud Platform (GCP)</em></a>.</p><p>While updating roles in that , make sure to add <strong>Dialogflow API Client</strong> and <strong>Service Account User</strong>.</p><p>Next, we need to create a Dialogflow CX agent, as demonstrated in the video, and configure it with the required data. This data will be passed as a file in Datastore to ensure proper communication between the agent and the application. You can follow the step-by-step process in this video: <a href="https://www.youtube.com/watch?v=xdt41_MN4Zg">Datastore Integration — Google Dialogflow CX Generative AI</a>.</p><p>Once these steps are completed, the focus shifts to the application side, where we integrate and configure the necessary components for seamless communication with Dialogflow CX.</p><p><strong>Step 1:</strong> Add the necessary dependencies.</p><pre>implementation(&quot;com.google.cloud:google-cloud-dialogflow-cx:0.28.0&quot;)<br>implementation (&quot;io.grpc:grpc-okhttp:1.54.0&quot;)<br>implementation (&quot;io.grpc:grpc-protobuf:1.54.0&quot;)<br>implementation (&quot;io.grpc:grpc-stub:1.54.0&quot;)<br>implementation (&quot;io.grpc:grpc-netty-shaded:1.54.0&quot;)</pre><p><strong>Step 2:</strong> Add the necessary details from the Dialogflow CX Console to your Constants object.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TtK4ZDnQrCv2BiOaV3DawA.png" /></figure><p><strong>Step 3:</strong> Place the service.json file inside the <strong>assets</strong> folder of your application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LihPK-hHOzk9Gi4EaLYaNw.png" /></figure><p><em>Note:</em> This method is recommended for testing purposes only. For production-level applications, embedding the file directly in the app is not advised due to security concerns.</p><p><strong>Step 4:</strong> Copy and implement the following piece of code to integrate Dialogflow into your Android application. This code will establish a connection between your app and the Dialogflow CX agent, enabling seamless interaction and response handling.</p><pre>fun getMessage(context: Context, prompt: String): String {<br>    return try {<br>        // Retrieve Google authentication credentials from the service.json file<br>        val inputStream = context.assets.open(&quot;service.json&quot;)<br>        val credentials = GoogleCredentials.fromStream(inputStream)<br><br>        // Configure Dialogflow CX session settings with authentication credentials<br>        val settings = SessionsSettings.newBuilder()<br>            .setCredentialsProvider(FixedCredentialsProvider.create(credentials))<br>            .build()<br><br>        // Create a SessionsClient instance to communicate with Dialogflow CX<br>        val sessionsClient = SessionsClient.create(settings)<br><br>        // Generate a unique session ID for this conversation<br>        val sessionId = UUID.randomUUID().toString()<br><br>        // Define the session name using project-specific constants<br>        val session = SessionName.of(<br>            Constants.PROJECT_ID,  // Google Cloud project ID<br>            Constants.LOCATION,    // Region where the Dialogflow agent is deployed<br>            Constants.AGENT_ID,    // Unique ID of the Dialogflow CX agent<br>            sessionId              // Unique session ID for conversation tracking<br>        )<br><br>        // Prepare the user input text<br>        val textInput = TextInput.newBuilder().setText(prompt).build()<br><br>        // Construct a query input object with the user text and language code<br>        val queryInput = QueryInput.newBuilder()<br>            .setText(textInput)<br>            .setLanguageCode(&quot;EN&quot;)  // Set language to English<br>            .build()<br><br>        // Create a request to send the user query to Dialogflow CX<br>        val detectIntentRequest = DetectIntentRequest.newBuilder()<br>            .setSession(session.toString())  // Attach the session to maintain context<br>            .setQueryInput(queryInput)       // Include the user&#39;s query<br>            .build()<br><br>        // Send the request and receive a response from Dialogflow CX<br>        val response = sessionsClient.detectIntent(detectIntentRequest)<br><br>        // Close the SessionsClient to free up resources<br>        sessionsClient.close()<br><br>        // Extract the first text response from the Dialogflow agent&#39;s response messages<br>        val responseText = response.queryResult.responseMessagesList.first().text.getText(0)<br><br>        // Return the agent&#39;s response as a string<br>        responseText<br>    } catch (e: Exception) {<br>        // Handle any exceptions and print the error message<br>        println(e.message)<br>        &quot;&quot;<br>    }<br>}</pre><p>Applying these steps in the application gives a simple means of getting a response if the given information is accurate.<br>I have left a sample application here in the repository for your reference:<br><a href="https://github.com/shibinsv/Ask-Me">https://github.com/shibinsv/Ask-Me</a>.</p><p>Go ahead and take a look. Happy coding! 😊</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=93b0b17110af" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>