是否可以将 OneSignal 与 Flutter-Web 一起使用?

Is it possible to use OneSignal with Flutter-Web?

调用任何 OneSignal 函数在 android 上都可以正常工作,但在网络上它会抛出以下异常。 请注意,订阅部分正在运行,我在 index.html 中设置了我的 appId,我上传了 service worker js 文件并收到了第一条欢迎消息。

但我需要能够获取“playerId”并保存它,还需要能够从网络发送通知。

OneSignal 函数调用示例:

  await OneSignal.shared.setAppId(kOneSignalAppId);
  OSDeviceState? deviceState = await OneSignal.shared.getDeviceState();
  OneSignal.shared.postNotification(notification);

异常:

Error: MissingPluginException(No implementation found for method OneSignal#log on channel OneSignal)
at Object.throw_ [as throw] (http://localhost:49430/dart_sdk.js:5079:11)
at MethodChannel._invokeMethod (http://localhost:49430/packages/flutter/src/services/restoration.dart.lib.js:1526:21)
at _invokeMethod.next (<anonymous>)
at http://localhost:49430/dart_sdk.js:38749:33
at _RootZone.runUnary (http://localhost:49430/dart_sdk.js:38620:59)
at _FutureListener.thenAwait.handleValue (http://localhost:49430/dart_sdk.js:33820:29)
at handleValueCallback (http://localhost:49430/dart_sdk.js:34372:49)
at Function._propagateToListeners (http://localhost:49430/dart_sdk.js:34410:17)
at _Future.new.[_completeWithValue] (http://localhost:49430/dart_sdk.js:34258:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:49430/dart_sdk.js:34279:35)
at Object._microtaskLoop (http://localhost:49430/dart_sdk.js:38887:13)
at _startMicrotaskLoop (http://localhost:49430/dart_sdk.js:38893:13)
at http://localhost:49430/dart_sdk.js:34626:9

Error: MissingPluginException(No implementation found for method OneSignal#setAppId on channel OneSignal)
at Object.throw_ [as throw] (http://localhost:49430/dart_sdk.js:5079:11)
at MethodChannel._invokeMethod (http://localhost:49430/packages/flutter/src/services/restoration.dart.lib.js:1526:21)
at _invokeMethod.next (<anonymous>)
at http://localhost:49430/dart_sdk.js:38749:33
at _RootZone.runUnary (http://localhost:49430/dart_sdk.js:38620:59)
at _FutureListener.thenAwait.handleValue (http://localhost:49430/dart_sdk.js:33820:29)
at handleValueCallback (http://localhost:49430/dart_sdk.js:34372:49)
at Function._propagateToListeners (http://localhost:49430/dart_sdk.js:34410:17)
at _Future.new.[_completeWithValue] (http://localhost:49430/dart_sdk.js:34258:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:49430/dart_sdk.js:34279:35)
at Object._microtaskLoop (http://localhost:49430/dart_sdk.js:38887:13)
at _startMicrotaskLoop (http://localhost:49430/dart_sdk.js:38893:13)
at http://localhost:49430/dart_sdk.js:34626:9

需要网页插件吗? 是否存在或我应该创建一个? 如果可以,请告诉我怎么做?

OneSignal 有 SDK for web push, flutter web 最后是一个网站 (webapp) 所以你应该为 web 配置 OneSignal 并尝试一下。

您可以这样做以获得 player_id 使用 JavaScript:

OneSignal.push(function() {
/* These examples are all valid 
*/

OneSignal.getUserId(function(userId) {
console.log("OneSignal User ID:", userId);
// (Output) OneSignal User ID: 270a35cd-4dda-4b3f-b04e-41d7463a2316    
  });
});

//Another example:

OneSignal.push(function() {               

OneSignal.getUserId().then(function(userId) {
console.log("OneSignal User ID:", userId);
// (Output) OneSignal User ID: 270a35cd-4dda-4b3f-b04e-41d7463a2316    
  });
});

然后就可以通过url传递给flutter代码了。

经过大量调查,我能够确认以下内容:

  1. “Flutter SDK”仅适用于移动应用,不适用于网络应用
  2. 对于 Web 应用程序,我们应该使用“Web SDK”,即使用 Java Script 而不是 Flutter
  3. 对于移动端和网络端,我们都可以使用 REST API,但在大多数情况下,它需要应用程序 ID、播放器 ID 和 API 密钥,以便初始化和获取播放器-id 我们仍然需要用于移动应用程序的“Flutter SDK”或用于网络的“Web SDK” 这就是我设法使用相同的代码使其在移动和网络应用程序上运行的方式: Web 部分
  • 正在通过 Web SDK 初始化
  • 通过Web SDK获取player-id
  • 通过 javascipt 在隐藏元素中保存玩家 ID
  • 通过“universal_html”包从 Flutter 代码中检索玩家 ID
  • 通过 REST 设置外部 ID API
  • 正在通过 REST 发送通知API

移动部分

  • 正在通过 Flutter SDK 初始化
  • 通过Flutter SDK获取player-id
  • 通过 Flutter SDK 设置 external-id
  • 通过 REST 发送通知API(因为 Flutter SDK 无法发送到外部 ID)

index.html

<head>
  ...
  <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
  <script>
    var OneSignal = window.OneSignal || [];
    var initConfig = {
      appId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      persistNotification: true,
      notifyButton: {
          enable: true
      },
    };
    OneSignal.push(function () {
      OneSignal.init(initConfig);
    });
  </script>
</head>
<body>
  <input type="hidden" id="osUserID" value="ERR" />
  ...
  <script>
    var eUserID = document.getElementById('osUserID');
    function getUserId() {
      OneSignal.getUserId(function(osUserID) {
        if (eUserID && osUserID) {
          eUserID.value = osUserID;
          }
      });
    }
    OneSignal.push(function () {
      OneSignal.isPushNotificationsEnabled(function(isEnabled) {
        if (isEnabled) getUserId();
      });
      OneSignal.on('subscriptionChange', function (isSubscribed) {
        if (isSubscribed) getUserId();
      });
    });
  </script>
</body>

来自 Flutter 内部

  import 'package:flutter/foundation.dart';
  import "package:universal_html/html.dart";
  import 'package:onesignal_flutter/onesignal_flutter.dart';
  import 'onesignal_api.dart';
  ...
  Future<String> getPlayerId(String exteralId) async {
    String _osUserID;
    if (kIsWeb){
      InputElement? element = querySelector("#osUserID") as InputElement?;
      osUserID = element?.value??"Not Subscribed";
      await _oneSignalAPI.setExternalId(osUserID, exteralId);
    }
    else {
      await OneSignal.shared.setAppId(kOneSignalAppId);
      OSDeviceState? deviceState = await OneSignal.shared.getDeviceState();
      osUserID = deviceState?.userId??"Not Subscribed";
      await OneSignal.shared.setExternalUserId(exteralId);
    }
    return osUserID;
  }
  Future<void> sendMessage(String exteralId, String message) async {
    _oneSignalAPI.sendNotification(exteralId, message);
  }