Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
Dizi · 44/61 Flutter Türkçe Tutorial
- Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
- Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
- Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
- Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
- Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
- Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
- Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
- Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
- Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
- Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
- Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
- Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
- Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
- Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
- Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
- Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
- Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
- Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
- Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
- Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
- Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
- Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
- Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
- Bölüm 6 — Konu 24: Provider Paketi
- Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
- Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
- Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
- Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
- Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
- Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
- Bölüm 7 — Konu 31: Deep Linking
- Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
- Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
- Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
- Bölüm 8 — Konu 35: Implicit Animasyonlar
- Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
- Bölüm 8 — Konu 37: Hero Animasyonları
- Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
- Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
- Bölüm 9 — Konu 40: Platform Channels
- Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
- Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
- Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
- Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
- Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
- Bölüm 10 — Konu 46: CI/CD
- Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
- Bölüm 10 — Konu 48: DevTools Profiling
- Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
- Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
- Bölüm 11 — Konu 51: Supabase Alternatifi
- Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
- Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
- Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
- Bölüm 12 — Konu 55: Flutter Web / Desktop
- Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
- Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
- Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
- Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
- Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
- Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
İçindekiler 11 başlık
- Flutter Projesinin Altında İki Ayrı "Native Proje" Yatıyor
- Android — Gradle Sistemi
- flutter build Komutları — APK vs App Bundle (AAB)
- Build Türleri — Debug, Profile, Release
- İmzalama (Signing) — Neden Zorunlu?
- iOS — Xcode ve CocoaPods
- Android ile iOS Build Sistemleri — Karşılaştırma
- Sık Karşılaşılan Build Sorunları — Nereye Bakmalı?
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
- 🎮 Mini Uygulama — Bölüm 9 Checkpoint: İzin ve Native Entegrasyon Merkezi
Bölüm 9'un son konusu. Şimdiye kadar hep flutter run ile geliştirme yaptık — bu derste, flutter run'ın arka planda gerçekte ne yaptığını ve bir uygulamayı dağıtılabilir bir dosyaya (APK, AAB, IPA) nasıl dönüştürdüğünü öğreneceğiz. Mağazaya yayınlama sürecinin kendisini Bölüm 11'de göreceğiz — bu ders, ona giden build mekanizmasına odaklanıyor.
Flutter Projesinin Altında İki Ayrı "Native Proje" Yatıyor
Bölüm 1 Konu 3'te flutter create ile oluşan klasör yapısını görmüştük — lib/ klasörü (senin Dart kodun) dışında, iki klasör daha vardı:
android/ # tam teşekküllü bir Android (Gradle) projesi
ios/ # tam teşekküllü bir iOS (Xcode) projesiÖnemli gerçek: Bunlar "sahte" ya da "yardımcı" dosyalar değil — android/ klasörü, Android Studio'da doğrudan açılabilen, ios/ klasörü Xcode'da doğrudan açılabilen, gerçek native projelerdir. Flutter, senin Dart kodunu derleyip, bu native projelerin içine bir kütüphane olarak yerleştirir. Bu yüzden Android build sistemini (Gradle) ve iOS build sistemini (Xcode/CocoaPods) en azından temel düzeyde anlamak, "build hatası" ile karşılaştığında nereye bakman gerektiğini bilmen için önemlidir.
Android — Gradle Sistemi
android/
├── build.gradle # PROJE geneli ayarlar (repository'ler, Kotlin sürümü)
├── app/
│ └── build.gradle # UYGULAMA'ya özel ayarlar (applicationId, sürüm, imzalama)
└── app/src/main/AndroidManifest.xml # izinler (Konu 41), uygulama adı, ikonapp/build.gradle içinde göreceğin en önemli alanlar:
android {
defaultConfig {
applicationId "com.senirket.uygulaman" // Play Store'daki BENZERSİZ kimliğin
minSdkVersion 21 // desteklenen EN ESKİ Android sürümü
targetSdkVersion 34 // test edilip ONAYLANDIĞIN Android sürümü
versionCode 1 // her yayında ARTMASI gereken tam sayı (Play Store bunu takip eder)
versionName "1.0.0" // kullanıcıya GÖRÜNEN sürüm numarası
}
}applicationId, Dart Bölüm 6'da öğrendiğimiz benzersiz tanımlayıcı kavramına benzer — Play Store'da bir kere kullanılır, yayınladıktan sonra değiştirilemez. versionCode ile versionName arasındaki fark önemli: versionCode makine içindir (Play Store, hangi sürümün daha yeni olduğunu bununla anlar — her yayında kesinlikle artmalı), versionName ise insan içindir (kullanıcının Play Store'da gördüğü "1.0.0" gibi bir metin).
flutter build Komutları — APK vs App Bundle (AAB)
flutter build apk # tek, kurulabilir bir .apk dosyası üretir
flutter build appbundle # Play Store'un istediği .aab formatı üretirAradaki fark, dağıtım şekli: .apk, doğrudan kurulabilen tam bir paket — test amaçlı, ya da Play Store dışı dağıtım (bir web sitesinden indirme gibi) için kullanılır. .aab (Android App Bundle), Play Store'a yüklediğin format — Play Store, bu dosyadan, her cihazın kendi özelliklerine (ekran çözünürlüğü, işlemci mimarisi, dil) göre optimize edilmiş, küçültülmüş bir APK kendisi üretip o cihaza gönderir. Pratik kural: Play Store'a yayınlayacaksan appbundle, elle test/dağıtım için apk.
Build Türleri — Debug, Profile, Release
Dart Bölüm 1'de öğrendiğimiz JIT (Just-In-Time) vs AOT (Ahead-Of-Time) derleme ayrımını hatırlarsan — Flutter'ın üç build türü, tam olarak bu ayrıma dayanır:
| Build Türü | Derleme | Ne Zaman Kullanılır |
|---|---|---|
| Debug | JIT — hot reload çalışır | Günlük geliştirme (flutter run'ın varsayılanı) |
| Profile | AOT — ama profiling araçları açık | Performans ölçümü (Bölüm 10'da DevTools ile) |
| Release | AOT — tüm optimizasyonlar açık, debug bilgisi yok | Gerçek kullanıcıya dağıtım |
flutter run # debug (varsayılan)
flutter run --profile
flutter run --release
flutter build apk --release # build komutlarında varsayılan zaten release'tirNeden bu ayrım önemli? Debug build'ler, hot reload'ı mümkün kılmak için ekstra kod ve kontrol taşır — bu, uygulamayı belirgin şekilde yavaşlatır. Bir arkadaşına "uygulamam çok yavaş" diye şikayet etmeden önce, release build ile test etmen gerekir — debug build'in performansı, gerçek kullanıcı deneyimini asla yansıtmaz.
İmzalama (Signing) — Neden Zorunlu?
Android, kimliği doğrulanmamış bir APK'nın Play Store'a yüklenmesine izin vermez — her release build'in bir imza (dijital sertifika) ile işaretlenmesi gerekir. Bu, Dart Bölüm 8'de öğrendiğimiz hata yönetimi kadar teknik olmayan, daha çok bir güvenlik/kimlik mekanizması: "bu uygulamanın gerçekten senden geldiğini" kanıtlıyor.
keytool -genkey -v -keystore ~/anahtar.jks -keyalg RSA -keysize 2048 -validity 10000 -alias anahtarimBu komutla oluşturduğun .jks dosyası (keystore), android/app/build.gradle'a bağlanır ve her --release build'inde otomatik olarak kullanılır. Kritik uyarı: Bu dosyayı kaybetmemen gerekir — kaybedersen, var olan uygulamanı bir daha güncelleyemezsin (Play Store, farklı bir imzayla gelen güncellemeyi reddeder). İmzalama sürecinin tam adımlarını Bölüm 11 Konu 53'te (Store yayınlama süreci) detaylı işleyeceğiz.
iOS — Xcode ve CocoaPods
ios/
├── Runner.xcworkspace # Xcode'da AÇILMASI gereken dosya (Runner.xcodeproj DEĞİL!)
├── Runner/Info.plist # izinler (Konu 41), uygulama adı, Bundle Identifier
└── Podfile # CocoaPods bağımlılıklarıRunner.xcworkspace vs Runner.xcodeproj — bu, iOS geliştirmeye yeni başlayanların sık düştüğü bir tuzak: pubspec.yaml'daki paketlerin native tarafındaki (iOS) kısımları, CocoaPods (iOS'un paket yöneticisi, Dart'ın pubuna benzer bir rolü var) ile yönetilir. CocoaPods, bu bağımlılıkları bir araya getiren bir .xcworkspace dosyası oluşturur — sen her zaman bu dosyayı açmalısın, .xcodeproj'u değil (o, sadece ana projeyi, eklenen paketler olmadan gösterir).
Info.plist, Konu 41'de gördüğümüz izin açıklamalarının (NSCameraUsageDescription gibi) yanı sıra, uygulamanın Bundle Identifier'ını da (Android'deki applicationId'nin iOS karşılığı, örn. com.senirket.uygulaman) tutar.
flutter build ios # simülatör/cihaz için (imzasız, test amaçlı)
flutter build ipa # App Store'a yüklenebilir .ipa dosyası (imzalı)iOS'ta imzalama daha karmaşıktır — bir Apple Developer hesabı (yıllık ücretli), bir imzalama sertifikası, ve bir provisioning profile (hangi cihazlarda/hangi özelliklerle çalışabileceğini tanımlayan bir dosya) gerektirir. Bu süreç, genelde Xcode'un kendi arayüzü üzerinden "Automatically manage signing" seçeneğiyle büyük ölçüde otomatikleştirilir — elle sertifika/profil yönetimi, genelde kurumsal/takım senaryolarında gerekir.
Android ile iOS Build Sistemleri — Karşılaştırma
| Android (Gradle) | iOS (Xcode/CocoaPods) | |
|---|---|---|
| Benzersiz kimlik | applicationId |
Bundle Identifier |
| Paket yöneticisi | Gradle (Maven repository'leri) | CocoaPods |
| Dağıtım formatı | .apk (test) / .aab (Store) |
.ipa |
| İmzalama | Keystore (.jks) — sen oluşturursun |
Sertifika + provisioning profile — Apple onaylar |
| Geliştirme maliyeti | Ücretsiz (Play Store kaydı bir kerelik $25) | Apple Developer hesabı (yıllık ~$99) |
| Açılması gereken dosya | (Android Studio otomatik bulur) | Runner.xcworkspace (.xcodeproj DEĞİL) |
Sık Karşılaşılan Build Sorunları — Nereye Bakmalı?
- "Gradle build failed" →
android/build.gradleveyaandroid/app/build.gradle'da bir sürüm çakışması, ya da bir paketin Android tarafındaki native kodunda sorun. - "CocoaPods could not find compatible versions" →
ios/Podfile.lock'ı silipcd ios && pod installçalıştırmak, çoğu zaman çözer. - "No provisioning profile found" → Apple Developer hesabı/sertifika sorunları — Xcode'un "Signing & Capabilities" sekmesine bakılır.
- Debug build'de yavaşlık şikayeti → muhtemelen sorun değil, release build ile tekrar test et.
🎯 Bu Dersten Çıkarılması Gerekenler
android/veios/klasörleri, gerçek native projelerdir — Flutter, Dart kodunu bunların içine bir kütüphane olarak yerleştirir.- Android'de
applicationId/versionCode/versionName,app/build.gradle'da tanımlanır;.apktest/dağıtım,.aabPlay Store içindir. - Build türleri (debug/profile/release), Dart'ın JIT/AOT derleme ayrımına dayanır — performans şikayetleri her zaman release build ile doğrulanmalıdır.
- Android imzalama bir keystore (
.jks) ile sendeyken, iOS imzalama Apple Developer hesabı + sertifika + provisioning profile gerektirir. - iOS'ta her zaman
Runner.xcworkspaceaçılmalı (CocoaPods bağımlılıklarını içerir),Runner.xcodeprojdeğil.
📝 Ödevler
- [ ] Bir Flutter projesinde
android/app/build.gradle'ı aç,applicationId,minSdkVersion,versionCode/versionNamealanlarını bul ve her birinin ne işe yaradığını kendi cümlelerinle yaz. - [ ]
flutter build apk --releaseveflutter build appbundle --releasekomutlarını çalıştır, oluşan dosyaların boyutunu ve konumunu karşılaştır. - [ ] Aynı uygulamayı debug ve release modda çalıştırıp (
flutter runvsflutter run --release), açılış hızındaki farkı gözlemle. - [ ] (Mac kullanıyorsan)
ios/Runner.xcworkspace'i Xcode'da aç, "Signing & Capabilities" sekmesinde Bundle Identifier'ı bul. - [ ] Kendi cümlelerinle, "neden
.aabformatının Play Store için.apk'dan daha avantajlı olduğunu" açıkla.
🎮 Mini Uygulama — Bölüm 9 Checkpoint: İzin ve Native Entegrasyon Merkezi
Bölüm 9'un tamamını (platform channels, izinler, kamera/konum/sensör, push notification, build) test eden bir mini proje:
Gereksinimler:
- Tek bir ekranda, sırayla şu özelliklerin her biri için durum gösteren ve tetikleyen bir buton/kart olsun: kamera izni (Konu 41), konum alma (Konu 42), ivmeölçer canlı verisi (Konu 42).
- Her kart,
PermissionStatus'a göre farklı bir görsel durum göstersin (granted: yeşil, denied: sarı, permanentlyDenied: kırmızı + "Ayarlara Git" butonu). - (Firebase kurulumun varsa) FCM token'ını ekranda göster, bir test bildirimi gönderip
onMessageile yakalayıpflutter_local_notificationsile göster. - Uygulamayı hem debug hem release modda çalıştırıp, tüm özelliklerin her ikisinde de çalıştığını doğrula.
- Bonus:
flutter build apk --releaseile gerçek bir APK üret, kendi Android cihazına yükleyip test et.
Bölüm 9 tamamlandı. Sıradaki konu: Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden Test)