Browse Source

[feat]键盘插件,实现默认键盘切换事件,通过EventChannel发送事件给Flutter端

hezihao 7 months ago
parent
commit
e5b6890d8d
21 changed files with 423 additions and 32 deletions
  1. 22 8
      lib/module/keyboard_guide/keyboard_guide_controller.dart
  2. 5 2
      lib/module/keyboard_guide/keyboard_guide_page.dart
  3. 62 0
      lib/plugins/default_keyboard_change_listener.dart
  4. 17 2
      lib/plugins/keyboard_android_platform.dart
  5. 4 0
      lib/plugins/keyboard_android_service.dart
  6. 9 0
      lib/plugins/plugin_constant.dart
  7. 8 7
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/KeyboardAndroidPlugin.kt
  8. 7 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/constant/PluginConfig.kt
  9. 32 7
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/KeyboardWatcher.kt
  10. 18 3
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/FlutterBridgeManager.kt
  11. 2 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/IBridgeApi.kt
  12. 11 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/api/KeyboardEventApi.kt
  13. 25 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/callback/NativeEventEmitter.kt
  14. 27 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/callback/NativeEventHandler.kt
  15. 58 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/event/DefaultKeyboardNativeEventHandler.kt
  16. 88 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/util/NativeEventRegistry.kt
  17. 8 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/util/NativeMethodRegistry.kt
  18. 4 0
      plugins/keyboard_android/lib/keyboard_android.dart
  19. 5 0
      plugins/keyboard_android/lib/keyboard_android_method_channel.dart
  20. 6 0
      plugins/keyboard_android/lib/keyboard_android_platform_interface.dart
  21. 5 0
      plugins/keyboard_android/test/keyboard_android_test.dart

+ 22 - 8
lib/module/keyboard_guide/keyboard_guide_controller.dart

@@ -6,6 +6,7 @@ import 'package:keyboard/resource/string.gen.dart';
 
 import '../../base/base_controller.dart';
 import '../../data/bean/keyboard_guide_msg.dart';
+import '../../plugins/default_keyboard_change_listener.dart';
 import '../../plugins/keyboard_android_platform.dart';
 import '../../utils/keyboard_guide_record_util.dart';
 import '../../utils/toast_util.dart';
@@ -32,8 +33,8 @@ class KeyboardGuidePageController extends BaseController {
   /// 消息列表
   final RxList<KeyboardGuideMsg> msgList = <KeyboardGuideMsg>[].obs;
 
-  /// 是否选择了键盘
-  final Rx<bool> isChooseKeyboard = false.obs;
+  /// 是否选择默认键盘
+  final Rx<bool> isChooseDefaultKeyboard = false.obs;
 
   @override
   void onInit() {
@@ -43,7 +44,7 @@ class KeyboardGuidePageController extends BaseController {
     _initMsgList();
     // 进入页面,就获取输入框焦点
     // inputFocusNode.requestFocus();
-    checkKeyboardEnable();
+    _registerDefaultKeyboardChangeEvent();
   }
 
   @override
@@ -53,14 +54,27 @@ class KeyboardGuidePageController extends BaseController {
     inputFocusNode.dispose();
     editingController.dispose();
     scrollController.dispose();
+    _unRegisterDefaultKeyboardChangeEvent();
     super.onClose();
   }
 
-  /// 检查键盘是否已启用
-  void checkKeyboardEnable() {
-    KeyboardAndroidPlatform.isTargetKeyboardEnabled().then((enable) {
-      isChooseKeyboard.value = enable;
-    });
+  /// 监听默认键盘切换事件
+  void _registerDefaultKeyboardChangeEvent() {
+    DefaultKeyboardMonitor.registerDefaultKeyboardChangeEvent(
+      handleDefaultKeyboardChange,
+    );
+  }
+
+  /// 取消监听默认键盘切换事件
+  void _unRegisterDefaultKeyboardChangeEvent() {
+    DefaultKeyboardMonitor.unRegisterDefaultKeyboardChangeEvent(
+      handleDefaultKeyboardChange,
+    );
+  }
+
+  /// 处理默认键盘切换
+  void handleDefaultKeyboardChange(bool isDefaultKeyboard) {
+    isChooseDefaultKeyboard.value = isDefaultKeyboard;
   }
 
   /// 关闭页面

+ 5 - 2
lib/module/keyboard_guide/keyboard_guide_page.dart

@@ -42,7 +42,10 @@ class KeyboardGuidePage extends BasePage<KeyboardGuidePageController> {
       backgroundColor: backgroundColor(),
       body: DelegateLifecycleWidget(
         onCreateCallback: () {
-          controller.showGuideOverlayDialog();
+          // 选择为默认键盘,则尝试显示引导弹窗
+          if (controller.isChooseDefaultKeyboard.value) {
+            controller.showGuideOverlayDialog();
+          }
         },
         child: Column(
           children: [
@@ -127,7 +130,7 @@ class KeyboardGuidePage extends BasePage<KeyboardGuidePageController> {
   Widget _buildContent() {
     return Obx(() {
       // 键盘已启用,显示聊天列表
-      if (controller.isChooseKeyboard.value) {
+      if (controller.isChooseDefaultKeyboard.value) {
         return _buildChatList();
       } else {
         // 未启用,显示引导动画

+ 62 - 0
lib/plugins/default_keyboard_change_listener.dart

@@ -0,0 +1,62 @@
+import 'dart:async';
+
+import 'package:flutter/services.dart';
+import 'package:keyboard/plugins/plugin_constant.dart';
+
+/// 默认键盘切换回调
+typedef DefaultKeyboardChangeListenerCallback =
+    void Function(bool isDefaultKeyboard);
+
+/// 默认键盘改变事件监听器
+class DefaultKeyboardMonitor {
+  /// 事件通道
+  static const EventChannel _eventChannel = EventChannel(
+    PluginConstant.flutterDefaultKeyboardEventChannelName,
+  );
+
+  /// 监听器列表
+  static final List<DefaultKeyboardChangeListenerCallback> _listenerList =
+      <DefaultKeyboardChangeListenerCallback>[];
+
+  /// 订阅事件流
+  static StreamSubscription? _streamSubscription;
+
+  /// 初始化
+  static init() {
+    _streamSubscription = _eventChannel.receiveBroadcastStream().listen(
+      (dynamic event) {
+        bool isDefaultKeyboard = event as bool;
+        // 切换事件,true为当前键盘为默认键盘,false为不是默认键盘
+        for (var listener in _listenerList) {
+          listener(isDefaultKeyboard);
+        }
+      },
+      onError: (dynamic error) {},
+      cancelOnError: true,
+    );
+  }
+
+  /// 解初始化
+  static unInit() {
+    if (_streamSubscription != null) {
+      _streamSubscription!.cancel();
+      _streamSubscription = null;
+    }
+  }
+
+  /// 注册默认键盘改变事件监听器
+  static void registerDefaultKeyboardChangeEvent(
+    DefaultKeyboardChangeListenerCallback callback,
+  ) {
+    if (!_listenerList.contains(callback)) {
+      _listenerList.add(callback);
+    }
+  }
+
+  /// 注销默认键盘改变事件监听器
+  static void unRegisterDefaultKeyboardChangeEvent(
+    DefaultKeyboardChangeListenerCallback callback,
+  ) {
+    _listenerList.remove(callback);
+  }
+}

+ 17 - 2
lib/plugins/keyboard_android_platform.dart

@@ -1,23 +1,32 @@
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
+import 'package:keyboard/plugins/plugin_constant.dart';
 import 'package:keyboard/utils/atmob_log.dart';
 
+import 'default_keyboard_change_listener.dart';
 import 'keyboard_android_service.dart';
 import 'keyboard_method_handler.dart';
 
 class KeyboardAndroidPlatform {
   KeyboardAndroidPlatform._();
 
-  static const MethodChannel _channel = MethodChannel('keyboard_android');
+  static const MethodChannel _channel = MethodChannel(
+    PluginConstant.flutterMethodChannelName,
+  );
   static const String _tag = 'KeyboardAndroidPlatform';
 
   static final KeyboardAndroidService _keyboardAndroidService =
       KeyboardAndroidService();
   static final KeyboardMethodHandler _methodHandler = KeyboardMethodHandler();
 
-  static void init() {
+  static void init() async {
     AtmobLog.d(_tag, '初始化 KeyboardAndroidPlatform ');
     _channel.setMethodCallHandler(_methodHandler.handleMethodCall);
+
+    // 通知插件初始化
+    await initPlugin();
+    // 默认键盘切换监听器
+    DefaultKeyboardMonitor.init();
   }
 
   static Future<void> sendDynamicTextRequest(
@@ -34,6 +43,12 @@ class KeyboardAndroidPlatform {
     }
   }
 
+  /// 初始化插件
+  static Future<void> initPlugin() async {
+    debugPrint('initPlugin');
+    return _keyboardAndroidService.initPlugin();
+  }
+
   /// 打开/关闭悬浮窗
   static void enableFloatingWindow(bool enable) {
     debugPrint('enableFloatingWindow $enable');

+ 4 - 0
lib/plugins/keyboard_android_service.dart

@@ -3,6 +3,10 @@ import 'package:keyboard_android/keyboard_android.dart';
 class KeyboardAndroidService {
   final _plugin = KeyboardAndroid();
 
+  Future<void> initPlugin() async {
+    await _plugin.initPlugin();
+  }
+
   void enableFloatingWindow(bool enable) {
     _plugin.enableFloatingWindow(enable);
   }

+ 9 - 0
lib/plugins/plugin_constant.dart

@@ -0,0 +1,9 @@
+/// 插件常量
+class PluginConstant {
+  /// MethodChannel通道名称,和Flutter端要一一对应
+  static const flutterMethodChannelName = "keyboard_android";
+
+  /// 默认键盘改变事件,EventChannel通道名称
+  static const flutterDefaultKeyboardEventChannelName =
+      "keyboard_android/event/default_keyboard";
+}

+ 8 - 7
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/KeyboardAndroidPlugin.kt

@@ -9,8 +9,8 @@ import com.atmob.keyboard_android.component.listener.ComponentUpdateLoggingListe
 import com.atmob.keyboard_android.floating.FloatingButtonService
 import com.atmob.keyboard_android.util.FloatingWindowUtil
 import com.atmob.keyboard_android.util.InputMethodUtil
-import com.atmob.keyboard_android.util.KeyboardWatcher
 import com.atmob.keyboard_android.util.LogUtil
+import com.atmob.keyboard_android.util.bridge.FlutterBridgeManager
 import io.flutter.embedding.engine.plugins.FlutterPlugin
 import io.flutter.plugin.common.MethodCall
 import io.flutter.plugin.common.MethodChannel
@@ -48,9 +48,6 @@ class KeyboardAndroidPlugin : FlutterPlugin, MethodCallHandler {
         channel = MethodChannel(flutterPluginBinding.binaryMessenger, "keyboard_android")
         channel.setMethodCallHandler(this)
 
-        // 注册键盘切换监听
-        KeyboardWatcher.init()
-
         LogUtil.d("KeyboardAndroidPlugin 初始化")
     }
 
@@ -61,6 +58,13 @@ class KeyboardAndroidPlugin : FlutterPlugin, MethodCallHandler {
                 result.success("Android ${Build.VERSION.RELEASE}")
             }
 
+            // 初始化插件
+            "initPlugin" -> {
+                // 注册键盘切换监听
+                FlutterBridgeManager.registerDefaultKeyboardChangeEvent()
+                result.success(null)
+            }
+
             // 开启或关闭悬浮窗
             "enableFloatingWindow" -> {
                 val enable = call.argument<Boolean>("enable") == true
@@ -109,9 +113,6 @@ class KeyboardAndroidPlugin : FlutterPlugin, MethodCallHandler {
     }
 
     override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
-        // 注销键盘切换监听
-        KeyboardWatcher.unInit()
-
         channel.setMethodCallHandler(null)
     }
 }

+ 7 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/constant/PluginConfig.kt

@@ -11,8 +11,14 @@ interface PluginConfig {
         const val FLUTTER_ENGINE_ID = "my_engine_id"
 
         /**
-         * 通道名称,和Flutter端要一一对应
+         * MethodChannel通道名称,和Flutter端要一一对应
          */
         const val FLUTTER_METHOD_CHANNEL_NAME = "keyboard_android"
+
+        /**
+         * 默认键盘改变事件,EventChannel通道名称
+         */
+        const val FLUTTER_DEFAULT_KEYBOARD_EVENT_CHANNEL_NAME =
+            "keyboard_android/event/default_keyboard"
     }
 }

+ 32 - 7
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/KeyboardWatcher.kt

@@ -9,16 +9,21 @@ import java.util.concurrent.CopyOnWriteArrayList
 
 
 /**
- * 键盘监听器
+ * 默认键盘切换监听器
  */
 @SuppressLint("StaticFieldLeak")
-object KeyboardWatcher {
+object DefaultKeyboardWatcher {
+    /**
+     * 是否初始化了
+     */
+    private var isInited = false
+
     private val mContext = ContextUtil.getContext()
 
     /**
      * 监听器列表
      */
-    private val mListenerList = CopyOnWriteArrayList<OnKeyboardChangeListener>()
+    private val mListenerList = CopyOnWriteArrayList<OnDefaultKeyboardChangeListener>()
 
     /**
      * 初始化,注册监听
@@ -26,6 +31,7 @@ object KeyboardWatcher {
     fun init() {
         val filter = IntentFilter(Intent.ACTION_INPUT_METHOD_CHANGED)
         mContext.registerReceiver(mImeChangeReceiver, filter)
+        isInited = true
     }
 
     /**
@@ -33,13 +39,26 @@ object KeyboardWatcher {
      */
     fun unInit() {
         mContext.unregisterReceiver(mImeChangeReceiver)
+        isInited = false
+    }
+
+    /**
+     * 是否初始化了
+     */
+    fun isInited(): Boolean {
+        return isInited
     }
 
-    interface OnKeyboardChangeListener {
+    interface OnDefaultKeyboardChangeListener {
         /**
-         * 当前键盘,被设置为默认键盘
+         * 当前键盘,被设置为默认键盘时回调
          */
         fun onDefaultKeyboard()
+
+        /**
+         * 当前键盘,非默认键盘时回调
+         */
+        fun onNotDefaultKeyboard()
     }
 
     /**
@@ -48,10 +67,16 @@ object KeyboardWatcher {
     private val mImeChangeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
         override fun onReceive(context: Context?, intent: Intent) {
             if (Intent.ACTION_INPUT_METHOD_CHANGED == intent.action) {
+                // 当前键盘,被设置为默认键盘
                 if (InputMethodUtil.isDefaultKeyboard(mContext)) {
                     for (listener in mListenerList) {
                         listener.onDefaultKeyboard()
                     }
+                } else {
+                    // 当前键盘,非默认键盘
+                    for (listener in mListenerList) {
+                        listener.onNotDefaultKeyboard()
+                    }
                 }
             }
         }
@@ -60,7 +85,7 @@ object KeyboardWatcher {
     /**
      * 注册监听器
      */
-    fun registerListener(listener: OnKeyboardChangeListener) {
+    fun registerListener(listener: OnDefaultKeyboardChangeListener) {
         if (!mListenerList.contains(listener)) {
             mListenerList.add(listener)
         }
@@ -69,7 +94,7 @@ object KeyboardWatcher {
     /**
      *
      */
-    fun unRegisterListener(listener: OnKeyboardChangeListener) {
+    fun unRegisterListener(listener: OnDefaultKeyboardChangeListener) {
         mListenerList.remove(listener);
     }
 }

+ 18 - 3
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/FlutterBridgeManager.kt

@@ -4,6 +4,7 @@ import com.atmob.keyboard_android.constant.FlutterHostConstants
 import com.atmob.keyboard_android.constant.PluginConfig
 import com.atmob.keyboard_android.enums.FlutterMethod
 import com.atmob.keyboard_android.util.FlutterPageLaunchUtil
+import com.atmob.keyboard_android.util.bridge.event.DefaultKeyboardNativeEventHandler
 import com.atmob.keyboard_android.util.bridge.model.base.EmptyResp
 import com.atmob.keyboard_android.util.bridge.model.req.SuperReplyReq
 import com.atmob.keyboard_android.util.bridge.model.req.SuperSpeakReq
@@ -15,7 +16,7 @@ import com.atmob.keyboard_android.util.bridge.model.resp.PrologueResp
 import com.atmob.keyboard_android.util.bridge.model.resp.SuperReplyResp
 import com.atmob.keyboard_android.util.bridge.model.resp.SuperSpeakResp
 import com.atmob.keyboard_android.util.bridge.util.FlutterMethodCaller
-import com.atmob.keyboard_android.util.bridge.util.NativeMethodRegistry
+import com.atmob.keyboard_android.util.bridge.util.NativeEventRegistry
 import io.flutter.embedding.engine.FlutterEngineCache
 
 /**
@@ -30,7 +31,12 @@ object FlutterBridgeManager : IBridgeApi {
     /**
      * 暴露原生方法给Flutter调用
      */
-    private val mNativeMethodRegistry = NativeMethodRegistry()
+    // private val mNativeMethodRegistry = NativeMethodRegistry()
+
+    /**
+     * 暴露原生事件给Flutter接收
+     */
+    private val mNativeEventRegistry = NativeEventRegistry()
 
     init {
         val flutterEngine = FlutterEngineCache.getInstance().get(PluginConfig.FLUTTER_ENGINE_ID)
@@ -38,7 +44,8 @@ object FlutterBridgeManager : IBridgeApi {
             throw IllegalArgumentException("FlutterEngine 未找到,MethodChannel 无法初始化")
         }
         mFlutterMethodCaller.init(flutterEngine)
-        mNativeMethodRegistry.init(flutterEngine)
+        // mNativeMethodRegistry.init(flutterEngine)
+        mNativeEventRegistry.init(flutterEngine)
     }
 
     override fun isLogin(onSuccess: (Boolean) -> Unit, onFail: (String) -> Unit) {
@@ -197,4 +204,12 @@ object FlutterBridgeManager : IBridgeApi {
             onFail = onFail
         )
     }
+
+    override fun registerDefaultKeyboardChangeEvent() {
+        val eventChannelHandler = DefaultKeyboardNativeEventHandler()
+        mNativeEventRegistry.registerNativeEvent(
+            eventChannelHandler.onGetEventChannelName(),
+            eventChannelHandler
+        )
+    }
 }

+ 2 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/IBridgeApi.kt

@@ -2,10 +2,11 @@ package com.atmob.keyboard_android.util.bridge
 
 import com.atmob.keyboard_android.util.bridge.api.AiChatApi
 import com.atmob.keyboard_android.util.bridge.api.KeyboardApi
+import com.atmob.keyboard_android.util.bridge.api.KeyboardEventApi
 import com.atmob.keyboard_android.util.bridge.api.RouteJumpApi
 import com.atmob.keyboard_android.util.bridge.api.UserApi
 
 /**
  * 定义桥接交互API
  */
-interface IBridgeApi : UserApi, RouteJumpApi, KeyboardApi, AiChatApi
+interface IBridgeApi : UserApi, RouteJumpApi, KeyboardApi, AiChatApi, KeyboardEventApi

+ 11 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/api/KeyboardEventApi.kt

@@ -0,0 +1,11 @@
+package com.atmob.keyboard_android.util.bridge.api
+
+/**
+ * 键盘事件相关Api
+ */
+interface KeyboardEventApi {
+    /**
+     * 注册默认键盘切换事件
+     */
+    fun registerDefaultKeyboardChangeEvent()
+}

+ 25 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/callback/NativeEventEmitter.kt

@@ -0,0 +1,25 @@
+package com.atmob.keyboard_android.util.bridge.callback
+
+/**
+ * 原生事件发射器
+ */
+interface NativeEventEmitter {
+    /**
+     * 发送成功事件
+     */
+    fun success(event: Any)
+
+    /**
+     * 发生错误时调用
+     *
+     * @param errorCode 错误码
+     * @param errorMsg 错误消息
+     * @param details 附加数据,类似拓展字段
+     */
+    fun error(errorCode: String, errorMsg: String, details: Any? = null)
+
+    /**
+     * 关闭事件流,相当于通知Flutter要解除事件注册
+     */
+    fun eventStreamClose()
+}

+ 27 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/callback/NativeEventHandler.kt

@@ -0,0 +1,27 @@
+package com.atmob.keyboard_android.util.bridge.callback
+
+/**
+ * 原生事件处理器,封装Flutter调用原生的事件注册、注销
+ */
+interface NativeEventHandler {
+    /**
+     * 获取该事件处理器的EventChannel通道名称
+     */
+    fun onGetEventChannelName(): String
+
+    /**
+     * Flutter端注册事件时回调
+     *
+     * @param args 参数
+     * @param emitter 事件发射器
+     */
+    fun onRegisterEventListener(args: String, emitter: NativeEventEmitter)
+
+    /**
+     * Flutter端取消注册事件时回调
+     *
+     * @param args 参数
+     * @param emitter 事件发射器
+     */
+    fun onUnRegisterEventListener(args: String, emitter: NativeEventEmitter)
+}

+ 58 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/event/DefaultKeyboardNativeEventHandler.kt

@@ -0,0 +1,58 @@
+package com.atmob.keyboard_android.util.bridge.event
+
+import com.atmob.keyboard_android.constant.PluginConfig
+import com.atmob.keyboard_android.util.DefaultKeyboardWatcher
+import com.atmob.keyboard_android.util.bridge.callback.NativeEventEmitter
+import com.atmob.keyboard_android.util.bridge.callback.NativeEventHandler
+import java.util.concurrent.CopyOnWriteArrayList
+
+/**
+ * 默认键盘切换事件处理器
+ */
+class DefaultKeyboardNativeEventHandler : NativeEventHandler {
+    /**
+     * 事件发射器列表
+     */
+    private var mNativeEventEmitters: MutableList<NativeEventEmitter> = CopyOnWriteArrayList()
+
+    /**
+     * 默认键盘切换监听
+     */
+    private val mOnKeyboardChangeListener =
+        object : DefaultKeyboardWatcher.OnDefaultKeyboardChangeListener {
+            override fun onDefaultKeyboard() {
+                for (emitter in mNativeEventEmitters) {
+                    emitter.success(true)
+                }
+            }
+
+            override fun onNotDefaultKeyboard() {
+                for (emitter in mNativeEventEmitters) {
+                    emitter.success(false)
+                }
+            }
+        };
+
+    override fun onGetEventChannelName(): String {
+        return PluginConfig.FLUTTER_DEFAULT_KEYBOARD_EVENT_CHANNEL_NAME
+    }
+
+    override fun onRegisterEventListener(
+        args: String,
+        emitter: NativeEventEmitter
+    ) {
+        if (!mNativeEventEmitters.contains(emitter)) {
+            mNativeEventEmitters.add(emitter)
+        }
+        // 没有初始化,则先初始化
+        if (!DefaultKeyboardWatcher.isInited()) {
+            DefaultKeyboardWatcher.init()
+        }
+        DefaultKeyboardWatcher.registerListener(mOnKeyboardChangeListener)
+    }
+
+    override fun onUnRegisterEventListener(args: String, emitter: NativeEventEmitter) {
+        mNativeEventEmitters.remove(emitter)
+        DefaultKeyboardWatcher.unRegisterListener(mOnKeyboardChangeListener)
+    }
+}

+ 88 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/util/NativeEventRegistry.kt

@@ -0,0 +1,88 @@
+package com.atmob.keyboard_android.util.bridge.util
+
+import com.atmob.keyboard_android.util.bridge.callback.NativeEventEmitter
+import com.atmob.keyboard_android.util.bridge.callback.NativeEventHandler
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.EventChannel
+import io.flutter.plugin.common.EventChannel.EventSink
+import io.flutter.plugin.common.EventChannel.StreamHandler
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * 原生端,发送事件给Flutter端,例如定位、默认键盘监听等功能
+ */
+class NativeEventRegistry {
+    /**
+     * Flutter引擎
+     */
+    private var mEngine: FlutterEngine? = null
+
+    /**
+     * 注册表,保存通道名称和通道的映射关系
+     */
+    private val mEventChannelMap = ConcurrentHashMap<String, EventChannel>()
+
+    /**
+     * 初始化
+     */
+    fun init(engine: FlutterEngine) {
+        this.mEngine = engine
+    }
+
+    /**
+     * 注册原生事件处理器
+     */
+    fun registerNativeEvent(eventChannelName: String, handler: NativeEventHandler) {
+        if (mEngine == null) {
+            throw IllegalArgumentException("请先调用init方法进行初始化")
+        }
+
+        val eventChannel = EventChannel(mEngine!!.dartExecutor.binaryMessenger, eventChannelName)
+        eventChannel.setStreamHandler(object : StreamHandler {
+            // 原生事件发射器
+            private var nativeEventEmitter: NativeEventEmitter? = null
+
+            override fun onListen(arguments: Any?, eventSink: EventSink) {
+                nativeEventEmitter = object : NativeEventEmitter {
+                    override fun success(event: Any) {
+                        // 发射成功事件
+                        eventSink.success(event)
+                    }
+
+                    override fun error(
+                        errorCode: String,
+                        errorMsg: String,
+                        details: Any?
+                    ) {
+                        // 发送错误事件
+                        eventSink.error(errorCode, errorMsg, details)
+                    }
+
+                    override fun eventStreamClose() {
+                        // 通知事件流关闭
+                        eventSink.endOfStream()
+                    }
+                }
+                // Flutter端注册监听
+                handler.onRegisterEventListener(arguments?.toString() ?: "", nativeEventEmitter!!)
+            }
+
+            override fun onCancel(arguments: Any?) {
+                if (nativeEventEmitter == null) {
+                    return
+                }
+                // Flutter端取消监听
+                handler.onUnRegisterEventListener(arguments?.toString() ?: "", nativeEventEmitter!!)
+            }
+        })
+        mEventChannelMap.put(eventChannelName, eventChannel)
+    }
+
+    /**
+     * 取消注册原生事件处理器
+     */
+    fun unRegisterNativeEvent(eventChannelName: String) {
+        val eventChannel = mEventChannelMap[eventChannelName]
+        eventChannel?.setStreamHandler(null)
+    }
+}

+ 8 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/util/NativeMethodRegistry.kt

@@ -1,6 +1,7 @@
 package com.atmob.keyboard_android.util.bridge.util
 
 import com.atmob.keyboard_android.constant.PluginConfig
+import com.atmob.keyboard_android.util.JsonUtil
 import com.atmob.keyboard_android.util.bridge.callback.NativeMethodHandler
 import com.atmob.keyboard_android.util.bridge.callback.ResultCallback
 import io.flutter.embedding.engine.FlutterEngine
@@ -35,7 +36,13 @@ class NativeMethodRegistry {
             // 方法名
             val methodName = call.method
             // 方法参数
-            val args = call.arguments<String>() ?: ""
+            val callArgs: Any = call.arguments
+            val args = if (callArgs is String) {
+                callArgs
+            } else {
+                val argMap: Map<*, *> = call.arguments<Map<*, *>>() ?: mapOf<Any, Any>()
+                JsonUtil.toJson(argMap)
+            }
             // 通过方法名,查找到方法处理器
             val nativeMethodHandler = mMethodMap[methodName]
             nativeMethodHandler?.onMethodCall(methodName, args, object : ResultCallback {

+ 4 - 0
plugins/keyboard_android/lib/keyboard_android.dart

@@ -6,6 +6,10 @@ class KeyboardAndroid {
     return KeyboardAndroidPlatform.instance.getPlatformVersion();
   }
 
+  Future<void> initPlugin() async {
+    return KeyboardAndroidPlatform.instance.initPlugin();
+  }
+
   /// 打开或关闭悬浮窗
   Future<void> enableFloatingWindow(bool enable) async {
     return KeyboardAndroidPlatform.instance.enableFloatingWindow(enable);

+ 5 - 0
plugins/keyboard_android/lib/keyboard_android_method_channel.dart

@@ -18,6 +18,11 @@ class MethodChannelKeyboardAndroid extends KeyboardAndroidPlatform {
   }
 
   @override
+  Future<void> initPlugin() async {
+    await methodChannel.invokeMethod('initPlugin');
+  }
+
+  @override
   Future<void> enableFloatingWindow(bool enable) async {
     await methodChannel.invokeMethod('enableFloatingWindow', {
       'enable': enable,

+ 6 - 0
plugins/keyboard_android/lib/keyboard_android_platform_interface.dart

@@ -27,6 +27,12 @@ abstract class KeyboardAndroidPlatform extends PlatformInterface {
     throw UnimplementedError('platformVersion() has not been implemented.');
   }
 
+  Future<void> initPlugin() {
+    throw UnimplementedError(
+      'initPlugin() has not been implemented.',
+    );
+  }
+
   Future<void> enableFloatingWindow(bool enable) {
     throw UnimplementedError(
       'enableFloatingWindow(bool enable) has not been implemented.',

+ 5 - 0
plugins/keyboard_android/test/keyboard_android_test.dart

@@ -11,6 +11,11 @@ class MockKeyboardAndroidPlatform
   Future<String?> getPlatformVersion() => Future.value('42');
 
   @override
+  Future<void> initPlugin() {
+    throw UnimplementedError();
+  }
+
+  @override
   Future<void> enableFloatingWindow(bool enable) {
     throw UnimplementedError();
   }