Я использую https://pub.flutter-io.cn/packages/system_alert_window, и он запускает службу переднего плана. Эта служба переднего плана вызывает следующий обратный вызов, когда событие нажатия кнопки происходит в окне системного предупреждения.
Это мой обратный вызов, это метод stati c
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);
}
});
}
Но я получаю следующее исключение при попытке использовать метод плагина в обратном вызове
[ОШИБКА: flutter / lib / ui / ui_dart_state. cc (157)] Необработанное исключение: MissingPluginException (Не найдено реализации для метода launchApp на канале com.pichillilorenzo / flutter_appavailability)
Насколько я понимаю, это проблема. Список registerOnClick вызовет канал метода. И этот канал метода будет делать следующее:
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
Единственный способ справиться при этом следует использовать плагин IsolateHandler. Но разве это тоже не плагин?
Желаемое поведение состоит в том, что я могу вызвать плагин из обратного вызова.
Примечание: это происходит с любым плагином, который я пытаюсь вызвать с обратного звонка