Interaksi antara kode Dart dan platform native adalah tugas utama dalam pengembangan aplikasi Flutter yang memerlukan akses ke kemampuan perangkat. Menurut Flutter Team, 2026, Platform Channel tetap menjadi mekanisme utama untuk integrasi semacam itu, menyediakan pengiriman pesan antara Dart dan kode native Android dan iOS tanpa melibatkan pustaka native tambahan.
Poin Penting
Platform Channel adalah teknologi Flutter yang menyediakan komunikasi dua arah antara kode Dart aplikasi dan kode native sistem operasi Android dan iOS. Tanpa Platform Channel, aplikasi Flutter terbatas pada kemampuan yang disediakan oleh framework dan tidak dapat mengakses langsung API kamera, sensor, Bluetooth, sistem file, dan fungsi perangkat tingkat rendah lainnya.
Arsitektur Platform Channel dibangun berdasarkan prinsip pertukaran pesan asinkron. Sisi Dart mengirimkan permintaan melalui saluran, sisi native memprosesnya dan mengembalikan hasil. Semua pesan diserialisasi ke format biner dan dikirim melalui buffer pesan Flutter Engine, yang memastikan latensi minimal saat mentransfer data antar lingkungan eksekusi.
Setiap Platform Channel diidentifikasi dengan nama logis unik — string yang berfungsi sebagai alamat untuk merutekan pesan. Sisi Dart dan sisi native harus menggunakan nama saluran yang sama agar komunikasi dapat terbentuk dengan benar. Flutter mendukung jumlah saluran berapa pun dalam satu aplikasi, dan setiap saluran bekerja secara independen dari yang lain.
Menurut dokumentasi resmi Flutter, Platform Channel memproses pesan dalam urutan yang sama seperti saat dikirim, yang menjamin prediktabilitas urutan panggilan. Ini sangat penting dalam skenario di mana urutan pemrosesan mempengaruhi kebenaran operasi, misalnya pada inisialisasi berurutan modul native atau rantai operasi dependen.
Mekanisme pengiriman pesan melalui Platform Channel terdiri dari tiga lapisan kunci: sisi Dart mengirimkan pesan dalam bentuk Map atau List melalui invokeMethod, Flutter Engine menserialisasinya menggunakan StandardMethodCodec, dan sisi native menerima panggilan di handler-nya. Hasilnya kembali melalui jalur yang sama ke arah sebaliknya.
Proses serialisasi secara otomatis mengonversi tipe data Dart ke padanannya di platform native. Angka, string, nilai boolean, daftar, dan kamus didukung tanpa konfigurasi tambahan dari pengembang. Tipe data kustom harus diserialisasi secara manual, misalnya ke string JSON, sebelum dikirim melalui saluran.
Di sisi Flutter Engine, pesan masuk ke antrian utas utama platform native. Di Android ini adalah utas utama aplikasi, di iOS — loop utama eksekusi. Ini berarti operasi yang lama di handler saluran akan memblokir antarmuka pengguna dan menyebabkan pembekuan. Pengembang disarankan untuk menjalankan tugas berat di utas latar belakang dan mengembalikan hasil secara asinkron melalui callback.
Kinerja Platform Channel cukup tinggi untuk sebagian besar skenario penggunaan: waktu pengiriman satu pesan kurang dari 1 milidetik pada perangkat modern. Namun, untuk operasi dengan beban tinggi, seperti pemrosesan streaming video real-time, disarankan menggunakan Dart FFI atau plugin native dengan akses langsung ke memori perangkat.
Keterbatasan utama arsitektur: Platform Channel tidak mendukung pengiriman deskriptor file, pointer memori, atau objek native. Semua data harus dapat diserialisasi ke format biner. Untuk mentransfer data dalam jumlah besar berukuran megabita, gunakan file sementara dengan pengiriman jalur file melalui saluran.
Flutter menyediakan tiga jenis Platform Channel, masing-masing ditujukan untuk skenario interaksi tertentu. Pemilihan jenis saluran yang tepat menentukan arsitektur integrasi dan kemudahan pemeliharaan kode di kedua sisi — Dart dan native, oleh karena itu penting untuk memahami perbedaan antara MethodChannel, EventChannel, dan BasicMessageChannel.
MethodChannel adalah jenis Platform Channel yang paling umum, menerapkan pola panggilan prosedur jarak jauh. Dart mengirimkan nama metode dan argumen, sisi native menjalankan operasi dan mengembalikan hasil. Setiap panggilan mengembalikan Future, memungkinkan penggunaan konstruksi async dan await dalam kode Dart untuk kerja asinkron yang nyaman.
Jenis saluran ini cocok untuk operasi tipe permintaan-respons: mendapatkan level baterai, membaca data sensor, melakukan perhitungan di sisi native, atau meminta data dari layanan sistem. MethodChannel mendukung tipe data standar melalui StandardMethodCodec, termasuk nilai null berkat dukungan Null safety di Dart modern.
Dalam proyek nyata, MethodChannel digunakan di sebagian besar plugin resmi Flutter. Misalnya, paket camera, battery, dan path_provider bekerja melalui jenis saluran ini, menyediakan akses ke API native tanpa perlu menulis kode integrasi sendiri untuk setiap platform.
EventChannel ditujukan untuk skenario di mana sisi native menghasilkan aliran peristiwa yang berkelanjutan dari waktu ke waktu. Data dikirim ke Dart melalui Stream, memungkinkan berlangganan pembaruan real-time. Contoh penggunaan tipikal: pembacaan akselerometer, koordinat GPS, perubahan status Bluetooth, dan notifikasi dari layanan sistem.
Berbeda dengan MethodChannel, EventChannel menggunakan model publikasi-langganan. Sisi native mengirimkan peristiwa saat terjadi, tanpa permintaan eksplisit dari kode Dart. Pelanggan di sisi Dart menerima setiap peristiwa dalam elemen stream terpisah dan dapat memfilter atau mentransformasi data yang diterima sebelum digunakan di antarmuka.
Saat menggunakan EventChannel, perlu mengelola langganan dan pembatalannya dengan benar. Setiap panggilan StreamSubscription harus dibatalkan setelah selesai bekerja dengan saluran untuk menghindari kebocoran memori di sisi native. Platform Flutter secara otomatis membatalkan stream saat widget dihancurkan, tetapi pengelolaan langganan secara eksplisit meningkatkan keandalan aplikasi dalam skenario jangka panjang.
BasicMessageChannel adalah jenis Platform Channel yang paling fleksibel, ditujukan untuk pertukaran pesan asinkron arbitrer. Berbeda dengan MethodChannel, di mana setiap pesan berisi nama metode dan argumen, BasicMessageChannel hanya mengirimkan muatan tanpa perutean bawaan. Pihak pengirim mengirimkan pesan, pihak penerima memprosesnya dan mengembalikan respons.
Jenis saluran ini berguna untuk protokol interaksi kustom, di mana struktur pesan dapat berubah secara dinamis tergantung pada status aplikasi. BasicMessageChannel secara default menggunakan StandardMessageCodec, tetapi mendukung penggantian dengan MessageCodec arbitrer untuk format serialisasi non-standar.
Dalam praktiknya, BasicMessageChannel lebih jarang digunakan daripada MethodChannel, karena memerlukan pemrosesan perutean pesan secara manual tanpa pola penamaan bawaan. Namun, ini sangat diperlukan saat integrasi dengan pustaka native yang mengharapkan format pesan tertentu, berbeda dari pola permintaan-respons standar yang diimplementasikan di MethodChannel.
Mari kita lihat implementasi praktis Platform Channel dengan contoh mendapatkan level baterai perangkat. Contoh ini mendemonstrasikan siklus kerja lengkap: deklarasi MethodChannel di sisi Dart, implementasi handler di Android dan iOS, serta penanganan kesalahan yang benar saat data tidak tersedia atau izin yang diperlukan tidak ada.
Di sisi Dart, dibuat instance MethodChannel dengan nama saluran string unik. Metode invokeMethod mengirimkan permintaan ke sisi native dan menunggu hasil dalam bentuk Future. Penanganan kesalahan dilakukan melalui penangkapan PlatformException, yang dikembalikan oleh sisi native saat terjadi pengecualian dalam proses pemrosesan permintaan.
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}';
}
}
}
Di sisi Android, handler didaftarkan di MainActivity melalui metode configureFlutterEngine. Di dalam setMethodCallHandler, nama metode yang masuk diperiksa, panggilan native ke BatteryManager dilakukan untuk mendapatkan level baterai, dan hasilnya dikembalikan melalui objek result. Untuk metode yang tidak didukung oleh saluran, result.notImplemented dipanggil.
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
)
}
}
Di platform iOS, handler didaftarkan di kelas AppDelegate melalui FlutterMethodChannel. Kode Swift menerima panggilan masuk, mengakses API sistem UIDevice untuk mendapatkan level baterai, dan mengembalikan hasil ke Flutter. Pemrosesan asinkron dengan weak self memungkinkan eksekusi permintaan tanpa risiko mempertahankan siklus referensi kuat di memori.
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 diperlukan dalam setiap kasus ketika aplikasi Flutter memerlukan akses ke kemampuan perangkat yang tidak diimplementasikan dalam paket standar. Pengembang harus membuat saluran sendiri saat integrasi dengan SDK native untuk kamera, biometrik, NFC, Bluetooth Low Energy, atau saat bekerja dengan sistem file di luar sandbox aplikasi.
Skenario tipikal pertama — penggunaan API native yang tidak memiliki akses langsung dari Dart. Ini mencakup layanan sistem Android dan iOS, sensor perangkat keras dengan protokol transfer data non-standar, notifikasi push dengan logika pemrosesan kustom, dan operasi kriptografi yang memerlukan Hardware Security Module untuk penyimpanan kunci yang aman.
Skenario kedua — integrasi kode native yang ada ke dalam proyek Flutter. Jika perusahaan telah mengembangkan pustaka native untuk Android atau iOS, Platform Channel memungkinkan penggunaan kembali tanpa mem-porting ke Dart. Ini mempercepat migrasi aplikasi hibrida ke Flutter dan mempertahankan investasi dalam kode native yang ada dan logika bisnis yang terakumulasi.
Skenario ketiga — publikasi plugin Flutter sendiri di pub.dev. Semua plugin populer menggunakan Platform Channel untuk menyediakan API yang seragam di Dart, yang di bawah tenda memanggil kode native setiap platform. Ini adalah pendekatan standar yang direkomendasikan oleh tim Flutter untuk membuat paket yang dapat digunakan kembali dengan dukungan untuk kedua platform mobile.
Saat memilih antara membuat Platform Channel sendiri dan menggunakan paket siap pakai dari pub.dev, disarankan untuk terlebih dahulu memeriksa ketersediaan solusi siap pakai. Paket camera, geolocator, shared_preferences, dan path_provider mencakup sebagian besar kebutuhan tipikal. Platform Channel sendiri hanya dibenarkan jika tidak ada paket yang sesuai atau jika diperlukan penyesuaian mendalam terhadap perilaku native yang tidak disediakan oleh solusi yang ada.
Pertanyaan Umum
MethodChannel mengimplementasikan pola permintaan-respons dengan satu kali panggilan metode dan pengembalian hasil melalui Future. EventChannel menggunakan model aliran: sisi native mengirimkan peristiwa saat terjadi, dan Dart menerimanya melalui Stream. MethodChannel cocok untuk operasi satu kali dengan harapan hasil, EventChannel — untuk aliran data berkelanjutan secara real-time.
Platform Channel mendukung tipe dasar Dart: int, double, bool, String, List, dan Map. Tipe-tipe ini secara otomatis diserialisasi ke padanan native melalui StandardMethodCodec dan StandardMessageCodec tanpa partisipasi pengembang. Untuk mengirim objek kustom, diperlukan serialisasi manual ke JSON atau penggunaan MessageCodec arbitrer dengan dukungan format non-standar.
Ya, Flutter mendukung jumlah tidak terbatas Platform Channel dalam satu aplikasi. Setiap saluran diidentifikasi dengan nama string unik yang harus cocok di sisi Dart dan platform native. Saluran terpisah dapat dibuat untuk modul yang berbeda: satu untuk kamera, satu lagi untuk Bluetooth, yang ketiga untuk sensor — semuanya bekerja secara independen dan tidak mempengaruhi kinerja satu sama lain.
Di sisi Dart, kesalahan ditangani melalui PlatformException, yang dikembalikan oleh sisi native saat terjadi pengecualian. Blok try-catch menangkap pengecualian dan menyediakan akses ke kode, pesan, dan detail kesalahan. Di sisi native, panggilan result.error mengirimkan kesalahan kembali ke Dart. Juga tersedia metode result.notImplemented untuk metode yang tidak didukung oleh saluran.
Ya, handler Platform Channel dieksekusi pada utas utama platform native. Jika handler menjalankan operasi yang lama — permintaan jaringan, pembacaan dari disk, atau perhitungan berat — antarmuka pengguna dapat membeku. Disarankan untuk menjalankan tugas berat di utas latar belakang di sisi native dan memanggil result hanya setelah selesai. Sisi Dart sementara itu tidak diblokir berkat sifat asinkron dari invokeMethod.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.