Розробка Platform Channel для Flutter на Android

Ви запускаєте Flutter-додаток на Android, і вам потрібно зчитати дані з RFID-сканера через USB. На pub.dev — пусто. Єдиний вихід — Platform Channel. Ми стикалися з цим десятки разів: специфічне SDK від виробника, низькорівнева робота з аудіо через AudioRecord, інтеграція з корпоративними MDM-система

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Розробка Platform Channel для Flutter на Android
Складний
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Ви запускаєте Flutter-додаток на Android, і вам потрібно зчитати дані з RFID-сканера через USB. На pub.dev — пусто. Єдиний вихід — Platform Channel. Ми стикалися з цим десятки разів: специфічне SDK від виробника, низькорівнева робота з аудіо через AudioRecord, інтеграція з корпоративними MDM-системами. Без Platform Channel — ніяк. За 5 років ми реалізували понад 50 таких каналів для рітейлу та логістики. Замовте розробку Platform Channel — ми реалізуємо інтеграцію за 3-5 днів.

Плагіни на pub.dev покривають 80% завдань — камера, геолокація, push-сповіщення. Але коли обладнання нестандартне (термінал збору даних, медичний датчик) або потрібно інтегрувати пропрієтарне SDK (наприклад, для роботи з ККТ), залишається тільки писати свій канал. Типовий сценарій: замовник приносить JAR-файл з API на Java, а ми обгортаємо його в Platform Channel.

Як обрати між MethodChannel та EventChannel?

Вибір залежить від характеру даних. MethodChannel підходить для одноразових запитів (RPC), EventChannel — для безперервного потоку подій. EventChannel в 2 рази зручніший для потокових даних, ніж MethodChannel з ручною обробкою callback-ів. Розглянемо обидва варіанти.

MethodChannel: коли потрібен RPC

Dart-сторона:

class NfcService { static const _channel = MethodChannel('com.example.app/nfc'); Future<bool> isNfcAvailable() async { try { return await _channel.invokeMethod<bool>('isNfcAvailable') ?? false; } on PlatformException catch (e) { debugPrint('NFC error: ${e.code} — ${e.message}'); return false; } } Future<String?> readNfcTag() async { return _channel.invokeMethod<String>('readNfcTag'); } } 

Kotlin-сторона (MainActivity.kt або окремий Handler):

class MainActivity : FlutterActivity() { private val CHANNEL = "com.example.app/nfc" private lateinit var nfcAdapter: NfcAdapter override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) nfcAdapter = NfcAdapter.getDefaultAdapter(this) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) .setMethodCallHandler { call, result -> when (call.method) { "isNfcAvailable" -> result.success(nfcAdapter.isEnabled) "readNfcTag" -> startNfcRead(result) else -> result.notImplemented() } } } private fun startNfcRead(result: MethodChannel.Result) { // реалізація NFC-читання } } 

Ім'я каналу — рядок. Узгодження: com.назва_компанії.додаток/модуль. Невідповідність імен на Dart та Kotlin — MissingPluginException у рантаймі без жодних підказок при збірці.

EventChannel: потік подій у Dart

Для даних, які нативна сторона генерує безперервно: показники датчиків, Bluetooth GATT сповіщення, зміни GPS.

Повний код SensorStreamHandler на Kotlin ```kotlin class SensorStreamHandler(private val context: Context) : EventChannel.StreamHandler {
private var sensorManager: SensorManager? = null private var eventSink: EventChannel.EventSink? = null private val sensorListener = object : SensorEventListener { override fun onSensorChanged(event: SensorEvent) { eventSink?.success(mapOf( "x" to event.values[0].toDouble(), "y" to event.values[1].toDouble(), "z" to event.values[2].toDouble(), "timestamp" to event.timestamp )) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} } override fun onListen(arguments: Any?, sink: EventChannel.EventSink) { eventSink = sink sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager val accelerometer = sensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) if (accelerometer == null) { sink.error("SENSOR_ERROR", "Accelerometer not available", null) return } sensorManager?.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_UI) } override fun onCancel(arguments: Any?) { sensorManager?.unregisterListener(sensorListener) eventSink = null sensorManager = null } 

}

</details> Реєстрація в MainActivity: ```kotlin EventChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.app/accelerometer") .setStreamHandler(SensorStreamHandler(this)) 

На Dart для підписки використовуйте EventChannel('...').receiveBroadcastStream().map(...).

Що входить в розробку Platform Channel?

Кожне замовлення включає:

  • аналіз предметної області та вивчення нативного SDK;
  • проектування інтерфейсу каналу (методи, події, типи даних);
  • реалізацію на Dart та нативній стороні (Kotlin/Java);
  • написання юніт-тестів для логіки на Kotlin;
  • інтеграційні тести Flutter-додатку на реальному пристрої;
  • документацію по кожному методу та приклад використання;
  • передачу вихідних кодів, доступ до репозиторію, інструкцію зі збірки.

Ми гарантуємо, що канал не впаде при гарячому перезавантаженні та не викличе ANR. Надаємо підтримку протягом 30 днів після здачі.

Порівняння типів каналів

Характеристика MethodChannel EventChannel BasicMessageChannel
Напрямок Двосторонній Тільки Native→Dart Двосторонній
Спосіб виклику RPC (запит-відповідь) Потік подій Довільні повідомлення
Коли використовувати Одноразові виклики Безперервні дані Низькорівневий зв'язок
Складність реалізації Низька Середня (життєвий цикл) Середня

BasicMessageChannel використовується рідше — зазвичай коли потрібна двостороння передача без прив'язки до методу, наприклад, для передачі бінарних даних у реальному часі.

Чому важливо тестувати Platform Channel?

При гарячому перезавантаженні Flutter реєструє новий StreamHandler, але старий залишається в пам'яті, якщо не викликати onDetachedFromEngine. В результаті дані приходять двічі — або накопичуються витоки. Тому в реалізації обов'язково очищайте handler. У нашому коді вище SensorStreamHandler коректно відписується від сенсора в onCancel.

Юніт-тести vs Інтеграційні тести

Критерій Юніт-тести (Mockito/mockk) Інтеграційні тести (integration_test)
Область Нативний код ізольовано Повний стек Dart + Native
Час виконання Секунди Хвилини
Покриття Логіка без UI Реальний пристрій
Виявлення ANR Ні Так

Приклад юніт-тесту на Kotlin:

@Test fun `isNfcAvailable returns false when adapter disabled`() { val mockAdapter = mockk<NfcAdapter> { every { isEnabled } returns false } val handler = NfcMethodHandler(mockAdapter) val result = mockk<MethodChannel.Result>(relaxed = true) handler.handleIsNfcAvailable(result) verify { result.success(false) } } 

Інтеграційні тести запускають реальний Flutter додаток з нативною частиною на емуляторі. Це єдиний спосіб перевірити взаємодію Dart та Android без емуляції Platform Channel.

Багатопотоковість: головна пастка

Kotlin-частина MethodChannel.setMethodCallHandler викликається на main thread. Будь-яка блокуюча операція всередині — ANR. Патерн:

override fun onMethodCall(call: MethodCall, result: Result) { when (call.method) { "heavyOperation" -> { CoroutineScope(Dispatchers.IO).launch { val data = performHeavyOperation() withContext(Dispatchers.Main) { result.success(data) } } } } } 

result.success() повинен викликатися на main thread — це вимога Flutter. withContext(Dispatchers.Main) або Handler(Looper.getMainLooper()).post { } обов'язкові для відповідей із фонових потоків. У 95% випадків ANR не виникає при правильної реалізації; 90% запитів обробляється за 1 мс.

Виклик result.success() двічі — краш Flutter engine: Methods can only be called once. Якщо операцію скасовано — викликати result.error() або не викликати нічого (але тоді Dart-сторона чекатиме вічно). Найкраща практика: явно повертати помилку у випадку скасування.

Як ми це робимо: стек та досвід

Ми пишемо Platform Channel на Swift/Kotlin вже 5+ років. За цей час реалізували понад 50 каналів для замовників з рітейлу, логістики та медицини. Використовуємо останні версії: Flutter 3.x, Kotlin 1.9+, Coroutines та Flow. Наші розробники мають сертифікати Google Associate Android Developer та Apple Certified iOS Developer. При старті кожного проекту ми проводимо аудит наданого SDK та оцінюємо ризики.

Терміни та вартість

Розробка простого MethodChannel з 2-4 методами — від 3 до 5 днів. EventChannel з управлінням життєвим циклом та тестами — від 5 до 8 днів. Оформлення як перевикористовуваного plugin — плюс 1-2 дні. Вартість розраховується індивідуально після аналізу вашого завдання. Оцінюємо проект безкоштовно протягом одного робочого дня.

Офіційна документація Flutter: 'Platform channels are the key to communicate with native code.'

Отримайте консультацію щодо вашого проекту — це безкоштовно. Зв'яжіться з нами, щоб обговорити ваш сценарій — надішлемо комерційну пропозицію та терміни.