DEV Community

Samuel Adekunle
Samuel Adekunle

Posted on • Originally published at techwithsam.dev

AI Engineering for Flutter Developers – Getting Started with Gemini & On-Device AI

It's been a while since my last release. You know, life happened :(

I'm back now with more positive energy, and I'm starting a brand new series titled AI Engineering for Flutter Developers.

This series is about helping you become a better AI Engineer as a Flutter developer, someone who can thoughtfully integrate AI into production-grade mobile apps, understand the concepts, make smart architecture decisions, and ship reliable features.

We're starting from the fundamentals, i.e mindset shift, key concepts you need to know, and building your very first practical AI feature using Gemini and on-device models.

If you've been overwhelmed by all the AI noise on socials (esp. X), this series is for you.

It's no longer a secret that most (if not all) developers right now are AI users, i.e they use AI to perform coding tasks (copy prompts, paste code) and hope it works.

As Flutter developers, we need to become AI Engineers.

What does that mean?

  • You understand when to use on-device vs cloud AI
  • You know how to evaluate quality and handle failures
  • You design proper architecture around AI features
  • You care about privacy, performance, cost, and user experience

Key AI Concepts Every Developer Should Know

  • LLMs (Large Language Models): Gemini, Claude, etc.
  • Embeddings: Turning text/images into numbers for comparison
  • RAG (Retrieval Augmented Generation): Giving AI your own data
  • Tool Calling / Function Calling: Letting AI trigger actions
  • Agents: AI that can plan and execute multi-step tasks
  • On-device AI: Running models locally for privacy and speed

We'll use all of these throughout the series, so keep them in mind.

Practical Setup (Gemini + On-Device)

First, let's get set up.

  1. Get your Gemini API key from Google AI Studio

Google AI Studio API Key Page

  1. Add the necessary packages:
dependencies:
  googleai_dart: ^latest
  tflite_flutter: ^latest
Enter fullscreen mode Exit fullscreen mode
  1. Basic Gemini call example:
import 'package:googleai_dart/googleai_dart.dart';

Future<void> main() async {
  final client = GoogleAIClient.fromEnvironment();

  try {
    final response = await client.models.generateContent(
      model: 'gemini-3.5-flash',
      request: GenerateContentRequest(
        contents: [Content.text('Explain why Dart works well for APIs.')],
      ),
    );

    print(response.text);
  } finally {
    client.close();
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Simple on-device model setup (we'll use a lightweight classification model):
/// Initialize TFLite Interpreter if asset model is provided.
  Future<void> initializeModel({String? modelPath}) async {
    if (modelPath != null) {
      try {
        _interpreter = await Interpreter.fromAsset(modelPath);
        _isInitialized = true;
      } catch (e) {
        debugPrint('TFLite native model initialization note: $e');
        _isInitialized = false;
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

Now let's build something useful together.

We're going to create a Smart Text Analyzer feature that can:

  • Use Gemini to summarize or extract insights
  • Use an on-device model for quick classification (e.g., sentiment or category)
  • Show both results side by side

Creating a structured prompt for JSON output with Gemini

/// Analyzes input text using Google Gemini AI via googleai_dart client.
  Future<GeminiInsight> analyzeText(String inputText) async {
    if (apiKey.trim().isEmpty) {
      throw Exception(
        'Gemini API Key is missing. Tap the key icon in the app bar to configure your key.',
      );
    }

    if (inputText.trim().isEmpty) {
      throw Exception('Input text cannot be empty.');
    }

    GoogleAIClient? client;
    try {
      // 1. Instantiate client using GoogleAIConfig and ApiKeyProvider from googleai_dart
      client = GoogleAIClient(
        config: GoogleAIConfig(
          authProvider: ApiKeyProvider(apiKey),
        ),
      );

      // 2. Format structured prompt for JSON output
      final prompt = '''
Analyze the following text and extract structured insights. Return ONLY a valid JSON object with:
- "summary": A concise 2-3 sentence summary of the key message.
- "keyInsights": A list of up to 4 main takeaways.
- "actionItems": A list of relevant action items or follow-ups suggested by the text (or empty list [] if none).
- "tone": The overall tone (e.g., Professional, Urgent, Enthusiastic, Frustrated, Informative).

Text to analyze:
"$inputText"
''';

      // 3. Send request to Gemini API via client.models.generateContent
      final response = await client.models.generateContent(
        model: modelName,
        request: GenerateContentRequest(
          contents: [
            Content(
              parts: [TextPart(prompt)],
              role: 'user',
            ),
          ],
        ),
      );

      // 4. Extract generated text from response candidate
      final candidate = response.candidates?.firstOrNull;
      final parts = candidate?.content?.parts ?? [];
      final rawText = parts
          .whereType<TextPart>()
          .map((p) => p.text)
          .join('\n');

      if (rawText.isEmpty) {
        throw Exception('Received an empty response from Gemini API.');
      }

      return _parseResponse(rawText);
    } catch (e) {
      if (e is Exception) rethrow;
      throw Exception('Gemini API Error: $e');
    } finally {
      client?.close();
    }
  }
Enter fullscreen mode Exit fullscreen mode

On-device classification

/// Classifies text locally on device and measures inference latency.
  Future<OnDeviceClassification> classifyText(String text) async {
    // ....... 

    // Fast high-speed local token analysis engine (on-device fallback)
    final words = _tokenize(text);
    final detectedKeywords = <String>{};

    double posScore = 0.0;
    double negScore = 0.0;

    for (final word in words) {
      if (_positiveWords.containsKey(word)) {
        posScore += _positiveWords[word]!;
        detectedKeywords.add(word);
      }
      if (_negativeWords.containsKey(word)) {
        negScore += _negativeWords[word]!;
        detectedKeywords.add(word);
      }
    }

    // Sentiment Determination
    String sentiment = 'Neutral';
    double sentimentConfidence = 0.5;

    if (posScore > negScore && posScore > 0.3) {
      sentiment = 'Positive';
      sentimentConfidence = min(0.99, 0.55 + (posScore / (posScore + negScore + 1.0)) * 0.44);
    } else if (negScore > posScore && negScore > 0.3) {
      sentiment = 'Negative';
      sentimentConfidence = min(0.99, 0.55 + (negScore / (posScore + negScore + 1.0)) * 0.44);
    } else {
      sentiment = 'Neutral';
      sentimentConfidence = 0.65;
    }

    // Category Determination
    final categoryScores = <String, double>{};
    for (final entry in _categoryKeywords.entries) {
      double score = 0.0;
      for (final kw in entry.value) {
        if (words.contains(kw)) {
          score += 1.0;
          detectedKeywords.add(kw);
        }
      }
      categoryScores[entry.key] = score;
    }

    // .......
  }
Enter fullscreen mode Exit fullscreen mode

Full source code here:

GitHub logo techwithsam / ai_engineer_for_flutter_devs

AI Engineering for Flutter Devs 2026 - TechWithSam

AI Engineering for Flutter Developers – Smart Text Analyzer

Free resource from Tech With Sam — companion repo for the AI Engineering for Flutter Developers YouTube series.

Flutter Dart Google AI TensorFlow Lite License YouTube Playlist


📦 What's in This Repo

Folder / File Contents
/lib/services Cloud Gemini (GeminiService), On-Device TFLite (OnDeviceClassifierService), & Resilient AI Engine (ResilientAIService, RetryHelper)
/lib/models Data models (TextAnalysisResult), Structured Output schemas (ArticleBlueprint), & Custom AI Exceptions (ai_exceptions.dart)
/lib/widgets UI components: Gemini/On-Device cards, StreamingOutputWidget, StructuredBlueprintCard, & ErrorResilienceBanner
/lib/theme Dark & light mode brand theme system (AppTheme)
/lib/part_two_app.dart Video 2 entry point & studio screen for Structured Output, Token Streaming, and Fault Injection testing
/lib/main.dart Main root app launcher coexisting across all video series modules

🚀 Quick Setup

# 1. Clone the repo
git clone https://github.com/techwithsam/ai_engineer_for_flutter_devs.git
# 2. Navigate into the project
cd ai_engineer_for_flutter_devs

# 3. Get dependencies
flutter
Enter fullscreen mode Exit fullscreen mode

Recap & Key Takeaways

Today we covered:

  • The difference between an AI user and an AI Engineer
  • Core concepts you need
  • How to set up Gemini and basic on-device AI
  • Your first working AI feature in Flutter

This is just the foundation. The real power comes in the next article.


Before you go - I've prepared a free AI Engineering Starter Pack for you.
It includes:

  • Setup guides
  • Reusable components
  • Prompt templates
  • And a few exclusive extras

You can download it for free at: techwithsam.dev/ai-starter-kit

Just enter your email, and it will be sent to you instantly.


If you found this valuable, please hit the like clap, follow, and turn on notifications so you don't miss the rest of this series.

This is Part 1 of the AI Engineering for Flutter Devs series.

In the next release, we'll go deeper into building reliable, production-ready AI features.

Drop a comment and tell me: What's one AI feature you want to build in your Flutter app?

Thank you for following. Welcome back to the journey with me, and I'll see you in the next one.

Take care!

Top comments (0)