Ders İçeriği
Flutter, platformlar arası uygulama geliştirmeyi kolaylaştırsa da, bazen platforma özgü özelliklere veya yerel (native) kodlara erişim ihtiyacı duyulabilir. Flutter, bu tür senaryolar için
MethodChannel ve Platform sınıfları gibi mekanizmalar sunar.
4.1. Platform Kanalları (MethodChannel)
MethodChannel, Flutter (Dart) kodu ile platforma özgü (Kotlin/Java for Android, Swift/Objective-C for iOS) kod arasında çift yönlü iletişim kurmak için kullanılır. Flutter tarafında bir metod çağrısı yapabilir ve platform tarafında bu çağrıyı dinleyip bir sonuç döndürebilirsiniz. Aynı şekilde, platform tarafından Flutter tarafına olaylar gönderebilirsiniz.
Nasıl Çalışır?
1.Flutter (Dart) Tarafı:
•Bir MethodChannel örneği oluşturulur ve benzersiz bir kanal adı verilir (örneğin, samples.flutter.dev/battery).
•invokeMethod() kullanılarak platforma bir metod çağrısı yapılır. İsteğe bağlı olarak argümanlar gönderilebilir.
•Platformdan gelen sonuç Future olarak alınır.
2.Platform (Native) Tarafı (Android - Kotlin/Java):
•Aynı kanal adıyla bir MethodChannel oluşturulur.
•setMethodCallHandler() kullanılarak Flutter tarafından gelen metod çağrıları dinlenir.
•Gelen metodun adı kontrol edilir ve ilgili platforma özgü kod çalıştırılır.
•Sonuç result.success(), result.error() veya result.notImplemented() ile Flutter tarafına geri gönderilir.
Örnek: Batarya Seviyesini Alma (Android için)
Flutter (Dart) Kodu (lib/main.dart):import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // MethodChannel için
class BatteryLevelScreen extends StatefulWidget {
const BatteryLevelScreen({Key? key}) : super(key: key);
@override
State<BatteryLevelScreen> createState() => _BatteryLevelScreenState();
}
class _BatteryLevelScreenState extends State<BatteryLevelScreen> {
static const MethodChannel _channel = MethodChannel('samples.flutter.dev/battery');
String _batteryLevel = 'Bilinmiyor.';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await _channel.invokeMethod('getBatteryLevel');
batteryLevel = 'Batarya seviyesi: $result%';
} on PlatformException catch (e) {
batteryLevel = "Batarya seviyesi alınamadı: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Batarya Seviyesi')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_batteryLevel, style: const TextStyle(fontSize: 20)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _getBatteryLevel,
child: const Text('Batarya Seviyesini Al'),
),
],
),
),
);
}
}
void main() {
runApp(const MaterialApp(home: BatteryLevelScreen()));
}
Android (Kotlin) Kodu (android/app/src/main/kotlin/com/example/your_app_name/MainActivity.kt):package com.example.your_app_name // Paket adınızı güncelleyin
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL =
"samples.flutter.dev/battery"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Batarya seviyesi alınamadı.", null)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = android.content.ContextWrapper(applicationContext).registerReceiver(null, android.content.IntentFilter(android.content.Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(android.os.BatteryManager.EXTRA_SCALE, -1)
}
return batteryLevel
}
}
iOS (Swift) Kodu (ios/Runner/AppDelegate.swift):import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard call.method == "getBatteryLevel" else {
result(FlutterMethodNotImplemented)
return
}
self?.receiveBatteryLevel(result: result)
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func receiveBatteryLevel(result: FlutterResult) {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
if device.batteryState == .unknown {
result(FlutterError(code: "UNAVAILABLE",
message: "Batarya seviyesi alınamadı.",
details: nil))
} else {
result(Int(device.batteryLevel * 100))
}
}
}
MethodChannel kullanımı, uygulamanızın platforma özgü donanım veya yazılım özelliklerine erişmesi gerektiğinde vazgeçilmezdir. Ancak, mümkün olduğunca platform bağımsız çözümler veya hazır Flutter paketleri kullanmak, kod karmaşıklığını azaltır.
4.2. Kamera, Galeri, Konum Servisleri Entegrasyonu
Mobil uygulamalarda sıkça kullanılan özellikler arasında kamera erişimi, galeriye erişim ve konum servisleri bulunur. Flutter, bu tür platform özelliklerine erişmek için genellikle popüler paketler aracılığıyla kolay entegrasyon sağlar.
•Kamera ve Galeri (image_picker paketi):
image_picker paketi, cihazın kamerasını kullanarak fotoğraf çekmenizi veya galeriden mevcut bir fotoğrafı/videoyu seçmenizi sağlar.
•Android: android/app/src/main/AndroidManifest.xml dosyasına kamera ve depolama izinlerini eklemeniz gerekebilir.
•iOS: ios/Runner/Info.plist dosyasına kamera ve fotoğraf kütüphanesi kullanım açıklamalarını eklemeniz gerekir.
•Konum Servisleri (geolocator paketi):
geolocator paketi, cihazın konum bilgilerine (enlem, boylam, hız vb.) erişmenizi sağlar. GPS, Wi-Fi veya hücresel ağlar aracılığıyla konum alabilir.
dependencies:
flutter:
sdk: flutter
geolocator: ^11.0.0 # En güncel sürümü kullanın
Sonra flutter pub get komutunu çalıştırın.
**Platforma Özgü Ayarlar:**
* Android: `android/app/src/main/AndroidManifest.xml` dosyasına konum izinlerini ekleyin.
* iOS: `ios/Runner/Info.plist` dosyasına konum kullanım açıklamalarını ekleyin.
Kullanım Örneği:
dart
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
class LocationExample extends StatefulWidget {
const LocationExample({Key? key}) : super(key: key);
@override
State<LocationExample> createState() => _LocationExampleState();
}
class _LocationExampleState extends State<LocationExample> {
String _locationMessage = 'Konum bekleniyor...';
Future<void> _getCurrentLocation() async {
bool serviceEnabled;
LocationPermission permission;
// Konum servislerinin etkin olup olmadığını kontrol et
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
setState(() {
_locationMessage = 'Konum servisleri kapalı. Lütfen açın.';
});
return;
}
// Konum izinlerini kontrol et
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
setState(() {
_locationMessage = 'Konum izinleri reddedildi.';
});
return;
}
}
if (permission == LocationPermission.deniedForever) {
setState(() {
_locationMessage = 'Konum izinleri kalıcı olarak reddedildi. Ayarlardan izin verin.';
});
return;
}
// Konumu al
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
_locationMessage = 'Enlem: ${position.latitude}, Boylam: ${position.longitude}';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Konum Servisleri Örneği')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_locationMessage, textAlign: TextAlign.center, style: const TextStyle(fontSize: 18)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _getCurrentLocation,
child: const Text('Konumumu Al'),
),
],
),
),
);
}
}
void main() {
runApp(const MaterialApp(home: LocationExample()));
}
4.3. Paket Kullanımı ve Oluşturma
Flutter ekosistemi, pub.dev adresinde yüzlerce hazır paketle doludur. Bu paketler, geliştirme sürecini hızlandırmak ve yaygın işlevleri kolayca uygulamanızı sağlamak için tasarlanmıştır. Kendi özel ihtiyaçlarınız için de paketler oluşturabilir ve paylaşabilirsiniz.
•Paket Kullanımı:
1.Paket Bulma: pub.dev adresinde ihtiyacınız olan paketi arayın.
2.pubspec.yaml'a Ekleme: Paketin sayfasındaki Installing sekmesinde belirtilen bağımlılığı pubspec.yaml dosyanızın dependencies bölümüne ekleyin.
3.Paketleri İndirme: Terminalde flutter pub get komutunu çalıştırın. Bu, paketi projenize indirir ve bağımlılıkları çözer.
4.Paketi İçe Aktarma: Dart kodunuzda paketi kullanmak istediğiniz yerde import 'package:some_package/some_package.dart'; şeklinde içe aktarın.
•Paket Oluşturma:
Kendi özel widget'larınızı, fonksiyonlarınızı veya platforma özgü kodlarınızı diğer projelerde veya toplulukla paylaşmak için bir Flutter paketi oluşturabilirsiniz.
1.Paket Oluşturma Komutu: Terminalde aşağıdaki komutu çalıştırın:
2.Kod Yazma: lib/ klasöründe Dart kodunuzu yazın. Eğer platforma özgü kod gerekiyorsa, android/ ve ios/ klasörlerinde ilgili native kodları yazın ve MethodChannel kullanarak Flutter tarafıyla iletişim kurun.
3.pubspec.yaml Düzenleme: Paketin açıklamasını, versiyonunu ve bağımlılıklarını pubspec.yaml dosyasında güncelleyin.
4.Test Etme: Paketinizi test etmek için bir örnek uygulama oluşturabilir veya mevcut bir uygulamada yerel olarak kullanabilirsiniz.
5.Yayınlama (İsteğe Bağlı): Paketinizi pub.dev'de yayınlamak isterseniz, pub.dev yönergelerini takip ederek paketinizi yayınlayabilirsiniz.
Paketler, Flutter geliştirme ekosisteminin gücünü ve esnekliğini gösterir. Mevcut paketleri kullanarak geliştirme süresini kısaltabilir, kendi paketlerinizi oluşturarak da topluluğa katkıda bulunabilirsiniz.