android - 如何从 system_alert_window 包调用应用范围内的回调

标签 android flutter dart android-service

我正在使用 https://pub.flutter-io.cn/packages/system_alert_window并启动前台服务。当系统警报窗口中发生按钮单击事件时,此前台服务会调用以下回调。
这是我的回调,它是一个静态方法

  static Future<void> systemOverlayOnClickListner(String value) async {
    if (value == 'button_app_to_foreground') {
      await SystemAlertWindow.closeSystemWindow();
      await AppAvailability.launchApp('com.company_name.app_name');
    }
  }
这是插件中注册回调的方法
  static Future<bool> registerOnClickListener(
      OnClickListener callBackFunction) async {
    final callBackDispatcher =
        PluginUtilities.getCallbackHandle(callbackDispatcher);
    final callBack = PluginUtilities.getCallbackHandle(callBackFunction);
    _channel.setMethodCallHandler((MethodCall call) {
      print("Got callback");
      switch (call.method) {
        case "callBack":
          dynamic arguments = call.arguments;
          if (arguments is List) {
            final type = arguments[0];
            if (type == "onClick") {
              final tag = arguments[1];
              callBackFunction(tag);
            }
          }
      }
      return null;
    });
    await _channel.invokeMethod("registerCallBackHandler",
        <dynamic>[callBackDispatcher.toRawHandle(), callBack.toRawHandle()]);
    return true;
  }
这是调用回调的顶级方法
void callbackDispatcher() {
  // 1. Initialize MethodChannel used to communicate with the platform portion of the plugin
  const MethodChannel _backgroundChannel =
      const MethodChannel(Constants.BACKGROUND_CHANNEL);
  // 2. Setup internal state needed for MethodChannels.
  WidgetsFlutterBinding.ensureInitialized();

  // 3. Listen for background events from the platform portion of the plugin.
  _backgroundChannel.setMethodCallHandler((MethodCall call) async {
    final args = call.arguments;
    // 3.1. Retrieve callback instance for handle.
    final Function callback = PluginUtilities.getCallbackFromHandle(
        CallbackHandle.fromRawHandle(args[0]));
    assert(callback != null);
    final type = args[1];
    if (type == "onClick") {
      final tag = args[2];
      // 3.2. Invoke callback.
      callback(tag);
    }
  });
}
但是尝试在回调中使用插件方法时出现以下异常

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method launchApp on channel com.pichillilorenzo/flutter_appavailability)


据我所知,这就是问题所在。 registerOnClick 列表器将调用方法 channel 。这个方法 channel 将执行以下操作
    case "registerCallBackHandler":
        try {
            List arguments = (List) call.arguments;
            if (arguments != null) {
                long callbackHandle = Long.parseLong(String.valueOf(arguments.get(0)));
                long onClickHandle = Long.parseLong(String.valueOf(arguments.get(1)));
                SharedPreferences preferences = mContext.getSharedPreferences(Constants.SHARED_PREF_SYSTEM_ALERT_WINDOW, 0);
                preferences.edit().putLong(Constants.CALLBACK_HANDLE_KEY, callbackHandle)
                        .putLong(Constants.CODE_CALLBACK_HANDLE_KEY, onClickHandle).apply();
                startCallBackHandler(mContext);
                result.success(true);
            } else {
                Log.e(TAG, "Unable to register on click handler. Arguments are null");
                result.success(false);
            }
        }
所以 startcallback 处理程序被调用
public static void startCallBackHandler(Context context) {
    SharedPreferences preferences = context.getSharedPreferences(Constants.SHARED_PREF_SYSTEM_ALERT_WINDOW, 0);
    long callBackHandle = preferences.getLong(Constants.CALLBACK_HANDLE_KEY, -1);
    Log.d(TAG, "onClickCallBackHandle " + callBackHandle);
    if (callBackHandle != -1) {
        FlutterMain.ensureInitializationComplete(context, null);
        String mAppBundlePath = FlutterMain.findAppBundlePath();
        FlutterCallbackInformation flutterCallback = FlutterCallbackInformation.lookupCallbackInformation(callBackHandle);
        if (sBackgroundFlutterView == null) {
            sBackgroundFlutterView = new FlutterNativeView(context, true);
            if(mAppBundlePath != null && !sIsIsolateRunning.get()){
                if (sPluginRegistrantCallback == null) {
                    Log.i(TAG, "Unable to start callBackHandle... as plugin is not registered");
                    return;
                }
                Log.i(TAG, "Starting callBackHandle...");
                FlutterRunArguments args = new FlutterRunArguments();
                args.bundlePath = mAppBundlePath;
                args.entrypoint = flutterCallback.callbackName;
                args.libraryPath = flutterCallback.callbackLibraryPath;
                sBackgroundFlutterView.runFromBundle(args);
                sPluginRegistrantCallback.registerWith(sBackgroundFlutterView.getPluginRegistry());
                backgroundChannel = new MethodChannel(sBackgroundFlutterView, Constants.BACKGROUND_CHANNEL);
                sIsIsolateRunning.set(true);
            }
        }else {
            if(backgroundChannel == null){
                backgroundChannel = new MethodChannel(sBackgroundFlutterView, Constants.BACKGROUND_CHANNEL);
            }
            sIsIsolateRunning.set(true);
        }
    }
}
这似乎产生了一个隔离来运行回调。因此,当触发我的回调时,它将在单独的隔离中触发。
根据这个帖子
github post
解决这个问题的唯一方法是使用 IsolateHandler 插件。但这不也是一个插件吗?
期望的行为是我可以从回调中调用插件。
注意:我尝试从回调 调用的任何插件都会发生这种情况

最佳答案

你的错误

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: 
MissingPluginException(No implementation found for method launchApp on channel
com.pichillilorenzo/flutter_appavailability)
不属于 system alert window插入。
您缺少插件异常的原因是,flutter_appavailability插件不支持后台执行。
因此,要使其正常工作,您必须使用隔离通​​信从 system_alert_window 获取回调。到主线程,然后调用这个插件。提到了here
识别插件是否支持后台执行的一种简单方法是查看是否需要在 application.class 中注册插件。或 application.kt

关于android - 如何从 system_alert_window 包调用应用范围内的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62803689/

相关文章:

java - Android: View 寻呼机中 fragment 之间的通信

dart - DART中有用于声明式ui的类似方法吗?

android - GvrViewerMain 自己旋转相机。 Unity3D + 谷歌VR

android - 覆盖每个 Activity 的 Activity 转换

android - 如何使堆栈响应敏捷?

android - 在 "flutter doctor"中显示关于 Android 工具链的错误

tabs - Flutter - 使用带有动态选项卡 View 的 TabBarView 小部件实现抽屉导航

dart - 在其状态类中访问有状态小部件的功能? flutter

dart - NestedScrollView 和 CustomScrollView 有什么区别?

android - 将谷歌地图链接到 TextView 中的邮政编码