Amol Pawar

Cryptography

What Is Cryptography and How Does It Work? A Beginner’s Explanation

If you’ve ever entered a password, paid online, or chatted on WhatsApp, you’ve already used cryptography — whether you knew it or not.
 It’s the invisible lock protecting your private information from hackers and eavesdroppers.

In this beginner-friendly guide, you’ll learn what cryptography is, how it works, and see a Kotlin example in action.
 No complex math — just a clear explanation you can actually understand.

What Is Cryptography?

Cryptography is the science of securing information so only the intended people can read it.
 Think of it as putting your message in a sealed envelope, but one that only the right person has the key to open.

The term comes from the Greek words:

  • kryptos — hidden
  • graphein — writing

Put together: hidden writing.

Why Is Cryptography Important?

Without cryptography, sending data online would be like shouting your secrets in a crowded room.
 Here’s where it plays a role every day:

  • Online banking: Keeps credit card and transaction data safe.
  • Messaging apps: WhatsApp, Signal, and Telegram use strong end-to-end encryption.
  • Passwords: Stored securely so hackers can’t read them.
  • Data privacy: Protects personal files, medical records, and government documents.

The Core Principles of Cryptography

  1. Confidentiality — Only the intended person can read the message.
  2. Integrity — Ensures the message isn’t altered along the way.
  3. Authentication — Confirms the identity of sender and receiver.
  4. Non-repudiation — Prevents someone from denying they sent a message.

How Does Cryptography Work?

At a basic level, cryptography takes:

  • Plaintext — normal readable data
  • Key — a secret or public piece of information
  • Encryption algorithm — a method to scramble the plaintext

It turns plaintext into ciphertext (scrambled text).
 Only someone with the correct key can reverse the process through decryption.

Two Main Types of Cryptography

1. Symmetric Key Cryptography

  • Same key for encryption and decryption.
  • Faster but needs secure key sharing.
  • Example: AES (Advanced Encryption Standard).

2. Asymmetric Key Cryptography

  • Two keys: public (to encrypt) and private (to decrypt).
  • You can share the public key openly.
  • Example: RSA encryption.

Kotlin Example: Caesar Cipher

Let’s write a simple Caesar Cipher in Kotlin — one of the earliest encryption methods.
 It shifts letters in the alphabet by a fixed number.

Kotlin
fun encrypt(text: String, shift: Int): String {
    val result = StringBuilder()

    for (char in text) {
        if (char.isLetter()) {
            val base = if (char.isUpperCase()) 'A' else 'a'
            val shifted = ((char - base + shift) % 26 + base.code).toChar()
            result.append(shifted)
        } else {
            result.append(char) // Keep spaces and punctuation unchanged
        }
    }
    return result.toString()
}

fun decrypt(text: String, shift: Int): String {
    return encrypt(text, 26 - shift) // Reverse the shift
}

fun main() {
    val message = "Hello World"
    val shiftKey = 3
    val encryptedMessage = encrypt(message, shiftKey)
    val decryptedMessage = decrypt(encryptedMessage, shiftKey)
    println("Original: $message")
    println("Encrypted: $encryptedMessage")
    println("Decrypted: $decryptedMessage")
}

How the Kotlin Code Works

encrypt() function

  • Loops over each character.
  • If it’s a letter, shifts it forward by the shift value.
  • Keeps spaces and punctuation as they are.

decrypt() function

  • Reverses the shift to get back the original message.

Example output:

Kotlin
Original: Hello World
Encrypted: Khoor Zruog
Decrypted: Hello World

Real-Life Uses of Cryptography

  • Secure websites: HTTPS uses cryptography to protect data.
  • Digital signatures: Prove a file or message is genuine.
  • Blockchain: Relies on cryptographic hashing for security.

Conclusion

Cryptography is the backbone of digital security.
 It’s what keeps your passwords, bank details, and personal messages safe in a world where cyber threats are everywhere.
 While the math behind it can get deep, the basic idea is simple: scramble information so only the right person can read it.

Vehicle HAL

What Is Vehicle HAL? How Vehicle HAL Is Changing the Way You Drive

In today’s rapidly evolving automotive world, technology increasingly powers every aspect of your driving experience. One such advancement making a significant impact behind the scenes is Vehicle HAL. You might be wondering, what exactly is Vehicle HAL, and how does it affect the way you drive? Let’s break it down clearly and simply.

What Is Vehicle HAL? 

Vehicle HAL stands for Vehicle Hardware Abstraction Layer. Think of it as the translator between the car’s hardware (like sensors, cameras, control units) and the software apps that make your driving experience smarter and safer. It sits in the middle, handling the nitty‑gritty so app developers can focus on features — not on hardware quirks.

With Vehicle HAL, your car’s systems talk in a standard language. Whether it’s braking, lane‑keeping, infotainment, or diagnostics, everything works through that common interface. That consistency simplifies development, improves safety, and speeds up innovation.

Why Vehicle HAL Matters

1. One Interface, Many Devices

Vehicle HAL gives developers a single, reliable interface to access diverse hardware. Instead of building custom code for each sensor or device, they write once and it works across models — much faster and safer.

2. Faster Updates, Smarter Features

Need to add voice commands, predictive cruise control, or advanced diagnostics? Vehicle HAL decouples hardware from apps. That means updates come quicker and you get new features without long delays.

3. Safety First

By enforcing consistent behavior across hardware components, Vehicle HAL helps reduce bugs and improves reliability. Consistency boosts safety — especially in critical systems like braking or collision avoidance.

4. Interoperability & Modularity

Automakers and suppliers can plug in different parts — cameras, sensors, processors — from various vendors. As long as they follow Vehicle HAL standards, everything integrates seamlessly. This encourages competition and innovation while keeping quality high.

How Vehicle HAL Works

Let’s look at a basic example in Android’s Vehicle HAL environment to understand how it controls a vehicle’s power state.

Java
// Example: Controlling Vehicle Power State with Vehicle HAL

public class VehiclePowerController {
    private VehicleHal vehicleHal;

    public VehiclePowerController(VehicleHal hal) {
        this.vehicleHal = hal;
    }

    // Method to turn vehicle power on or off
    public void setPowerState(boolean on) {
        try {
            int powerState = on ? VehiclePropertyIds.POWER_STATE_ON : VehiclePropertyIds.POWER_STATE_OFF;
            vehicleHal.setProperty(VehiclePropertyIds.POWER_STATE, powerState);
            System.out.println("Vehicle power turned " + (on ? "ON" : "OFF"));
        } catch (VehicleHalException e) {
            System.err.println("Failed to set power state: " + e.getMessage());
        }
    }
}

Here,

  • VehicleHal is an object representing the hardware abstraction layer interface.
  • The method setPowerState takes a boolean to turn the vehicle power on or off.
  • VehiclePropertyIds.POWER_STATE_ON and POWER_STATE_OFF are constants representing the hardware power states.
  • The setProperty method sends the command down to the hardware, abstracted away from the specific implementation.

This simple code showcases how Vehicle HAL hides the hardware complexities and presents a clean way to control vehicle functions programmatically.

Benefits of Vehicle HAL for Developers and Drivers

  • For developers: Simplifies app development and testing across multiple vehicle platforms.
  • For drivers: You get a smooth, consistent driving experience with new features delivered faster and more safely.
  • For manufacturers: Promotes modular design, reducing costs and accelerating innovation.

The Future of Driving with Vehicle HAL

As connected and autonomous vehicles advance, the role of Vehicle HAL will grow even more crucial. It will support complex sensor networks, cloud integration, AI-driven decisions, and real-time data sharing between vehicles to make driving smarter, safer, and more enjoyable.

Conclusion

In conclusion, Vehicle HAL is revolutionizing the automotive space by breaking down the barriers between hardware and software. It’s making cars more adaptable, feature-rich, and user-friendly, changing the way you interact with your vehicle every day. Whether it’s through better safety, easier updates, or improved performance, Vehicle HAL is quietly refashioning the future of driving, one line of code at a time.

Drive smarter, safer, and connected — thanks to Vehicle HAL.

Fibonacci Sequence in Kotlin Using Recursion

Fibonacci Sequence in Kotlin Using Recursion — From Theory to Code

If you’ve ever been fascinated by numbers that seem to appear everywhere in nature — from the petals of flowers to the spirals in seashells — then you’ve already met the Fibonacci sequence.

In this blog, we’ll explore Fibonacci Sequence in Kotlin Using Recursion step by step. We’ll start with the theory, then move into writing simple yet powerful Kotlin code. Everything will be easy to follow, and beginner-friendly.

Understanding the Fibonacci Sequence

The Fibonacci sequence is a series of numbers where:

Kotlin
F(n) = F(n-1) + F(n-2)

with:

Kotlin
F(0) = 0
F(1) = 1

So, the sequence begins like this:

Kotlin
0, 1, 1, 2, 3, 5, 8, 13, 21, ...

Each term is the sum of the previous two terms. It’s a simple rule with surprisingly deep applications — mathematics, art, computer science, and even stock market analysis.

Why Use Recursion?

Recursion is when a function calls itself to solve smaller parts of a problem.
 In the case of the Fibonacci sequence, recursion works naturally because the definition of Fibonacci is already recursive in nature:

  • To find F(n), you find F(n-1) and F(n-2) and add them.
  • Each of those smaller problems breaks down further until you hit the base case (F(0) or F(1)).

Think of it like climbing stairs:

  • To reach the nth step, you must have come from either step (n-1) or (n-2).
  • You keep breaking it down until you reach the first or second step.

Writing Fibonacci Sequence in Kotlin Using Recursion

Here’s the code:

Kotlin
fun fibonacci(n: Int): Int {
    // Base cases: when n is 0 or 1
    if (n == 0) return 0
    if (n == 1) return 1

// Recursive call
    return fibonacci(n - 1) + fibonacci(n - 2)
}

fun main() {
    val terms = 10

    println("Fibonacci sequence up to $terms terms:")

    for (i in 0 until terms) {
        print("${fibonacci(i)} ")
    }
}

Code Explanation

1. Base Cases

Kotlin
if (n == 0) return 0
if (n == 1) return 1

These are our stopping points. If n is 0 or 1, we simply return the value without further calculations.

2. Recursive Step

Kotlin
return fibonacci(n - 1) + fibonacci(n - 2)

The function calls itself twice:

  • Once for the previous term (n-1)
  • Once for the term before that (n-2)
     It then adds them together to produce the nth term.

3. Main Function

Kotlin
for (i in 0 until terms) {
    print("${fibonacci(i)} ")
}

We loop through and print the first terms Fibonacci numbers, giving us a clean, readable sequence.

A Note on Performance

While Fibonacci Sequence in Kotlin Using Recursion is elegant and easy to understand, pure recursion can be slow for large n because it recalculates the same values multiple times.

Example:

  • fibonacci(5) calls fibonacci(4) and fibonacci(3).
  • But fibonacci(4) again calls fibonacci(3) — we’re repeating work.

Solution: Use memoization or dynamic programming to store results and avoid recalculations. But for learning recursion, the basic approach is perfect.

Real-World Applications

  • Algorithm practice: Great for learning recursion and problem-solving.
  • Mathematical modeling: Growth patterns in populations or financial data.
  • Computer graphics: Spiral designs and procedural patterns.

Key Takeaways

  • The Fibonacci sequence is naturally suited to recursion because of its self-referential definition.
  • Kotlin makes it clean and readable with its concise syntax.
  • For small inputs, recursion works perfectly, but for larger inputs, optimization is needed.

Conclusion

Recursion is like magic — it hides complexity behind a few lines of code. With the Fibonacci Sequence in Kotlin Using Recursion, you get both an elegant algorithm and a deep understanding of how problems can solve themselves step by step.

ONNX Runtime on Android

ONNX Runtime on Android: The Ultimate Guide to Lightning-Fast AI Inference

Artificial intelligence is no longer limited to servers or the cloud. With ONNX Runtime on Android, you can bring high-performance AI inference directly to mobile devices. Whether you’re building smart camera apps, real-time translation tools, or health monitoring software, ONNX Runtime helps you run models fast and efficiently on Android.

In this guide, we’ll break down everything you need to know about ONNX Runtime on Android — what it is, why it matters, and how to get started with practical code examples.

What is ONNX Runtime?

ONNX Runtime is a cross-platform, high-performance engine for running machine learning models in the Open Neural Network Exchange (ONNX) format. It’s optimized for speed and efficiency, supporting models trained in frameworks like PyTorch, TensorFlow, and scikit-learn.

Why Use ONNX Runtime on Android?

  • Speed: Optimized inference using hardware accelerators (like NNAPI).
  • Portability: Train your model once, run it anywhere — desktop, cloud, or mobile.
  • Flexibility: Supports multiple execution providers, including CPU, GPU, and NNAPI.
  • Open Source: ONNX Runtime is backed by Microsoft and a large open-source community.

Setting Up ONNX Runtime on Android

Getting started with ONNX Runtime on Android is simple. Here’s how to set it up step by step.

1. Add ONNX Runtime to Your Android Project

First, update your project’s build.gradle file to include ONNX Runtime dependencies.

Kotlin
dependencies {
    implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.17.0'
}

Replace 1.17.0 with the latest version available on Maven Central.

2. Add the ONNX Model to Assets

Place your .onnx model file in the src/main/assets directory of your Android project. This allows your app to load it at runtime.

3. Android Permissions

No special permissions are required just to run inference with ONNX Runtime on Android, unless your app needs access to the camera, storage, or other hardware.

Loading and Running ONNX Model on Android

Here’s a minimal but complete example of how to load a model and run inference.

Kotlin
import ai.onnxruntime.*

fun runInference(context: Context, inputData: FloatArray): FloatArray {
    val ortEnv = OrtEnvironment.getEnvironment()
    val modelBytes = context.assets.open("model.onnx").readBytes()
    
    val session = ortEnv.createSession(modelBytes)
    val shape = longArrayOf(1, inputData.size.toLong())
    val inputTensor = OnnxTensor.createTensor(ortEnv, inputData, shape)
    
    session.use {
        ortEnv.use {
            inputTensor.use {
                val inputName = session.inputNames.iterator().next()
                val results = session.run(mapOf(inputName to inputTensor))
                val outputTensor = results[0].value as Array<FloatArray>
                return outputTensor[0]
            }
        }
    }
}
  • Create Environment: Initialize ONNX Runtime environment.
  • Load Model: Read the .onnx file from assets.
  • Create Session: Set up an inference session.
  • Prepare Input Tensor: Wrap input data into an ONNX tensor.
  • Run Inference: Call the model with input data and fetch the output.

This is all done locally on the device — no internet connection required.

Optimizing Performance with NNAPI

ONNX Runtime on Android supports Android’s Neural Networks API (NNAPI), which can accelerate inference using hardware like DSPs, GPUs, or NPUs.

To enable NNAPI:

Kotlin
val sessionOptions = OrtSession.SessionOptions()
sessionOptions.addNnapi()
val session = ortEnv.createSession(modelBytes, sessionOptions)

This simple addition can significantly reduce inference time, especially on modern Android devices with dedicated AI hardware.

Best Practices for ONNX Runtime on Android

  • Quantize Models: Use quantization (e.g., int8) to reduce model size and improve speed.
  • Use Async Threads: Run inference off the main thread to keep your UI responsive.
  • Profile Performance: Measure inference time using SystemClock.elapsedRealtime().
  • Update Regularly: Keep ONNX Runtime updated for the latest performance improvements.

Common Use Cases

Here are some practical examples of where ONNX Runtime on Android shines:

  • Real-Time Object Detection: Fast image recognition in camera apps.
  • Voice Commands: Low-latency speech recognition on-device.
  • Health Monitoring: Analyze sensor data in real-time.
  • Smart Assistants: Natural language processing without cloud dependency.

Conclusion

ONNX Runtime on Android offers developers a straightforward way to integrate AI inference into mobile apps without sacrificing speed or battery life. With cross-platform compatibility, hardware acceleration, and a simple API, it’s a top choice for running machine learning models on Android.

If you’re serious about building AI-powered apps, ONNX Runtime on Android is your best bet for fast, efficient, and reliable inference.

NNAPI

Neural Networks API (NNAPI) Explained: The Ultimate 2025 Guide to Android’s AI Acceleration

Artificial intelligence on mobile devices is no longer a futuristic concept — it’s part of our daily tech life. From facial recognition to voice assistants, AI is everywhere. For Android developers, the Neural Networks API (NNAPI) is the key to unlocking efficient on-device AI. In this guide, you’ll learn everything about NNAPI, why it matters, how it...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
ONNX Runtime

What Is ONNX Runtime? A Beginner’s Guide to Faster AI Model Inference

If you’ve ever worked with AI models, you know how exciting it is to see them in action. But here’s the catch — many models are slow to run, especially in production environments. That’s where ONNX Runtime comes in. It’s a game-changer for speeding up model inference without changing the model itself.

In this guide, you’ll learn exactly what ONNX Runtime is, why it’s useful, and how you can use it to run your AI models faster. Whether you’re a beginner in AI or an experienced developer looking for performance boosts, this post will break it down simply and clearly.

What Is ONNX Runtime (ORT)?

ONNX Runtime is an open-source, high-performance engine for running machine learning models. Developed by Microsoft, it supports models trained in popular frameworks like PyTorch, TensorFlow, and scikit-learn by converting them to the ONNX (Open Neural Network Exchange) format.

Think of ONNX Runtime as a universal language interpreter for AI models. You train your model in any framework, convert it to ONNX, and then ONNX Runtime takes care of running it efficiently across various hardware (CPU, GPU, even specialized accelerators).

Why Use ONNX Runtime?

Speed

ONNX Runtime is optimized for speed. It reduces inference time dramatically compared to native frameworks.

Cross-Platform

It runs on Windows, Linux, macOS, Android, and iOS. You can use it in cloud services, edge devices, or even mobile apps.

Flexibility

Supports models from PyTorch, TensorFlow, scikit-learn, XGBoost, and more — once converted to ONNX.

Cost-Efficient

Faster inference means fewer resources and lower cloud costs. Who doesn’t like saving money..?

How Does ONNX Runtime Work?

Here’s the simple flow:

  1. Train your model using TensorFlow, PyTorch, or another framework.
  2. Export the model to ONNX format.
  3. Use ONNX Runtime to run inference — faster and more efficiently.

Running a Model with ONNX Runtime

Let’s see a basic Python example to understand how to use ONNX Runtime.

Install ONNX Runtime

Python
pip install onnxruntime

This command installs the CPU version. If you have a GPU, you can install the GPU version like this:

Python
pip install onnxruntime-gpu

Load an ONNX Model

Let’s say you have a model called model.onnx.

Python
import onnxruntime as ort

# Create an inference session
session = ort.InferenceSession("model.onnx")

Prepare Input

You need to know the input names and shapes.

Python
import numpy as np

# Get input name
input_name = session.get_inputs()[0].name

# Create dummy input
input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)

Run Inference

Python
# Run inference
outputs = session.run(None, {input_name: input_data})

print("Model Output:", outputs[0])

That’s it! You just ran an AI model using ONNX Runtime in a few lines of code.

How to Convert Models to ONNX Format

Python
import torch

# Example PyTorch model
model = torch.hub.load('pytorch/vision', 'resnet18', pretrained=True)
model.eval()

# Dummy input
dummy_input = torch.randn(1, 3, 224, 224)

# Export to ONNX
torch.onnx.export(model, dummy_input, "resnet18.onnx")

Now you can use resnet18.onnx with ONNX Runtime for fast inference.

When Should You Use ONNX Runtime?

Use CaseONNX Runtime Benefit
Production deploymentFaster inference and hardware flexibility
Edge devices (IoT)Smaller footprint and speed
Cloud servicesReduced inference costs
Multi-framework pipelinesEasier model standardization

If you need consistent, fast model inference across different environments, ONNX Runtime is a solid choice.

ONNX Runtime vs Native Frameworks

FeaturePyTorch/TensorFlowONNX Runtime
Inference SpeedGoodFaster, optimized kernels
Deployment FlexibilityLimitedMulti-platform, hardware-optimized
Framework Lock-inYesNo, cross-framework support
Learning CurveFramework-specificSimple API, easy to adopt

Tips for Maximizing ONNX Runtime Performance

  • Use ONNX Optimizer: Tools like onnxoptimizer help remove redundant operations.
  • Enable Graph Optimizations: ONNX Runtime automatically optimizes computation graphs.
  • Leverage Execution Providers: Choose CUDAExecutionProvider for GPU, CPUExecutionProvider for CPU, or others like TensorRT.
  • Batch Inputs: Inference is faster with batched data.

Conclusion

ONNX Runtime is not just a tool — it’s a performance booster for AI inference. It simplifies deployment, cuts inference time, and makes your AI projects more scalable.

If you’ve been struggling with slow model inference or complicated deployments, ONNX Runtime is your friend. Install it, give it a try, and see the speed-up for yourself.

FAQs

Q: Is ONNX Runtime free?
 Yes, it’s completely open-source and free to use under the MIT license.

Q: Can I use ONNX Runtime with GPU?
 Absolutely. Just install onnxruntime-gpu and you’re good to go.

Q: Does ONNX Runtime support quantized models?
 Yes! It supports quantization for even faster and smaller models.

Model Inference in AI

Model Inference in AI Explained Simply: How Your AI Models Make Real-World Predictions

Artificial Intelligence (AI) seems like magic — type a prompt and it answers, upload a picture and it identifies objects, or speak to your phone and it replies smartly. But what happens behind the scenes when an AI makes these decisions? The answer lies in a crucial process called model inference in AI.

In this guide, we’ll keep things simple and walk through a few easy coding examples. Whether you’re new to AI or just curious about how it works, you’ll come away with a clear understanding of how AI models make real-world predictions.

What is Model Inference in AI?

Think of AI as a student who spends months studying (training) and finally takes a test (inference). Model inference in AI refers to the phase where a trained model uses its knowledge to make predictions or decisions on new data it hasn’t seen before.

  • Training = Learning phase
  • Inference = Prediction phase (real-world usage)

When you ask a chatbot a question or upload an image to an app, the model is performing inference — it’s not learning at that moment but applying what it has already learned.

Real-Life Examples of Model Inference

  • Typing on your phone and seeing autocomplete suggestions? Model inference.
  • Netflix recommending a movie? Model inference.
  • AI detecting tumors in medical images? Model inference.

It’s the AI’s way of taking what it learned and helping you in the real world.

Why is Model Inference Important?

Without inference, AI would be useless after training. The whole point of AI is to make smart decisions quickly and reliably on new data.

Here’s why model inference in AI matters:

  • Speed: Fast inference means smooth user experiences (think instant translations or responses).
  • Efficiency: Good inference balances accuracy with hardware constraints (e.g., smartphones vs servers).
  • Real-World Application: From healthcare diagnoses to personalized recommendations, inference powers the AI tools we use daily.

Model Inference vs Model Training

How Model Inference in AI Works 

Let’s walk through a typical inference workflow in simple terms.

1. Input Data

This is the real-world information the AI needs to process:

  • Text prompt (chatbots)
  • Image (object detection)
  • Voice (speech recognition)

2. Preprocessing

Before sending the input to the model, it’s cleaned and formatted:

  • Text is tokenized (split into words or subwords).
  • Images are resized or normalized.
  • Audio is converted into frequency data.

3. Model Prediction (Inference)

The preprocessed data enters the trained model:

  • The model applies mathematical operations (like matrix multiplications).
  • It calculates probabilities or outputs based on its training.

4. Postprocessing

The raw model output is converted into human-friendly results:

  • Probabilities are converted to labels (“cat” or “dog”).
  • Text tokens are transformed back into readable sentences.

5. Output

Finally, the AI gives you the result: a prediction, an answer, or an action.

Image Classification Inference

Let’s see a practical example using Python and a pretrained model from PyTorch.

Python
import torch
from torchvision import models, transforms
from PIL import Image

# Load a pretrained model (ResNet18)
model = models.resnet18(pretrained=True)
model.eval()  # Set model to inference mode
# Preprocessing steps
preprocess = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225]),
])
# Load and preprocess the image
image = Image.open("cat.jpg")
input_tensor = preprocess(image)
input_batch = input_tensor.unsqueeze(0)  # Add batch dimension
# Model Inference
with torch.no_grad():
    output = model(input_batch)
# Get the predicted class
_, predicted_class = torch.max(output, 1)
print(f"Predicted class index: {predicted_class.item()}")

Here,

  • model.eval() puts the model in inference mode.
  • Preprocessing ensures the image matches the model’s expected input format.
  • torch.no_grad() disables gradient calculations (saves memory).
  • The model predicts the class index of the image — this could be mapped to actual class names using imagenet_classes.

Let’s see one more working example using TensorFlow and a pre-trained model.

Python
import tensorflow as tf
import numpy as np
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image

# Load a pre-trained model
model = MobileNetV2(weights='imagenet')

# Load and preprocess image
img_path = 'dog.jpg'  # path to your image
img = image.load_img(img_path, target_size=(224, 224))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array = preprocess_input(img_array)

# Perform inference
predictions = model.predict(img_array)

# Decode predictions
decoded = decode_predictions(predictions, top=1)[0]
print(f"Predicted: {decoded[0][1]} with confidence {decoded[0][2]:.2f}")

Here,

  • We load MobileNetV2, a pre-trained model.
  • We preprocess the image to fit model input size.
  • model.predict() runs model inference.
  • The result is a human-readable prediction.

So, basically,

  • ResNet-18 is for general-purpose use where computational resources are available — great for accuracy without worrying too much about speed.
  • MobileNetV2 is designed for efficiency, trading off a bit of accuracy for speed and low resource use, especially on mobile or embedded devices.

If you need speed and small model size, go for MobileNetV2.
If you need accuracy and don’t care about size/speed, ResNet-18 is a solid choice.

Optimizing Model Inference in AI

In real-world applications, inference needs to be fast, efficient, and accurate. Here are some common optimization techniques:

  • Quantization: Reduce model size by using lower precision (e.g., float32 → int8).
  • Model Pruning: Remove unnecessary neurons or layers.
  • Hardware Acceleration: Use GPUs, TPUs, or specialized chips.
  • Batching: Process multiple inputs at once to maximize efficiency.
  • ONNX and TensorRT: Export models to efficient formats for deployment.
  • Edge AI: Run inference directly on mobile/IoT devices.

These techniques allow you to deploy AI on devices ranging from cloud servers to mobile phones.

Inference Deployment: How AI Models Go Live

There are three common ways to deploy model inference in AI:

  1. Cloud Inference: AI models run on powerful servers (e.g., AWS, Azure).
  2. Edge Inference: Models run on devices (phones, cameras).
  3. Hybrid Inference: Combines both to balance speed and accuracy.

Example: Google Lens uses edge inference for instant results, but may use cloud inference for more complex tasks.

Real-Life Examples of Model Inference in AI

Every time you use AI, you’re actually seeing model inference in action..!

Best Practices for Responsible Model Inference

To ensure trustworthy AI, especially in sensitive applications, keep these tips in mind:

  • Monitor inference outputs for bias.
  • Ensure privacy during inference (especially for personal data).
  • Test models in diverse scenarios before deployment.
  • Optimize for both performance and fairness.

FAQs on Model Inference in AI

Is inference always faster than training?

 Yes! Inference happens in real-time, while training can take days.

Can inference happen offline?

 Yes. With edge inference, AI runs without internet access.

Do I need GPUs for inference?

 Not always. Many models run fine on CPUs, especially after optimization.

Conclusion: Bringing AI to Life

Model inference in AI is where the magic happens — when AI takes all its training and applies it to make real-world decisions. Whether it’s recommending a Netflix show, identifying diseases, or powering chatbots, inference ensures that AI doesn’t just stay in labs but actively helps people.

Quick Recap,

  • Model inference = real-time predictions using trained AI models.
  • Involves preprocessing, prediction, and postprocessing.
  • Optimizations make inference faster and efficient.
  • Responsible inference means ethical, fair, and private AI.

By understanding inference, you gain a deeper appreciation of how AI works, and you’re better equipped to build or use AI responsibly.

Android BOM

What Is Android BOM? A Beginner’s Guide to Simplifying Dependencies in 2025

Managing dependencies in Android development can feel like juggling flaming torches—one wrong move, and your build breaks. If you’re tired of mismatched library versions, build errors, and long Gradle files, Android BOM might be the solution you didn’t know you needed.

In this guide, we’ll break down what Android BOM is, why it matters in 2025, and how you can start using it to clean up your project and avoid versioning headaches.

What Is Android BOM?

BOM stands for Bill of Materials. It’s a feature in Gradle (and supported by Maven too) that lets you manage versions of multiple libraries from a single source.

In the Android world, an Android BOM is typically published by a library maintainer (like Google for Jetpack Compose or Firebase) and defines the versioning for all related artifacts under the hood.

Instead of specifying a version number for each dependency manually, you just import the BOM, and it ensures all components stay in sync.

Why Use Android BOM in 2025?

In 2025, modern Android apps rely on a stack of complex, interconnected libraries. Manually managing versions is error-prone and inefficient.

Here’s why Android BOM is a must-have:

Simplifies Dependency Management

No more version conflicts or mismatched components.

Reduces Boilerplate

You can skip version numbers for each Firebase or Jetpack Compose module.

Keeps Everything in Sync

The BOM ensures all included libraries are compatible with each other.

Easier Upgrades

Want to update Firebase? Just bump the BOM version.

How Does It Work?

Here’s what a typical implementation looks like in your build.gradle.kts or build.gradle file:

Without Android BOM (manual versioning):

Kotlin
dependencies {
    implementation("androidx.compose.ui:ui:1.6.1")
    implementation("androidx.compose.material:material:1.6.1")
    implementation("androidx.compose.ui:ui-tooling-preview:1.6.1")
}

Every library needs a version. If you upgrade, you need to change them all manually.

With Android BOM (simplified and synced):

Kotlin
dependencies {
    implementation(platform("androidx.compose:compose-bom:2025.01.00"))
    
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.material:material")
    implementation("androidx.compose.ui:ui-tooling-preview")
}

Only the BOM needs a version. The other libraries inherit it automatically. Clean and safe.

Where Can You Use Android BOM?

Android BOM is commonly used with:

  • Jetpack Compose
  • Firebase (via com.google.firebase:firebase-bom)
  • Ktor (JetBrains’ Kotlin server-client library)
  • Any library group that publishes a BOM

It works in both Gradle Kotlin DSL and Groovy.

Each is maintained by the respective teams and updated regularly.

BOM and Version Catalogs

Gradle’s Version Catalogs work perfectly with BOMs. Define the BOM in your libs.versions.toml file:

TOML
[versions]
compose-bom = "2025.05.00"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
ui = { group = "androidx.compose.ui", name = "ui" }

And in your build.gradle.kts:

Kotlin
implementation (platform(libs.androidx.compose.bom))
implementation (libs.ui)

This keeps your dependency management even more organized.

Best Practices When Using Android BOM

  • Stick to one BOM per group — Don’t mix Firebase and Compose BOMs in a single platform declaration. You can have multiple BOMs, but declare them separately.
  • Keep BOM versions updated — Stay on top of version updates for stability and security.
  • Avoid adding versions to individual artifacts if the BOM already manages them.

What If a Library Doesn’t Support BOM?

Some third-party libraries might not publish a BOM. In that case, you’ll still have to manage versions manually. But you can combine both approaches — use BOM for libraries that support it and pin versions for others.

Overriding BOM Versions

Sometimes, you might need a specific library version that’s newer (or older) than what the BOM provides. You can override it by specifying the version directly:

Kotlin
implementation (platform("androidx.compose:compose-bom:2025.05.00"))
implementation ("androidx.compose.material3:material3:1.2.0-alpha09") // Overrides BOM

Be cautious: overriding can break compatibility guarantees, so only do this if necessary.

Common Questions About Android BOM

Does the BOM automatically add all libraries to my app?

No. You still need to declare each library you want to use. The BOM just manages their versions.

Can I use BOM for alpha or beta releases?

Yes! There are alpha, beta, and stable BOMs available. Just add -alpha or -beta to the BOM artifact name:

Kotlin
implementation (platform("androidx.compose:compose-bom-alpha:2025.05.00"))

Am I forced to use BOM?

No, but it’s highly recommended for easier and safer dependency management.

Does BOM increase build time?

Actually, the opposite. Because it simplifies dependency resolution, it can help Gradle builds run more efficiently.

Conclusion

If you’re building Android apps in 2025, using Android BOM isn’t just a nice-to-have — it’s essential. It streamlines dependency management, prevents version mismatches, and keeps your codebase cleaner and safer.

Whether you’re working on a small app or a complex multi-module project, adopting Android BOM early will save you time and frustration.

What is libs.versions.toml

Mastering libs.versions.toml: Add Plugins, Dependencies & Manage Versions Like a Pro

In modern Android and Kotlin Multiplatform development, managing dependencies across multiple modules can quickly become messy. Manually updating versions in each build.gradle.kts file is not only error-prone—it’s a headache when scaling projects.

That’s where libs.versions.toml steps in—the primary and recommended configuration file for Gradle Version Catalogs, a game-changing feature introduced in Gradle 7.0 and stabilized in 7.4.

In this in-depth guide, you’ll learn how to master libs.versions.toml—from setting it up, organizing your dependencies and plugins, to managing versions like a seasoned pro.

What is libs.versions.toml?

libs.versions.toml is a centralized configuration file introduced in Gradle 7+ that lets you declare and manage dependencies, plugin versions, and bundles in one place.

This improves:

  • Readability of dependency definitions
  • Consistency across modules
  • Maintainability by updating versions in a single file

Enabling Version Catalogs

Before you can use libs.versions.toml, make sure you’re on Gradle 7.0+ and Kotlin DSL (.kts).

In your project’s settings.gradle.kts, enable the version catalog:

Kotlin
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("gradle/libs.versions.toml"))
        }
    }
}

This tells Gradle to look for a libs.versions.toml file inside the gradle/ directory.

Creating libs.versions.toml

Create the file at:

Kotlin
project-root/
├── gradle/
│   └── libs.versions.toml

Let’s break down its structure.

Structure of the File

The file is divided into three main sections:

Kotlin
[versions]
[libraries]
[plugins]
  • [versions]: Define all your version numbers here.
  • [libraries]: List your dependencies, referencing versions from above.
  • [plugins]: List your plugins, referencing versions as well

Defining Versions

Under [versions], you define the reusable version strings.

Kotlin
[versions]
kotlin = "1.9.22"
agp = "8.4.0"
coroutines = "1.7.3"

This creates version aliases. You can later reference these in your dependency and plugin definitions.

Adding Libraries

Under [libraries], you define the actual dependencies:

Kotlin
[libraries]
compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }

Or, use the module shorthand:

Kotlin
[libraries]
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version = "2.9.0" }

Here, you define your dependencies using aliases. Reference the version from the [versions] block to keep things DRY (Don’t Repeat Yourself).

Explanation:

  • module = full Maven coordinate
  • version = direct version
  • version.ref = refers to a shared version from [versions]

This improves consistency and avoids duplication.

Adding Plugins

Under [plugins], plugins are managed just like libraries. Reference the version from [versions] for consistency.

Kotlin
[plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "agp" }

Using the Version Catalog in Your Build Files

Once your libs.versions.toml is set up, you can use its entries in your module-level build.gradle.kts files.

Applying Plugins

Replace hardcoded plugin IDs and versions with aliases:

Kotlin
plugins {
    alias(libs.plugins.kotlin.android)
}

Adding Dependencies

Use the aliases you defined for dependencies:

Kotlin
dependencies {
    implementation(libs.compose.ui)
    implementation(libs.compose.material3)
}

Using Bundles (optional, but highly recommended for grouping related dependencies)

You can group related dependencies into bundles for convenience:

Kotlin
[bundles]
compose = [
    "compose-ui",
    "compose-material3"
]

And use them in your build file:

Kotlin
dependencies {
    implementation(libs.bundles.compose)
}

It reduces boilerplate and enforces consistency.

Pro Tips for libs.versions.toml

1. Use Comments Wisely

Unlike JSON or YAML, .toml supports inline comments:

Kotlin
kotlin = "1.9.22" # Kotlin version used for both plugin and stdlib

Helpful when collaborating or reviewing changes.

2. Semantic Grouping

Group dependencies logically: UI, Networking, Testing, etc.

Kotlin
[libraries]
# UI
compose-ui = { module = "androidx.compose.ui:ui", version = "1.6.2" }
compose-material = { module = "androidx.compose.material:material", version = "1.6.2" }

# Testing
junit = { module = "junit:junit", version = "4.13.2" }

Improves navigation and scalability.

3. Version Locking & Conflict Resolution

If you use a dependency with a transitive mismatch, use constraints in build.gradle.kts:

Kotlin
dependencies {
    implementation(libs.some.lib)
    constraints {
        implementation("some:transitive-lib:1.2.3")
    }
}

This ensures predictable builds.

Real-world Usage Example

libs.versions.toml:

Kotlin
[versions]
kotlin = "1.9.22"
agp = "8.4.0"
coroutines = "1.7.3"
compose = "1.6.2"

[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }

[plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "agp" }

[bundles]
core = ["kotlin-stdlib", "coroutines-core"]

app/build.gradle.kts:

Kotlin
plugins {
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.android.application)
}

dependencies {
    implementation(libs.bundles.core)
    implementation(libs.compose.ui)
}

Simple, elegant, and maintainable.

Why libs.versions.toml Matters

As projects grow, consistency becomes critical. libs.versions.toml:

  • Reduces version mismatches
  • Makes updates seamless
  • Keeps modules DRY (Don’t Repeat Yourself)
  • Is IDE-friendly and fully supported by Android Studio

It’s the kind of practice that scales well in enterprise codebases and simplifies maintenance.

Conclusion

If you’re not using libs.versions.toml, now’s the time to start.

Whether you’re building a small Android app or managing dozens of modules across a large monorepo, version catalogs offer clarity, consistency, and control.

Keep your libs.versions.toml organized, document versions, and treat it like your project’s single source of truth.

Migrate from SharedPreferences to Jetpack DataStore

How to Migrate from SharedPreferences to Jetpack DataStore (Step-by-Step Guide)

If you’re still using SharedPreferences in your Android app, it’s time to level up. Google introduced Jetpack DataStore as the modern solution for storing key-value and typed objects in a more efficient, safe, and asynchronous way.

In this guide, we’ll walk you through how to migrate from SharedPreferences to Jetpack DataStore, step by step, with easy-to-follow code examples and clear explanations.

Let’s future-proof your app’s data storage..!

Why Migrate from SharedPreferences to Jetpack DataStore?

Before we jump into the code, here’s why the switch matters:

  • Asynchronous: DataStore is built on Kotlin Coroutines, meaning no more blocking the main thread.
  • Type safety: With Proto DataStore, you can define your own schema.
  • More robust: Handles data consistency and corruption better.
  • Google-backed: DataStore is the future; SharedPreferences is legacy.

So let’s get into it.

Step 1: Add DataStore Dependencies

First, update your build.gradle (app-level) file:

Kotlin
dependencies {
    implementation "androidx.datastore:datastore-preferences:1.0.0"
}

Sync your project to download the necessary libraries.

Step 2: Create Your DataStore Instance

Unlike SharedPreferences, you don’t instantiate DataStore directly. Instead, use an extension on Context.

Kotlin
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")

Place this in a Kotlin file (e.g., DataStoreModule.kt) at the top-level (outside any class).

Step 3: Reading Data from DataStore

Let’s say you used to read the user’s theme like this:

Kotlin
val isDarkMode = sharedPreferences.getBoolean("dark_mode", false)

Here’s how to do it with DataStore:

Kotlin
val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")

val isDarkModeFlow: Flow<Boolean> = context.dataStore.data
    .map { preferences ->
        preferences[DARK_MODE_KEY] ?: false
    }

Btw, what’s happening here?

  • DARK_MODE_KEY is a typed key (you can have string, int, float, etc.).
  • dataStore.data returns a Flow of Preferences.
  • map transforms it to the value you care about.

To observe the value:

Kotlin
lifecycleScope.launch {
    isDarkModeFlow.collect { isDark ->
        // Update UI or store in variable
    }
}

Step 4: Writing Data to DataStore

Here’s how you’d save data using SharedPreferences:

Kotlin
sharedPreferences.edit().putBoolean("dark_mode", true).apply()

With DataStore:

Kotlin
suspend fun saveDarkModeSetting(context: Context, isDarkMode: Boolean) {
    context.dataStore.edit { preferences ->
        preferences[DARK_MODE_KEY] = isDarkMode
    }
}

This function must be called from a coroutine or lifecycleScope.launch {}.

Step 5: Migrate Existing Data from SharedPreferences

Let’s say you have existing users and don’t want to lose their preferences.

Jetpack provides a migration tool built in:

Kotlin
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
    name = "user_prefs",
    produceMigrations = { context ->
        listOf(SharedPreferencesMigration(context, "user_prefs"))
    }
)

This tells DataStore to automatically read and move values from SharedPreferences the first time it’s accessed.

Important:
  • The name in preferencesDataStore must match the SharedPreferences file name.
  • After migration, DataStore handles everything.

Step 6: Remove SharedPreferences Usage

Once you’re confident DataStore is working, clean up your codebase:

  • Delete old SharedPreferences references
  • Remove the old preference XML file if applicable

This makes your app lighter and future-proof.

Bonus: Best Practices for DataStore

  • Use a singleton or Context extension to access DataStore.
  • Keep key declarations in one place (object or constants file).
  • Prefer Flow + collect with lifecycle awareness to avoid leaks.
  • Validate and sanitize user input before writing to DataStore.

Conclusion

Migrating from SharedPreferences to Jetpack DataStore is a smart move. It modernizes your data layer, embraces async programming, and makes your app more robust.

With the step-by-step guide above, you should now feel confident making the switch. It’s not just about keeping up with Android trends — it’s about building better apps.

So go ahead, migrate from SharedPreferences to Jetpack DataStore, and give your app the stability and performance it deserv

error: Content is protected !!