feat: add platform channel bridge between Flutter and Android

This commit is contained in:
fiatcode 2026-04-30 11:14:27 +07:00
parent d1b7948723
commit 45da511f87
No known key found for this signature in database
3 changed files with 141 additions and 0 deletions

View file

@ -0,0 +1,71 @@
package com.traccar.traccar_client
import android.content.Context
import com.traccar.traccar_client.service.LocationTrackingService
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
private lateinit var methodChannel: MethodChannel
private lateinit var eventChannel: EventChannel
private var context: Context? = null
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
context = binding.applicationContext
methodChannel = MethodChannel(binding.binaryMessenger, "com.traccar.client/tracking")
methodChannel.setMethodCallHandler(this)
eventChannel = EventChannel(binding.binaryMessenger, "com.traccar.client/location_updates")
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
methodChannel.setMethodCallHandler(null)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"startTracking" -> {
startTrackingService()
result.success(true)
}
"stopTracking" -> {
stopTrackingService()
result.success(true)
}
"updateConfig" -> {
val config = call.arguments as? Map<*, *>
updateTrackingConfig(config)
result.success(true)
}
"getStatus" -> {
result.success(mapOf(
"isTracking" to false,
"lastLatitude" to 0.0,
"lastLongitude" to 0.0
))
}
else -> result.notImplemented()
}
}
private fun startTrackingService() {
val intent = android.content.Intent(context, LocationTrackingService::class.java).apply {
action = LocationTrackingService.ACTION_START
}
context?.startForegroundService(intent)
}
private fun stopTrackingService() {
val intent = android.content.Intent(context, LocationTrackingService::class.java).apply {
action = LocationTrackingService.ACTION_STOP
}
context?.startService(intent)
}
private fun updateTrackingConfig(config: Map<*, *>?) {
}
}

View file

@ -0,0 +1,11 @@
package com.traccar.traccar_client
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine.plugins.add(BridgeModule())
}
}

View file

@ -0,0 +1,59 @@
import 'dart:async';
import 'package:flutter/services.dart';
class LocationBridge {
static const MethodChannel _methodChannel =
MethodChannel('com.traccar.client/tracking');
static const EventChannel _eventChannel =
EventChannel('com.traccar.client/location_updates');
static Stream<Map<String, dynamic>>? _locationStream;
static Future<bool> startTracking() async {
try {
final result = await _methodChannel.invokeMethod<bool>('startTracking');
return result ?? false;
} on PlatformException catch (e) {
print('Failed to start tracking: ${e.message}');
return false;
}
}
static Future<bool> stopTracking() async {
try {
final result = await _methodChannel.invokeMethod<bool>('stopTracking');
return result ?? false;
} on PlatformException catch (e) {
print('Failed to stop tracking: ${e.message}');
return false;
}
}
static Future<bool> updateConfig(Map<String, dynamic> config) async {
try {
final result =
await _methodChannel.invokeMethod<bool>('updateConfig', config);
return result ?? false;
} on PlatformException catch (e) {
print('Failed to update config: ${e.message}');
return false;
}
}
static Future<Map<String, dynamic>?> getStatus() async {
try {
final result = await _methodChannel.invokeMethod<Map>('getStatus');
return result?.cast<String, dynamic>();
} on PlatformException catch (e) {
print('Failed to get status: ${e.message}');
return null;
}
}
static Stream<Map<String, dynamic>> get locationUpdates {
_locationStream ??= _eventChannel
.receiveBroadcastStream()
.map((event) => Map<String, dynamic>.from(event as Map));
return _locationStream!;
}
}