dart 如何在onesignal通知上打开特定页面点击Flutter?

30byixjq  于 2023-11-14  发布在  Flutter
关注(0)|答案(6)|浏览(139)

我正在使用OneSignal推送通知服务,我想在通知点击时直接打开应用程序到特定页面。我通过数据发送页面。我尝试了navigator.push,但它不工作,我猜是因为上下文问题。我在登录后调用_initializeonesignal(),其中包含onesignal init和以下代码。

OneSignal.shared.setNotificationOpenedHandler((notification) {
  var notify = notification.notification.payload.additionalData;
  if (notify["type"] == "message") {
    //open DM(user: notify["id"])
  }
  if (notify["type"] == "user") {
   //open Profileo(notify["id"])
  }
  if (notify["type"] == "post") {
    //open ViewPost(notify["id"])
  }
  print('Opened');
});

字符串

jqjz2hbq

jqjz2hbq1#

您需要在主应用程序scaffold中注册一个全局Navigator句柄--然后就可以在通知处理程序中使用它。
所以-在我们的应用程序中,在我们的主应用程序中,我们有:

// Initialize our global NavigatorKey
    globals.navigatorKey = GlobalKey<NavigatorState>();

...
            return MaterialApp(
              title: 'MissionMode Mobile',
              theme: theme,
              initialRoute: _initialRoute,
              onGenerateRoute: globals.router.generator,
              navigatorKey: globals.navigatorKey,
            );

字符串
关键是navigatorKey:part,并将其保存到您可以访问的其他地方。
然后在您的处理程序中:
OneSignal.shared. setNotificationOpenedString(_String NotificationOpened);.

// What to do when the user opens/taps on a notification
void _handleNotificationOpened(OSNotificationOpenedResult result) {
  print('[notification_service - _handleNotificationOpened()');
  print(
      "Opened notification: ${result.notification.jsonRepresentation().replaceAll("\\n", "\n")}");

  // Since the only thing we can get current are new Alerts -- go to the Alert screen
  globals.navigatorKey.currentState.pushNamed('/home');
}


这应该能起作用--反正对我们来说也是这样:)

mm9b1k5b

mm9b1k5b2#

很简单,通过使用onesignal,您可以创建从Kotlin到flutter的系统调用
在我的例子中,我必须从WordPress中的onesignal的通知中获取URL中的数据:

package packageName.com

import android.os.Bundle
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
// import io.flutter.plugins.firebaseadmob.FirebaseAdMobPlugin;
private val CHANNEL = "poc.deeplink.flutter.dev/channel"
private var startString: String? = null

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        MethodChannel(flutterEngine.dartExecutor, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "initialLink") {
                if (startString != null) {
                    result.success(startString)
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val intent = getIntent()
        startString = intent.data?.toString()
    }
}

字符串
这是我从onCreate获取的数据,但只有在点击通知时,我才会获取**“intent”**数据,然后将其发送到以下类中的flutter代码:

import 'dart:async';

import 'package:flutter/services.dart';

class MyNotificationHandler {
  //Method channel creation
  static const platform =
      const MethodChannel('poc.deeplink.flutter.dev/channel');
  //Method channel creation

  static String url;
  static String postID;
  static onRedirected(String uri) {
    url = uri;
    postID = url.split('/').toList()[3];
  }

  static Future<String> startUri() async {
    try {
      return platform.invokeMethod('initialLink');
    } on PlatformException catch (e) {
      return "Failed to Invoke: '${e.message}'.";
    }
  }

  //Adding the listener into contructor
  MyNotificationHandler() {
    //Checking application start by deep link
    startUri().then(onRedirected);
  }
}


在这里,我从一个WordPress URL中获取数据,4 ed '/'后面的最后一个词是帖子的ID。
现在如何使用它和调用它,因为我创建了它静态我将使用它在我的代码时,第一个页面加载,

import 'package:com/config/LocalNotification.dart';

class MyLoadingPage extends StatefulWidget {
  MyLoadingPage() {
    MyNotificationHandler.startUri().then(MyNotificationHandler.onRedirected);
  }
  @override
  _MyLoadingPageState createState() => _MyLoadingPageState();
}

...


此页面将从我的WordPress API加载数据。
所以从数据库加载数据后,我会检查id的值,并导航到文章页面,我的主页中的示例:

....
  @override
  void initState() {
    MyViewWidgets.generalScaffoldKey = _scaffoldKey;

    myWidgetPosts = MyPostsOnTheWall(MyPost.allMyPosts, loadingHandler);
    MyHomePAge.myState = this;
    super.initState();

    if (MyNotificationHandler.postID != null) {
      Future.delayed(Duration(milliseconds: 250)).then((value) {
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => MyArticlePage(MyPost.allMyPosts
                    .firstWhere((element) =>
                        element.id == MyNotificationHandler.postID))));
      });
    }
  }
....


秘密是在Kotlin或Java中,通过使用从Kotlin到Fluter或从Java到Flutter的调用,我想你将不得不对iOS做同样的事情,我会留下一篇文章来帮助我。

https://medium.com/flutter-community/deep-links-and-flutter-applications-how-to-handle-them-properly-8c9865af9283

jv4diomz

jv4diomz3#

我解决了同样的问题,如下所示:
在主屏幕文件MyApp.dart

@override
  void initState() {
    OneSignalWapper.handleClickNotification(context);
  }

字符串
[*] OneSignalWapper.dart**:

static void handleClickNotification(BuildContext context) {
    OneSignal.shared
        .setNotificationOpenedHandler((OSNotificationOpenedResult result) async {
      try {
        var id = await result.notification.payload.additionalData["data_id"];
        Navigator.of(context).push(MaterialPageRoute(
            builder: (context) => PostDetailsScreen.newInstance('$id')));
      } catch (e, stacktrace) {
        log(e);
      }
    });
  }

tcbh2hod

tcbh2hod4#

您可以使用此代码:

final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();

 OneSignal.shared.setNotificationOpenedHandler((result) {
       navigatorKey.currentState.push(
        MaterialPageRoute(
          builder: (context) => YourPage(),
        ),
      );
    });

字符串
MaterialApp(home:SplashScreen(),navigatorKey:navigatorKey,)

bprjcwpo

bprjcwpo5#

我找到了解决方案:
在主屏幕上设置处理程序。
第一:

Map<String, dynamic> additional = {
              "route": 'detail',
              "userId": widget.userId
            };

            await OneSignal.shared.postNotification(OSCreateNotification(
                playerIds: userToken,
                content: 'your content',
                heading: 'your heading',
                additionalData: additional,
                androidLargeIcon:'any icon'));

字符串
第二:

OneSignal.shared.setNotificationOpenedHandler(
    (OSNotificationOpenedResult action) async {
  Map<String, dynamic> dataNotification =
      action.notification.payload.additionalData;

  if (dataNotification.containsValue('detailPage')) {
    await Navigator.push(
      context,
      new MaterialPageRoute(
        builder: (context) => new DetailScreen(
            userId: dataNotification['userId'],
      ),
    ).catchError((onError) {
      print(onError);
    });
  }

ezykj2lf

ezykj2lf6#

RiverPods解决方案
主要:

class MyApp extends ConsumerStatefulWidget {
  const MyApp({super.key});

  @override
  ConsumerState<MyApp> createState() => _MyAppState();
}

class _MyAppState extends ConsumerState<MyApp> {
  bool requireConsent = false;

  @override
  void initState() {
    super.initState();
    OneSignalWapper.forgroundListener(ref);
  }

  @override
  Widget build(BuildContext context) {
    print('User: ${ref.watch(userDataProvider)?.data?.email}');
    print(
        'Role: ${Roles.roleChecker(ref.read(userDataProvider)?.data?.roles) ?? ""}');
    print(
        'Token: ${ref.watch(sharedPreferencesProvider)?.getString(SharedPreferencesNames.token.name)}');
    print('User ID: ${ref.watch(userDataProvider)?.data?.id}');
    print(
        "device id: ${ref.watch(sharedPreferencesProvider)?.getString(SharedPreferencesNames.deviceid.name)}");

    var router = ref.read(routing);
    //Called here......................
    OneSignalWapper.handleClickNotification(ref);

    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      themeMode: ref.watch(themeProvider),
      theme: MyThemes.lightTheme,
      darkTheme: MyThemes.darkTheme,
      title: 'Flutter Demo',
      routeInformationParser: router.routeInformationParser,
      routerDelegate: router.routerDelegate,
      routeInformationProvider: router.routeInformationProvider,
    );
  }
}

字符串
自定义 Package 文件.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';
import 'package:rescue/utils/constants.dart';
import 'package:rescue/utils/provider.dart';
import 'package:rescue/utils/routing/router.dart';
import 'package:rescue/utils/routing/router_names.dart';

class OneSignalWapper {
  static void handleClickNotification(WidgetRef ref) {
    OneSignal.Notifications.addClickListener((event) async {
      var router = ref.read(routing);

      ref
          .read(notificationList.notifier)
          .setID(ref.watch(userDataProvider)!.data!.id!);
      await ref
          .watch(notificationList.notifier)
          .getUsersAnnoucements(ref.watch(userDataProvider)?.data?.id);

      switch (ref.watch(userDataProvider)?.data?.accountType) {
        case Roles.user:
          router.goNamed(RouteNames.userPushNotifications.name);
          break;
        case Roles.admin:
          router.goNamed(RouteNames.adminHomePage.name);
          break;
        case Roles.assistant:
          router.goNamed(RouteNames.assistantHomePage.name);
          break;
        default:
          router.goNamed(RouteNames.login.name);
      }
    });
  }

  // static void forgroundListener(WidgetRef ref) {
  //   OneSignal.Notifications.addForegroundWillDisplayListener((event) async {
  //     ref
  //         .read(notificationList.notifier)
  //         .setID(ref.watch(userDataProvider)!.data!.id!);

  //     await ref
  //         .watch(notificationList.notifier)
  //         .getUsersAnnoucements(ref.watch(userDataProvider)!.data!.id, true);

  //     print(event.notification.title);
  //   });
  // }
}

相关问题