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

Когда стандартные плагины не справляются с нестандартным оборудованием или проприетарным SDK, на помощь приходит Platform Channel. Мы разрабатываем нативные мосты между Dart и Kotlin, реализуя интеграцию под ключ — от анализа API до внедрения и поддержки. Наша команда обеспечивает надёжную работу канала и его сопровождение после запуска.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

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

Вы запускаете 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-приложения на реальном устройстве;
  • документацию по каждому методу и пример использования;
  • передачу исходников, access к репозиторию, инструкцию по сборке.

Мы гарантируем, что канал не упадёт при горячей перезагрузке и не вызовет 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.'

Получите консультацию по вашему проекту. Свяжитесь с нами, чтобы обсудить ваш сценарий — пришлём коммерческое предложение и сроки.

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

Последние работы

  • Разработка мобильного приложения для компании FEEDME
    Разработка мобильного приложения для компании FEEDME
    1009
  • Разработка мобильного приложения для компании XOOMER
    Разработка мобильного приложения для компании XOOMER
    902
  • Разработка мобильного приложения для компании RHL
    Разработка мобильного приложения для компании RHL
    1331
  • Разработка мобильного приложения для компании ZIPPY
    Разработка мобильного приложения для компании ZIPPY
    1179
  • Разработка мобильного приложения для компании Affhome
    Разработка мобильного приложения для компании Affhome
    1106
  • Разработка мобильного приложения для компании FLAVORS
    Разработка мобильного приложения для компании FLAVORS
    713