我正在创建使用 Xamarin.Forms
和 MvvmCross
6.1.2 构建的应用程序,并且需要向 显示通知>用户
。单击通知后,需要显示特定屏幕。目前我正在尝试在android上实现这个功能。我使用 Notification.Builder
来创建和显示通知,并且在执行此操作时需要提供要运行的 Intent 。
创建 Intent :
var request = MvxViewModelRequest<SomeViewModel>.GetDefaultRequest();
var translator = Mvx.Resolve<IMvxAndroidViewModelRequestTranslator>();
var intent = translator.GetIntentFor(request);
不幸的是,它崩溃并提示Type isn'therited from Java.Lang.Object
。我卡住了,找不到任何示例或解释如何在单击通知时导航到特定屏幕/ View 模型。 MvvmCross
示例均不包含此类功能。
真的需要你的帮助!
此外,为了演示这个问题,我在 github 上创建了一个简单的项目: https://github.com/oleg-savoskin/mvvmcross-sample
更新 1(堆栈跟踪):
07-07 13:04:32.734 I/MonoDroid(15618): UNHANDLED EXCEPTION:
07-07 13:04:32.785 I/MonoDroid(15618): System.ArgumentException: type
07-07 13:04:32.785 I/MonoDroid(15618): Parameter name: Type is not derived from a java type.
07-07 13:04:32.785 I/MonoDroid(15618): at Java.Lang.Class.FromType (System.Type type) [0x00012] in <263adecfa58f4c449f1ff56156d886fd>:0
07-07 13:04:32.785 I/MonoDroid(15618): at Android.Content.Intent..ctor (Android.Content.Context packageContext, System.Type type) [0x00000] in <263adecfa58f4c449f1ff56156d886fd>:0
07-07 13:04:32.785 I/MonoDroid(15618): at MvvmCross.Platforms.Android.Views.MvxAndroidViewsContainer.GetIntentFor (MvvmCross.ViewModels.MvxViewModelRequest request) [0x0003f] in <17df0d0bdae848b7a8a12b58d710f763>:0
07-07 13:04:32.785 I/MonoDroid(15618): at Sample.Droid.Services.NotificationService.GetContentIntent () [0x0000d] in D:\TEMP\Repositories\Sample\Sample.Android\Services\NotificationService.cs:31
07-07 13:04:32.785 I/MonoDroid(15618): at Sample.Droid.Services.NotificationService.ShowNotification () [0x00001] in D:\TEMP\Repositories\Sample\Sample.Android\Services\NotificationService.cs:15
07-07 13:04:32.785 I/MonoDroid(15618): at Sample.Core.ViewModels.HomeViewModel.ShowNotification () [0x00001] in D:\TEMP\Repositories\Sample\Sample.Core\ViewModels\HomeViewModel.cs:25
07-07 13:04:32.786 I/MonoDroid(15618): at MvvmCross.Commands.MvxCommand.Execute (System.Object parameter) [0x00009] in <17df0d0bdae848b7a8a12b58d710f763>:0
07-07 13:04:32.786 I/MonoDroid(15618): at Xamarin.Forms.Button.SendClicked () [0x00008] in D:\a\1\s\Xamarin.Forms.Core\Button.cs:132
07-07 13:04:32.786 I/MonoDroid(15618): at Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer+ButtonClickListener.OnClick (Android.Views.View v) [0x0000b] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\ButtonRenderer.cs:291
07-07 13:04:32.786 I/MonoDroid(15618): at Android.Views.View+IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_v) [0x0000f] in <263adecfa58f4c449f1ff56156d886fd>:0
07-07 13:04:32.786 I/MonoDroid(15618): at (wrapper dynamic-method) System.Object.3ef246c1-103e-48ba-ba77-3d677f97466e(intptr,intptr,intptr)
更新2
我设法通过提供主要 Activity 作为目标类型来使其以某种方式工作。它会打开应用程序,但实际上并未导航到“第 2 页”。
public class NotificationService : INotificationService
{
public void ShowNotification()
{
var notification = new NotificationCompat.Builder(Application.Context)
.SetContentTitle("Sample app")
.SetContentText("Click here to navigate to page 2")
.SetSmallIcon(Resource.Drawable.ic_notification)
.SetContentIntent(GetContentIntent())
.SetShowWhen(false)
.Build();
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(1, notification);
}
private PendingIntent GetContentIntent()
{
var request = MvxViewModelRequest<Page2ViewModel>.GetDefaultRequest();
var converter = Mvx.Resolve<IMvxNavigationSerializer>();
var requestText = converter.Serializer.SerializeObject(request);
var intent = new Intent(Application.Context, typeof(MainActivity)) // <-- It's here;
intent.PutExtra("MvxLaunchData", requestText);
return PendingIntent.GetActivity(Application.Context, 0, intent, 0);
}
}
但有时它仍然会崩溃,并出现错误 System.NotSupportedException:无法从 native 句柄 0x7fc0da6d44 激活 Xamarin.Forms.Platform.Android.PageRenderer 类型的实例
。
知道我在这里做错了什么吗?
最佳答案
您的更新 2 走在正确的轨道上。第一个问题是,MvvmCross 似乎在 Android 内部使用 Intents,但其中一些无法传递给 Android 方法,因为引用的类型不继承自Java.Lang.Object。
此代码正在运行,位于 https://github.com/curtisshipley/mvvmcross-sample 中
它处理主 Activity 运行时和不运行时的情况。根据情况,如果 MainActivity 未运行,则 Intent 会有不同的入口点:OnCreate
。 OnNewIntent
如果是的话。在示例代码中,这些仅调用 NavigateToRequestIfPresent
。
此外,我对 NavigationService 进行了一些小调整,以便它可以与派生自 IMvxViewModel 的任何 ViewModel 配合使用。
public void ShowNotification<VM>() where VM : IMvxViewModel
{
var notification =
new NotificationCompat.Builder(Application.Context, SampleApplication.NOTIFICATION_CHANNEL)
.SetContentTitle("Sample app")
.SetContentText("Click here to navigate to page 2")
.SetSmallIcon(Resource.Drawable.ic_notification)
.SetContentIntent(GetContentIntent<VM>())
.SetShowWhen(false)
.Build();
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(1, notification);
}
private PendingIntent GetContentIntent<VM>() where VM : IMvxViewModel
{
var request = MvxViewModelRequest<VM>.GetDefaultRequest();
var converter = Mvx.Resolve<IMvxNavigationSerializer>();
var requestText = converter.Serializer.SerializeObject(request);
var intent = new Intent(Application.Context, typeof(MainActivity));
// We only want one activity started
intent.AddFlags(ActivityFlags.SingleTop);
intent.PutExtra("MvxLaunchData", requestText);
// Create Pending intent, with OneShot. We're not going to want to update this.
return PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.OneShot);
}
为了响应,我们需要允许 MainActivity 了解 Intent 。此方法检查 View 模型的序列化请求的 Intent。如果存在的话, 我们反序列化然后导航。
protected void NavigateToRequestIfPresent(Intent intent)
{
// If MvxLaunchData is present, we then know we should navigate to that intent
var requestText = intent.GetStringExtra("MvxLaunchData");
if (requestText == null)
return;
var viewDispatcher = Mvx.Resolve<IMvxViewDispatcher>();
var converter = Mvx.Resolve<IMvxNavigationSerializer>();
var request = converter.Serializer.DeserializeObject<MvxViewModelRequest>(requestText);
viewDispatcher.ShowViewModel(request);
}
最后一点,从 Android Oreo 开始,这种创建通知的特殊方式需要一个NotificationChannel。
关于android - MvvmCross 和 Android 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51216823/