【问题标题】:How to resume the application and open a specific page with a push notification in Xamarin.forms如何在 Xamarin.forms 中恢复应用程序并使用推送通知打开特定页面
【发布时间】:2017-03-27 18:15:58
【问题描述】:

我目前正在开发适用于 iOS 和 Android 的 Xamarin 应用程序,但我要解释的问题仅涉及 Android 应用程序(iOS 应用程序中尚未实现)。

实际上,当我收到给定的推送通知时,我需要在我的应用程序中打开一个特定页面。如果在收到推送通知时应用程序处于打开状态,它会很好地工作,但如果我的应用程序关闭或在后台运行,应用程序会崩溃。

好吧,当我收到通知时,我最终会使用名为“OnShouldOpenCommand”的方法:

  private void OnShouldOpenCommand(string commandId)
        {
            NotifyNewCommand(AppResources.AppName, AppResources.CommandNotificationText, commandId);

            Device.BeginInvokeOnMainThread(() =>
            {
                try
                {

                    App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(commandId))
                    {
                        BarBackgroundColor = Color.FromHex("1e1d1d")
                    };

                    App.MasterDetailPage.NavigationStack.Push(((NavigationPage)(App.MasterDetailPage.Detail)).CurrentPage);
                }
                catch(Exception e)
                {                   
                        Log.Debug("PushAsync", "Unable to push CommandAcceptancePage : "+ex.Message);
                }

            });
        }

    private void NotifyNewCommand(string Title,string Description, string commandId)
    {
        var intent = new Intent(this, typeof(MainActivity));
        if (!String.IsNullOrEmpty(commandId))
        {
            intent.PutExtra("CommandId", commandId);
        }
        intent.AddFlags(ActivityFlags.ClearTop);
        var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);

        var notificationBuilder = new Notification.Builder(this)
            .SetSmallIcon(Resource.Drawable.icon)
            .SetContentTitle("Kluox")
            .SetContentText(Description)
            .SetAutoCancel(true)
            .SetContentIntent(pendingIntent);

        Notification notification = notificationBuilder.Build();

        var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
        notificationManager.Notify(0, notification);
    }

还有代码

App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(commandId))
                    {
                        BarBackgroundColor = Color.FromHex("1e1d1d")
                    };

正在生成类型异常:

Java.Lang.IllegalStateException: 之后无法执行此操作 onSaveInstanceState

好吧,如果我的应用程序没有在前台运行,我想我无法访问“应用程序”并重定向到另一个页面。好吧,这是我收到推送通知的时候,而不是我点击它的时候。但是,我不打算通过这样做来重新打开我的应用程序。

因为在那之后,当我点击名为 Kluox 的推送通知(这应该重新打开我的应用程序)时,应用程序崩溃了,我真的不知道为什么,我不知道在哪里放置断点能够调试,因为 Visual Studio 只是告诉我“发生了未处理的异常。”。

有人可以帮我吗?如果你需要任何代码,你可以问我,我会编辑我的消息并给你任何你需要的信息!

编辑 1:这是我的 OnCreate 方法的代码:

protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);
            var info = Intent.Extras?.GetString("CommandId", "");
            global::Xamarin.Forms.Forms.Init(this, bundle);
            if (String.IsNullOrEmpty(info))
            {
                LoadApplication(new App());
            }
            else
            {
                LoadApplication(new App(info));
            }
            if (instance == null)
            {
                instance = this;
                RegisterWithGCM();
            }
            else
            {
                instance = this;
            }
        }

【问题讨论】:

标签: xamarin push-notification xamarin.forms


【解决方案1】:

在重写了MainActivity的所有方法后,终于找到了崩溃的原因:方法OnDestroy被调用了两次,由于activity已经被销毁,抛出了IllegalStateException。我找到了这个解决方法:

 protected override void OnDestroy()
        {
            try
            {
                base.OnDestroy();
            }
            catch (Java.Lang.IllegalStateException ex)
            {
                Log.Debug("MainActivity.OnDestroy", ex, "The activity was destroyed twice");
            }

        }

并且简单地记录了异常,应用程序可以毫无问题地打开和使用。

当重定向也有效时,我将编辑此答案。

编辑:如何重定向到页面

首先,我们需要在构造函数中注册 MessagingCenter

public static MyPackage.Model.Command CurrentCommand { get; set; }
public App()
{
    InitializeComponent();
    MainPage = new ContentPage();
    MessagingCenter.Subscribe<object, DataLib.Model.Command>(this, "Command", (sender, arg) => {
      try
      {
         CurrentCommand = arg;
      }
      catch(Exception ex)
      {
         CurrentCommand = null;
      }
    });
  }

当我们收到推送通知时发送消息:

private void OnMessage(string serializedCommand)
{
  //stuff happens
  MessagingCenter.Send<object, MyPackage.Model.Command>(this, "Command", command);
}

最后,当我们得到 App.Xaml.cs 的 OnStart() 时

                if (CurrentCommand != null)
                {
                    App.MasterDetailPage.Detail = new NavigationPage(new CommandAcceptancePage(CurrentCommand, service))
                    {
                        BarBackgroundColor = Color.FromHex("1e1d1d")
                    };
                }

现在,它似乎可以解决问题!随后将进行更多调试,但代码似乎可以正常工作。非常感谢@BraveHeart 的帮助!

【讨论】:

    【解决方案2】:

    你很幸运,几天前我在那里,掉了很多头发,直到我让它在 Android 上工作(并且仍在为 iOS 奋斗)。

    当你杀死你的应用程序并再次从图标或通知中实例化它时,你将进入主要活动。

    如果我们想从实例化它的通知中获取主活动中的一些信息,我们在 OnCreate() 中这样做:

    var info = Intent.Extras?.GetString("info", "");
    

    现在,在您的情况下,我将在通知中添加额外信息,以显示此通知是关于哪个视图/页面,例如它的名称)

    您可以在加载之前将这条额外信息传递给 App 的构造函数。

    在应用的构造函数中可以检查是否有额外的信息,如果没有则表示启动应用的主页面是默认的主页面,否则是某个页面。

    【讨论】:

    • 我现在试试这个,之后我会给你反馈,无论如何感谢你的帮助!
    • 嘿,我正在与 Anto Maniscalco 合作,我们尝试了您的解决方案,但我们遇到了同样的问题。当我们创建通知时,我们添加intent.PutExtra("CommandId", commandId); 在 OnCreate 中,我们有var info = Intent.Extras?.GetString("CommandId", ""); global::Xamarin.Forms.Forms.Init(this, bundle); if (String.IsNullOrEmpty(info)) { LoadApplication(new App()); } else { LoadApplication(new App(info)); }
    • 你确定你得到的信息是正确的吗?也许您可以在此处添加祝酒词,向您显示此处的信息。
    • 我用调试器检查过,我得到的数据很好,通知确实显示了正确的文本和所有内容,但是当我点击它时,应用程序崩溃了,甚至没有进入OnCreate 方法...
    • 太好了,如果应用程序正在运行,那么它肯定不会转到 OnCreate() ,但它会转到“OnResume” 我首先想到的是使用 MessagingCenter 并发送那里的页面名称。然后你可以从任何地方订阅它,一个消息被触发,它将在共享项目中处理。这样你就可以为所欲为:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2015-05-26
    相关资源
    最近更新 更多