Dart kodu ile yerel platformlar arasındaki etkileşim, cihaz yeteneklerine erişim gerektiren Flutter uygulamaları geliştirirken önemli bir görevdir. Flutter Team, 2026'ya göre, Platform Channel ek yerel kitaplık gerektirmeden Dart ile Android ve iOS yerel kodu arasında mesaj iletimini sağlayarak bu tür entegrasyon için birincil mekanizma olmaya devam etmektedir.
Önemli Noktalar
Platform Channel, uygulamanın Dart kodu ile Android ve iOS işletim sistemlerinin yerel kodu arasında çift yönlü iletişim sağlayan bir Flutter teknolojisidir. Platform Channel olmadan, bir Flutter uygulaması framework tarafından sağlanan yeteneklerle sınırlı kalır ve kamera API'lerine, sensörlere, Bluetooth'a, dosya sistemine ve diğer düşük seviyeli cihaz işlevlerine doğrudan erişemez.
Platform Channel mimarisi, asenkron mesaj alışverişi ilkesi üzerine inşa edilmiştir. Dart tarafı kanal aracılığıyla bir istek gönderir, yerel taraf bunu işler ve sonucu döndürür. Tüm mesajlar ikili biçime serileştirilir ve Flutter Engine mesaj arabelleği aracılığıyla iletilir, bu da yürütme ortamları arasında veri aktarımında minimum gecikme sağlar.
Her Platform Channel, mesaj yönlendirme için adres görevi gören benzersiz bir mantıksal adla (bir dize) tanımlanır. Dart tarafı ve yerel taraf, iletişimin doğru şekilde kurulması için aynı kanal adını kullanmalıdır. Flutter, tek bir uygulamada isteğe bağlı sayıda kanalı destekler ve her kanal diğerlerinden bağımsız olarak çalışır.
Resmi Flutter dokümantasyonuna göre, Platform Channel mesajları gönderildikleri sırayla işleyerek tahmin edilebilir çağrı sıralaması sağlar. Bu, yerel modüllerin sıralı başlatılması veya bağımlı işlem zincirleri gibi işlem sırasının doğruluğu etkilediği senaryolar için kritiktir.
Platform Channel aracılığıyla mesaj iletim mekanizması üç temel katmandan oluşur: Dart tarafı invokeMethod aracılığıyla Map veya List olarak bir mesaj gönderir, Flutter Engine bunu StandardMethodCodec kullanarak serileştirir ve yerel taraf işleyicisinde çağrıyı alır. Sonuç aynı yol üzerinden ters yönde döndürülür.
Serileştirme süreci otomatik olarak Dart veri türlerini yerel platform eşdeğerlerine dönüştürür. Sayılar, dizeler, boole değerleri, listeler ve sözlükler geliştiriciden ek yapılandırma gerektirmeden desteklenir. Özel veri türleri, kanal aracılığıyla gönderilmeden önce manuel olarak (örneğin bir JSON dizesine) serileştirilmelidir.
Flutter Engine tarafında, mesaj yerel platformun ana iş parçacığı kuyruğuna girer. Android'de bu uygulamanın ana iş parçacığıdır, iOS'te ana çalıştırma döngüsüdür. Bu, kanal işleyicisindeki uzun süreli işlemlerin kullanıcı arayüzünü bloke ettiği ve donmalara neden olduğu anlamına gelir. Geliştiricilerin ağır görevleri arka plan iş parçacıklarında yürütmeleri ve sonuçları geri çağırma yoluyla asenkron olarak döndürmeleri önerilir.
Platform Channel'ın performansı çoğu kullanım durumu için yeterince yüksektir: modern cihazlarda bir mesajın iletim süresi 1 milisaniyeden azdır. Ancak, gerçek zamanlı video akışı işleme gibi yüksek yüklü işlemler için Dart FFI veya doğrudan cihaz belleğine erişimi olan yerel eklentiler önerilir.
Mimarinin önemli bir sınırlaması: Platform Channel, dosya tanımlayıcılarının, bellek işaretçilerinin veya yerel nesnelerin iletilmesini desteklemez. Tüm veriler ikili biçime serileştirilebilir olmalıdır. Megabayt aralığındaki büyük hacimli verileri aktarmak için, kanal aracılığıyla yolu iletilen geçici dosyalar kullanın.
Flutter, her biri belirli bir etkileşim senaryosu için tasarlanmış üç tür Platform Channel sağlar. Doğru kanal türünü seçmek, entegrasyon mimarisini ve her iki taraftaki — Dart ve yerel — kod bakım kolaylığını belirler, bu nedenle MethodChannel, EventChannel ve BasicMessageChannel arasındaki farkları anlamak önemlidir.
MethodChannel, uzak yordam çağrısı modelini uygulayan en yaygın Platform Channel türüdür. Dart bir yöntem adı ve argümanlar gönderir, yerel taraf işlemi gerçekleştirir ve sonucu döndürür. Her çağrı bir Future döndürür ve bu da kullanışlı asenkron işlemler için Dart kodunda async ve await yapılarının kullanılmasına olanak tanır.
Bu kanal türü, istek-yanıt işlemleri için uygundur: pil seviyesini alma, sensör verilerini okuma, yerel tarafta hesaplama yapma veya sistem hizmetlerinden veri isteme. MethodChannel, modern Dart'ta Null safety desteği sayesinde null değerler de dahil olmak üzere StandardMethodCodec aracılığıyla standart veri türlerini destekler.
Gerçek projelerde MethodChannel, çoğu resmi Flutter eklentisinde kullanılır. Örneğin, camera, battery ve path_provider paketleri bu kanal türü aracılığıyla çalışarak her platform için özel entegrasyon kodu yazmadan yerel API'lere erişim sağlar.
EventChannel, yerel tarafın zaman içinde sürekli bir olay akışı oluşturduğu senaryolar için tasarlanmıştır. Veriler Stream aracılığıyla Dart'a iletilir ve gerçek zamanlı güncellemelere abone olmaya olanak tanır. Tipik kullanım durumları arasında ivmeölçer okumaları, GPS koordinatları, Bluetooth durum değişiklikleri ve sistem hizmetlerinden gelen bildirimler bulunur.
MethodChannel'ın aksine, EventChannel bir yayınla-abone ol modeli kullanır. Yerel taraf, Dart kodundan açık bir istek olmadan olaylar meydana geldikçe gönderir. Dart tarafındaki abone, her olayı ayrı bir akış öğesinde alır ve arayüzde kullanmadan önce alınan verileri filtreleyebilir veya dönüştürebilir.
EventChannel kullanırken, abonelikleri ve iptallerini doğru şekilde yönetmek gerekir. Yerel tarafta bellek sızıntılarını önlemek için kanalla çalışma tamamlandığında her StreamSubscription çağrısı iptal edilmelidir. Flutter platformu bir widget yok edildiğinde akışı otomatik olarak iptal eder, ancak açık abonelik yönetimi uzun süreli senaryolarda uygulama güvenilirliğini artırır.
BasicMessageChannel, en esnek Platform Channel türüdür ve isteğe bağlı asenkron mesaj alışverişi için tasarlanmıştır. Her mesajın bir yöntem adı ve argüman içerdiği MethodChannel'ın aksine, BasicMessageChannel yerleşik yönlendirme olmadan yalnızca yükü iletir. Gönderen bir mesaj gönderir, alıcı onu işler ve bir yanıt döndürür.
Bu kanal türü, mesaj yapısının uygulama durumuna bağlı olarak dinamik olarak değişebildiği özel etkileşim protokolleri için uygundur. BasicMessageChannel varsayılan olarak StandardMessageCodec kullanır ancak standart olmayan veri serileştirme biçimleri için isteğe bağlı bir MessageCodec eklemeyi destekler.
Pratikte BasicMessageChannel, MethodChannel'dan daha az kullanılır çünkü yerleşik bir adlandırma modeli olmadan manuel mesaj yönlendirme işleme gerektirir. Ancak, MethodChannel'da uygulanan standart istek-yanıt modelinden farklı belirli bir mesaj biçimi bekleyen yerel kitaplıklarla entegrasyon yaparken vazgeçilmezdir.
Cihaz pil seviyesini alma örneğini kullanarak pratik bir Platform Channel uygulamasını inceleyelim. Bu örnek, tam iş akışını göstermektedir: Dart tarafında bir MethodChannel bildirimi, Android ve iOS'ta işleyici uygulaması ve verilerin kullanılamadığı veya gerekli izinlerin olmadığı durumlarda hataların doğru şekilde ele alınması.
Dart tarafında, benzersiz bir dize kanal adıyla bir MethodChannel örneği oluşturulur. invokeMethod yöntemi yerel tarafa bir istek gönderir ve sonucu Future olarak bekler. Hata işleme, istek işleme sırasında bir istisna oluştuğunda yerel tarafın döndürdüğü PlatformException'ı yakalayarak yapılır.
import 'package:flutter/services.dart';
class BatteryPlugin {
static const _channel = MethodChannel(
'samples.flutter.dev/battery',
);
Future<String> getBatteryLevel() async {
try {
final result = await _channel.invokeMethod<int>(
'getBatteryLevel',
);
return 'Battery level: $result%';
} on PlatformException catch (e) {
return 'Failed: ${e.message}';
}
}
}
Android tarafında, işleyici MainActivity içinde configureFlutterEngine yöntemi aracılığıyla kaydedilir. setMethodCallHandler içinde, gelen yöntem adı kontrol edilir, pil seviyesini almak için BatteryManager'a yerel bir çağrı yapılır ve sonuç result nesnesi aracılığıyla döndürülür. Kanal tarafından desteklenmeyen yöntemler için result.notImplemented çağrılır.
import android.os.BatteryManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(
flutterEngine: FlutterEngine
) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
CHANNEL
).setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
val level = getBatteryLevel()
if (level != -1) {
result.success(level)
} else {
result.error(
"UNAVAILABLE",
"Battery level not available",
null
)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val manager = getSystemService(BATTERY_SERVICE) as BatteryManager
return manager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
)
}
}
iOS platformunda, işleyici AppDelegate sınıfında FlutterMethodChannel aracılığıyla kaydedilir. Swift kodu gelen çağrıyı alır, pil seviyesini almak için UIDevice sistem API'sine erişir ve sonucu Flutter'a döndürür. weak self yakalamalı asenkron işleme, bellekte güçlü referans döngüleri riski olmadan isteklerin yürütülmesine olanak tanır.
import UIKit
import Flutter
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
override func application(
application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: "samples.flutter.dev/battery",
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { [weak self] call, result in
if call.method == "getBatteryLevel" {
let level = self?.getBatteryLevel() ?? -1
if level >= 0 {
result(level)
} else {
result(FlutterError(
code: "UNAVAILABLE",
message: "Battery level not available",
details: nil
))
}
} else {
result(FlutterMethodNotImplemented)
}
}
return super.application(
application: application,
didFinishLaunchingWithOptions: launchOptions
)
}
private func getBatteryLevel() -> Int {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
return Int(device.batteryLevel * 100)
}
}
Platform Channel, bir Flutter uygulamasının standart paketlerde uygulanmayan cihaz yeteneklerine erişmesi gerektiğinde her zaman gereklidir. Geliştirici, kamera, biyometri, NFC, Bluetooth Low Energy için yerel SDK'larla entegrasyon yaparken veya uygulama sandbox'ı dışındaki dosya sistemiyle çalışırken özel bir kanal oluşturmalıdır.
İlk tipik senaryo, Dart'tan doğrudan erişilemeyen yerel API'lerin kullanılmasıdır. Bu, Android ve iOS sistem hizmetlerini, standart olmayan veri aktarım protokollerine sahip donanım sensörlerini, özel işleme mantığına sahip push bildirimlerini ve güvenli anahtar depolama için Donanım Güvenlik Modülü gerektiren kriptografik işlemleri içerir.
İkinci senaryo, bir Flutter projesine mevcut yerel kodun entegre edilmesidir. Bir şirket zaten Android veya iOS için yerel bir kitaplık geliştirmişse, Platform Channel bunu Dart'a taşımadan yeniden kullanmaya olanak tanır. Bu, hibrit uygulamaların Flutter'a geçişini hızlandırır ve mevcut yerel koda ve birikmiş iş mantığına yapılan yatırımları korur.
Üçüncü senaryo, pub.dev'de özel bir Flutter eklentisi yayınlamaktır. Tüm popüler eklentiler, dahili olarak her platformun yerel kodunu çağıran birleşik bir Dart API sağlamak için Platform Channel kullanır. Bu, Flutter ekibi tarafından her iki mobil platformu da destekleyen yeniden kullanılabilir paketler oluşturmak için önerilen standart yaklaşımdır.
Özel bir Platform Channel oluşturma ile pub.dev'den hazır bir paket kullanma arasında seçim yaparken, önce mevcut bir çözümün kullanılabilirliğini kontrol etmeniz önerilir. camera, geolocator, shared_preferences ve path_provider paketleri çoğu tipik ihtiyacı karşılar. Özel bir Platform Channel, yalnızca uygun bir paket olmadığında veya mevcut çözümün sağlamadığı yerel davranışın derin özelleştirilmesi gerektiğinde haklı çıkar.
Sıkça Sorulan Sorular
MethodChannel, tek bir yöntem çağrısı ve Future aracılığıyla sonuç döndürme ile istek-yanıt modelini uygular. EventChannel akış modelini kullanır: yerel taraf olaylar meydana geldikçe gönderir ve Dart bunları Stream aracılığıyla alır. MethodChannel, sonuç bekleyen tek seferlik işlemler için uygunken, EventChannel sürekli gerçek zamanlı veri akışları içindir.
Platform Channel temel Dart türlerini destekler: int, double, bool, String, List ve Map. Bu türler, geliştirici müdahalesi olmadan StandardMethodCodec ve StandardMessageCodec aracılığıyla otomatik olarak yerel eşdeğerlerine serileştirilir. Özel nesneleri iletmek için JSON'a manuel serileştirme veya standart olmayan biçimleri destekleyen özel bir MessageCodec kullanımı gerekir.
Evet, Flutter tek bir uygulamada sınırsız sayıda Platform Channel'ı destekler. Her kanal, Dart tarafı ve yerel platformda eşleşmesi gereken benzersiz bir dize adıyla tanımlanır. Farklı modüller için ayrı kanallar oluşturulabilir: biri kamera için, diğeri Bluetooth için, üçüncüsü sensörler için — hepsi bağımsız çalışır ve birbirlerinin performansını etkilemez.
Dart tarafında, hatalar bir istisna oluştuğunda yerel tarafın döndürdüğü PlatformException aracılığıyla ele alınır. Try-catch bloğu istisnayı yakalar ve hata koduna, mesajına ve ayrıntılarına erişim sağlar. Yerel tarafta, result.error çağrısı hatayı Dart'a geri gönderir. Kanal tarafından desteklenmeyen yöntemler için result.notImplemented yöntemi de mevcuttur.
Evet, Platform Channel işleyicisi yerel platformun ana iş parçacığında çalışır. İşleyici uzun süreli bir işlem (ağ isteği, disk okuma veya ağır hesaplama) gerçekleştirirse kullanıcı arayüzü donabilir. Yerel tarafta arka plan iş parçacığında ağır görevler çalıştırmanız ve yalnızca tamamlandıktan sonra result çağırmanız önerilir. invokeMethod'un asenkron yapısı nedeniyle Dart tarafı bloke olmaz.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.