我如何打开单信号通知的特定页面?

时间:2018-10-23 16:39:54

标签: flutter onesignal

我正在使用OneSignal推送通知服务,我想在通知单击时直接将应用程序打开到特定页面。我正在通过数据发送页面。我尝试了navigator.push,但是由于上下文问题,我认为它不起作用。登录后我将调用_initializeonesignal(),其中包含一个信号初始化和以下代码。

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');
});

4 个答案:

答案 0 :(得分:0)

您将需要在主应用程序支架中注册一个全局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:部分,并将其保存到可以访问其他位置的位置。

然后在您的处理程序中:

OneSignal.shared.setNotificationOpenedHandler(_handleNotificationOpened); ...

// 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');
}

那应该可以解决问题-无论如何还是对我们有用:)

答案 1 :(得分:0)

很简单,通过使用onesignal,您可以创建从Kotlin到扑扑的系统调用

就我而言,我必须从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 获取数据的方法,但是只有在单击通知时,我才会获取“意图” 数据,然后将其发送到我的以下类别中的颤动代码:

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中获取数据,该URL是4ed'/'之后的最后一个单词,这是帖子的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到fluter或从Java到flutter的调用,秘密就在kotlin或Java中,我认为您必须对ios做同样的事情,我会留下一篇对我有帮助的文章。

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

答案 2 :(得分:0)

我解决了相同的问题,如下所示:
在主屏幕文件中 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);
      }
    });
  }

答案 3 :(得分:0)

我找到了解决办法:

在您的主屏幕上,设置处理程序。并且,在此之前,以这种方式设置您的配置通知

首先:

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);
    });
  }