Terakhir diperbarui: 26 Oktober 2026
Setelah menyelesaikan codelab ini, mahasiswa mampu:
campus_notify atau project hasil refactor Minggu 7). Codelab ini menambah satu fitur AI ke project yang sudah ada.AI fitur memungkinkan aplikasi mobile berkomunikasi dengan model AI di cloud untuk menyediakan layanan cerdas kepada pengguna:
+----------------+ HTTPS/wss +----------------+
| Flutter UI | <-----------------> | AI API Layer |
| (Chat, OCR, | (Dio/http) | (LLM, OCR, |
| STT, Image) | | STT, Vision) |
+----------------+ +----------------+
| |
| API Key (secure storage) | Response
v v
+----------------+ Optional +----------------+
| Local Cache | <-----------------> | Backend |
| (Hive/SQLite) | (batching) | (auth, log) |
+----------------+ +----------------+
flutter_secure_storage untuk menyimpan token/kunci| Komponen | Contoh | Tujuan |
|---|---|---|
| System prompt | "Kamu asisten kampus ramah, jawab dalam Bahasa Indonesia, maksimal 2 kalimat" | Menetapkan persona dan batas |
| User prompt | "Jadwal kampus hari Senin?" | Input pengguna |
| Konteks | Data jadwal, profil user, lokasi | Membuat respons relevan |
| Batas | Jangan memberikan data pribadi lain | Privasi dan keamanan |
Tips: Pertahankan prompt singkat dan spesifik, terjemahkan hasil jika diperlukan, dan validasi output sebelum ditampilkan ke user.
Tambahkan ke pubspec.yaml:
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
flutter_secure_storage: ^9.0.0
riverpod: ^2.5.0
Buat lib/ai/ai_service.dart:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class AiService {
final _storage = const FlutterSecureStorage();
final _apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent';
Future<String> ask(String question) async {
final apiKey = await _storage.read(key: 'ai_api_key');
if (apiKey == null || apiKey.isEmpty) {
throw Exception('API key tidak tersedia. Silakan atur di pengaturan.');
}
final response = await http.post(
Uri.parse('$_apiUrl?key=$apiKey'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'contents': [{
'parts': [{'text': question}]
}]
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['candidates'][0]['content']['parts'][0]['text'];
} else {
throw Exception('Gagal memanggil AI API: ${response.statusCode}');
}
}
Future<void> saveApiKey(String key) async {
await _storage.write(key: 'ai_api_key', value: key);
}
}
Buat lib/features/chat_screen.dart dengan streaming response dan indikator loading.
image_pickerrecord atau just_audiofinal result = await aiService.recognizeText(imageFile);
final text = await aiService.speechToText(audioFile);
| Risiko | Mitigasi |
|---|---|
| Bocor data pengguna | Jangan kirim data sensitif ke AI API |
| Biaya melonjak | Batasi request per user/hari, gunakan cache lokal |
| API error / down | Tampilkan pesan ramah, opsi coba lagi, mode offline |
| Respons tidak relevan | Terapkan validasi dan fallback ke data lokal |
try {
final response = await aiService.ask(question);
} catch (e) {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('Layanan AI Sibuk'),
content: const Text('Coba lagi nanti atau gunakan mode offline.'),
),
);
}
docs/ai-log.md.flutter analyze + flutter test di README.10-week-10-ai-feature-integration/ berisi lib/, docs/, README.md, screenshots/.