פיתוח ערוצי פלטפורמה עבור Flutter ב-Android

כאשר תוספים סטנדרטיים אינם מספיקים לחומרה לא סטנדרטית או SDK קנייניים, Platform Channel בא להציל. אנחנו בונים גשרים natives בין Dart ל-Kotlin, ומספקים אינטגרציה מלאה - מניתוח API ועד יישום ותמיכה. הצוות שלנו מבטיח פעילות אמינה של הערוצים ותחזוקה שוטפת לאחר ההשקה.

פיתוח ותמיכה בכל סוגי היישומים הניידים:

יישומים ניידים למידע ובידור
אפליקציות חדשות, משחקים, מדריכים, קטלוגים מקוונים, אפליקציות מזג אוויר, אפליקציות כושר ובריאות, אפליקציות נסיעות, אפליקציות חינוכיות, רשתות חברתיות ומסנג'רים, חידונים, בלוגים ופודקאסטים, פורומים, אגרגטורים
יישומים ניידים למסחר אלקטרוני
חנויות מקוונות, אפליקציות B2B, מרקטפלייסים, בורסות מקוונות, שירותי קאשבק, בורסות, פלטפורמות דרופשיפינג, תוכניות נאמנות, משלוחי מזון ומוצרים, מערכות תשלום.
יישומים ניידים לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, ניהול פרויקטים, כלים לצוותי מכירות, ניהול פיננסי, ניהול ייצור, ניהול לוגיסטיקה ומשלוחים, ניהול משאבי אנוש, מערכות ניטור נתונים
יישומים ניידים לשירותים אלקטרוניים
פלטפורמות מודעות מסווגות, בתי ספר מקוונים, בתי קולנוע מקוונים, פלטפורמות שירות אלקטרוניות, פלטפורמות קאשבק, אירוח וידאו, פורטלים נושאיים, פלטפורמות הזמנות ותזמון מקוונות, פלטפורמות מסחר מקוונות

אלה הם רק חלק מסוגי היישומים הניידים שאנו עובדים איתם, ולכל אחד מהם עשויים להיות מאפיינים ופונקציונליות ספציפיים משלו, המותאמים לצרכים ולמטרות הספציפיות של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 1734 השירותים
פיתוח ערוצי פלטפורמה עבור Flutter ב-Android
מורכב
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית מובייל עבור FEEDME
    פיתוח אפליקציית מובייל עבור FEEDME
    971
  • פיתוח אפליקציית מובייל עבור XOOMER
    פיתוח אפליקציית מובייל עבור XOOMER
    869
  • פיתוח אפליקציית מובייל עבור RHL
    פיתוח אפליקציית מובייל עבור RHL
    1289
  • פיתוח אפליקציית מובייל עבור ZIPPY
    פיתוח אפליקציית מובייל עבור ZIPPY
    1143
  • פיתוח אפליקציית מובייל עבור Affhome
    פיתוח אפליקציית מובייל עבור Affhome
    1076
  • פיתוח אפליקציית מובייל עבור חברת FLAVORS
    פיתוח אפליקציית מובייל עבור חברת FLAVORS
    677

אתה מריץ אפליקציית 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 עם Java API, ואנחנו עוטפים אותו ב-Platform Channel.

איך לבחור בין MethodChannel ל-EventChannel?

הבחירה תלויה באופי הנתונים. MethodChannel מתאים לבקשות חד-פעמיות (RPC), EventChannel — לזרם רציף של אירועים. EventChannel נוח פי 2 לנתוני סטרימינג מאשר MethodChannel עם טיפול ידני בקריאות חוזרות. בואו נחקור את שתי האפשרויות.

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.company_name.app/module. שמות לא תואמים ב-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, השתמש ב-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'); } } כדי להירשם.

מה כלול בפיתוח Platform Channel?

כל הזמנה כוללת:

  • ניתוח תחום הדעת וחקר ה-SDK המקורי;
  • עיצוב ממשק הערוץ (מתודות, אירועים, סוגי נתונים);
  • יישום ב-Dart ובצד המקורי (Kotlin/Java);
  • כתיבת בדיקות יחידה ללוגיקת Kotlin;
  • בדיקות אינטגרציה של אפליקציית Flutter על מכשיר אמיתי;
  • תיעוד לכל מתודה ודוגמת שימוש;
  • מסירת קוד מקור, גישה למאגר, הוראות בנייה.

אנחנו מבטיחים שהערוץ לא יקרוס במהלך hot reload ולא יגרום ל-ANR. אנו מספקים תמיכה למשך 30 יום לאחר המסירה.

השוואת סוגי ערוצים

מאפיין MethodChannel EventChannel BasicMessageChannel
כיוון דו-כיווני Native→Dart בלבד דו-כיווני
סוג קריאה RPC (בקשה-תגובה) זרם אירועים הודעות שרירותיות
מתי להשתמש קריאות חד-פעמיות נתונים רציפים תקשורת ברמה נמוכה
מורכבות יישום נמוכה בינונית (מחזור חיים) בינונית

BasicMessageChannel משמש פחות — בדרך כלל כשצריך תקשורת דו-כיוונית ללא קשירת מתודות, למשל להעברת נתונים בינאריים בזמן אמת.

למה חשוב לבדוק Platform Channels

במהלך hot reload, Flutter רושם StreamHandler חדש, אבל הישן נשאר בזיכרון אם 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-чтения } } לא נקרא. כתוצאה מכך, נתונים מגיעים פעמיים — או שמצטברים דליפות זיכרון. לכן, תמיד נקה את ה-handler ביישום. בקוד שלנו למעלה, 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)) .

בדיקות יחידה לעומת בדיקות אינטגרציה

קריטריון בדיקות יחידה (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 של EventChannel('...').receiveBroadcastStream().map(...) נקרא על ה-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)
                }
            }
        }
    }
}

יש לקרוא ל-onDetachedFromEngine על ה-thread הראשי — זו דרישה של Flutter. SensorStreamHandler או onCancel הם חובה לתגובות מ-threadים ברקע. ב-95% מהמקרים, ANR לא מתרחש עם יישום נכון; 90% מהבקשות מעובדות תוך 1 ms.

קריאה ל-@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: ניתן לקרוא למתודות רק פעם אחת. אם הפעולה מבוטלת — קרא ל-MethodChannel.setMethodCallHandler או כלום (אבל אז צד ה-Dart יחכה לנצח). השיטה המומלצת: החזר שגיאה במפורש בעת ביטול.

איך אנחנו עושים את זה: מחסנית וניסיון

אנחנו כותבים Platform Channels ב-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 ימים. אריזה כתוסף לשימוש חוזר מוסיפה 1-2 ימים. העלות מחושבת באופן אישי לאחר ניתוח המשימה שלך. אנו מעריכים את הפרויקט תוך יום עסקים אחד.

תיעוד Flutter הרשמי: 'ערוצי פלטפורמה הם המפתח לתקשורת עם קוד מקורי.'

קבלו ייעוץ לפרויקט שלכם. צרו קשר כדי לדון בתרחיש שלכם – נשלח הצעה מסחרית ולוחות זמנים.