【发布时间】:2020-04-30 13:17:52
【问题描述】:
在将我的应用程序从 Xamarin.Forms 4.1.0.709244 升级到 4.2.0.709249(或任何更新的软件包版本)后,以前可以正常工作的代码现在不再工作和崩溃,但仅在一种特定情况下。
我的应用通过 OneSignal 包接收推送通知,预期的行为是:
- 通知到达并打开
- 通知打开处理程序将有效负载保存到
App类参数并设置Application.Current.MainPage = new MainPage(); -
MainPage初始化程序中的逻辑解析负载以确定用户需要导航到哪个页面,并为该新页面创建一个 Page 对象。 -
Detail页面设置为新页面
在 4.1 下,这按预期工作。点击通知,用户将在所有场景下被带到应用程序中的相应页面。升级到 4.2+ 后,如果应用当前未运行,此方案会失败,但如果应用正在运行且在前台或后台运行,则此方案可以正常工作。
当它失败时,不是应用程序加载,然后用户被带到正确的页面,而是应用程序加载但只是坐在默认主页上(好像 Detail 没有使用来自的信息设置通知有效负载)。同样,此时如果您点击汉堡图标,导航菜单会短暂显示,应用程序会立即崩溃,并出现如下所示的空引用异常:
System.NullReferenceException:对象引用未设置为对象的实例 在 Xamarin.Forms.Platform.Android.AppCompat.Platform.Xamarin.Forms.Platform.Android.IPlatformLayout.OnLayout (System.Boolean 更改,System.Int32 l,System.Int32 t,System.Int32 r,System.Int32 b) [0x0002b] 在 :0 在 Xamarin.Forms.Platform.Android.PlatformRenderer.OnLayout(System.Boolean 已更改,System.Int32 l,System.Int32 t,System.Int32 r,System.Int32 b)[0x00025] 在 :0 在 Android.Views.ViewGroup.n_OnLayout_ZIIII (System.IntPtr jnienv, System.IntPtr native__this, System.Boolean changed, System.Int32 l, System.Int32 t, System.Int32 r, System.Int32 b) [0x00009] 在 :0 在(包装器动态方法)Android.Runtime.DynamicMethodNameCounter.28(intptr,intptr,bool,int,int,int,int)
由于这种情况仅在应用程序关闭并通过通知操作启动时才会发生,因此我无法使用 Visual Studio 调试器准确识别异常发生的位置。我使用 Microsoft AppCenter 添加了许多事件,这些事件将通过各种方法跟踪进度,然后报告逻辑流中发生崩溃的位置,但所有预期的步骤都在完成。正在调用将Detail 页面设置为新页面的步骤,并且在点击汉堡图标时调用的isPresentedChanged 处理程序也正在运行完成。
我已经查看了 4.2 here 的发行说明,虽然有一些与页面布局相关的修复可能与崩溃有关,但我觉得崩溃更像是与我需要彻底解决的问题相比,详细信息页面的更改没有正确发生的症状。我发现向 Xamarin 团队报告了一些类似的错误,但它们都已解决,并且不是完全相同的问题。请参阅here、here、here、here 和 here。
NotificationServices.cs(OneSignal 的服务扩展;无论通过哪个 userNotificationType,代码现在都会失败):
public class NotificationServices
{
public static void HandleNotificationOpened(OSNotificationOpenedResult result)
{
string notificationActionId = "HandleMessage";
OSNotificationPayload payload = result.notification.payload;
string message = payload.body;
App.NotificationActionId = notificationActionId;
App.NotificationData = payload.additionalData;
Application.Current.MainPage = new MainPage();
}
public static Page GetPageFromNotificationData()
{
Page ReturnPage;
ApiServices _apiServices = new ApiServices(); //service to make REST calls to backend system
user_notification_type userNotificationType = user_notification_type.None;
int fromUserId = 0;
int assocId = 0;
int msgId = 0;
if (App.NotificationData != null)
{
if (App.NotificationData.ContainsKey("assocId"))
{
Int32.TryParse(Convert.ToString(App.NotificationData["assocId"]), out assocId);
}
if (App.NotificationData.ContainsKey("fromUserId"))
{
Int32.TryParse(Convert.ToString(App.NotificationData["fromUserId"]), out fromUserId);
}
if (App.NotificationData.ContainsKey("msgId"))
{
Int32.TryParse(Convert.ToString(App.NotificationData["msgId"]), out msgId);
}
if (App.NotificationData.ContainsKey("userNotificationType"))
{
int unInt = 0;
Int32.TryParse(Convert.ToString(App.NotificationData["userNotificationType"]), out unInt);
userNotificationType = (user_notification_type)unInt;
}
}
switch (userNotificationType)
{
case user_notification_type.ChatMessage:
TeamBasic tm = new TeamBasic();
tm.OwnerID = fromUserId;
tm.OwnerName = _apiServices.GetUserName(fromUserId).Result;
ReturnPage = new ChatPage(tm);
break;
case user_notification_type.None:
ReturnPage = default(Page);
break;
default:
UserNotification unItem = new UserNotification();
var unList = _apiServices.GetUserNotifications(assocId, msgId+1, 1).Result;
unItem = unList[0];
UserNotificationDetailViewModel undVm = new UserNotificationDetailViewModel(unItem);
ReturnPage = new UserNotificationDetailPage(undVm);
break;
}
return ReturnPage;
}
}
Mainpage.xaml.cs:
public partial class MainPage : MasterDetailPage
{
private IHubServices _hubServices;
Dictionary<int, NavigationPage> MenuPages = new Dictionary<int, NavigationPage>();
public MainPage()
{
InitializeComponent();
_hubServices = DependencyService.Get<IHubServices>(); //signalR
_hubServices.Connect();
_hubServices.ClearPageCache += ClearPageCache;
MasterBehavior = MasterBehavior.Popover;
NavigationPage navPage = (NavigationPage)Detail;
ConnectionState cs = _hubServices.GetConnectionState().Result;
if (cs == ConnectionState.Connected)
{
var pg = NotificationServices.GetPageFromNotificationData(); //call to get page as specified per notification
Detail = new NavigationPage(pg); //this is where the Detail page should be getting updated but is acting like it isn't when the app is started by the act of opening the notification
MenuPages.Add((int)MenuItemType.LogOut, (NavigationPage)Detail);
}
else
{
App.CheckForNotificationRedirect = true;
MenuPages.Add((int)MenuItemType.About, (NavigationPage)Detail);
}
IsPresentedChanged += (sender, args) =>
{
try {
//anything
}
catch (Exception ex)
{
//anything
}
//it is after this has completed executing that the app is crashing. No exception ever occurs in the try/catch
};
}
}
App Center 提供的完整转储:
Xamarin 异常堆栈: System.NullReferenceException:对象引用未设置为对象的实例 在 Xamarin.Forms.Platform.Android.AppCompat.Platform.Xamarin.Forms.Platform.Android.IPlatformLayout.OnLayout (System.Boolean 改变,System.Int32 l,System.Int32 t,System.Int32 r, System.Int32 b) [0x0002b] in :0 在 Xamarin.Forms.Platform.Android.PlatformRenderer.OnLayout (System.Boolean 更改,System.Int32 l,System.Int32 t,System.Int32 r, System.Int32 b) [0x00025] in :0 在 Android.Views.ViewGroup.n_OnLayout_ZIIII (System.IntPtr jnienv, System.IntPtr native__this, System.Boolean 改变, System.Int32 l, System.Int32 t, System.Int32 r, System.Int32 b) [0x00009] 在 :0 在(包装器动态方法)Android.Runtime.DynamicMethodNameCounter.28(intptr,intptr,bool,int,int,int,int)
Thread 2: 0 dalvik.system.VMStack.getThreadStackTrace(VMStack.java:-2) 1 java.lang.Thread.getStackTrace(Thread.java:1538) 2 java.lang.Thread.getAllStackTraces(Thread.java:1588) 3 com.microsoft.appcenter.crashes.Crashes.saveUncaughtException(Crashes.java:1093) 4 com.microsoft.appcenter.crashes.WrapperSdkExceptionManager.saveWrapperException(WrapperSdkExceptionManager.java:58) 5 crc643f46942d9dd1fff9.PlatformRenderer.n_onLayout(PlatformRenderer.java:-2) 6 crc643f46942d9dd1fff9.PlatformRenderer.onLayout(PlatformRenderer.java:55) 7 android.view.View.layout(View.java:20740) 8 android.view.ViewGroup.layout(ViewGroup.java:6268) 9 android.widget.RelativeLayout.onLayout(RelativeLayout.java:1084) 10 android.view.View.layout(View.java:20740) 11 android.view.ViewGroup.layout(ViewGroup.java:6268) 12 android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 13 android.widget.FrameLayout.onLayout(FrameLayout.java:261) 14 android.view.View.layout(View.java:20740) 15 android.view.ViewGroup.layout(ViewGroup.java:6268) 16 android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 17 android.widget.FrameLayout.onLayout(FrameLayout.java:261) 18 android.view.View.layout(View.java:20740) 19 android.view.ViewGroup.layout(ViewGroup.java:6268) 20 android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 21 android.widget.FrameLayout.onLayout(FrameLayout.java:261) 22 android.view.View.layout(View.java:20740) 23 android.view.ViewGroup.layout(ViewGroup.java:6268) 24 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812) 25 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656) 26 android.widget.LinearLayout.onLayout(LinearLayout.java:1565) 27 android.view.View.layout(View.java:20740) 28 android.view.ViewGroup.layout(ViewGroup.java:6268) 29 android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 30 android.widget.FrameLayout.onLayout(FrameLayout.java:261) 31 com.android.internal.policy.DecorView.onLayout(DecorView.java:794) 32 android.view.View.layout(View.java:20740) 33 android.view.ViewGroup.layout(ViewGroup.java:6268) 34 android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2970) 35 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2465) 36 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1571) 37 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7616) 38 android.view.Choreographer$CallbackRecord.run(Choreographer.java:1034) 39 android.view.Choreographer.doCallbacks(Choreographer.java:845) 40 android.view.Choreographer.doFrame(Choreographer.java:780) 41 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1020) 42 android.os.Handler.handleCallback(Handler.java:873) 43 android.os.Handler.dispatchMessage(Handler.java:99) 44 android.os.Looper.loop(Looper.java:205) 45 android.app.ActivityThread.main(ActivityThread.java:6991) 46 java.lang.reflect.Method.invoke(Method.java:-2) 47 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 48 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884) Thread 41398: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:178) 2 java.lang.Daemons$Daemon.run(Daemons.java:103) 3 java.lang.Thread.run(Thread.java:764) Thread 41399: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Object.wait(Object.java:422) 2 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:188) 3 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:209) 4 java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:232) 5 java.lang.Daemons$Daemon.run(Daemons.java:103) 6 java.lang.Thread.run(Thread.java:764) Thread 41400: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:297) 2 java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:277) 3 java.lang.Daemons$Daemon.run(Daemons.java:103) 4 java.lang.Thread.run(Thread.java:764) Thread 41415: 0 java.lang.Object.wait(Object.java:-2) 1 com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:103) 2 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 3 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 4 java.lang.Thread.run(Thread.java:764) Thread 41416: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41417: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41419: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41420: 0 java.lang.Object.wait(Object.java:-2) 1 com.android.okhttp.okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:323) 2 com.android.okhttp.okio.AsyncTimeout.access$000(AsyncTimeout.java:40) 3 com.android.okhttp.okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:286) Thread 41421: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41424: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41425: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41431: 0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2) 1 android.os.MessageQueue.next(MessageQueue.java:326) 2 android.os.Looper.loop(Looper.java:170) 3 android.os.HandlerThread.run(HandlerThread.java:65) Thread 41469: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Thread.parkFor$(Thread.java:2137) 2 sun.misc.Unsafe.park(Unsafe.java:358) 3 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230) 4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2101) 5 java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467) 6 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1091) 7 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152) 8 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 9 com.google.android.gms.common.util.concurrent.zza.run 10 java.lang.Thread.run(Thread.java:764) Thread 41470: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Thread.parkFor$(Thread.java:2137) 2 sun.misc.Unsafe.park(Unsafe.java:358) 3 java.util.concurrent.locks.LockSupport.park(LockSupport.java:190) 4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2059) 5 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1120) 6 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:849) 7 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1092) 8 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152) 9 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 10 com.google.android.gms.common.util.concurrent.zza.run 11 java.lang.Thread.run(Thread.java:764) Thread 41478: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Thread.parkFor$(Thread.java:2137) 2 sun.misc.Unsafe.park(Unsafe.java:358) 3 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230) 4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2101) 5 java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467) 6 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1091) 7 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152) 8 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 9 java.lang.Thread.run(Thread.java:764) Thread 41483: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Thread.parkFor$(Thread.java:2137) 2 sun.misc.Unsafe.park(Unsafe.java:358) 3 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230) 4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2101) 5 java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467) 6 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1091) 7 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152) 8 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 9 java.lang.Thread.run(Thread.java:764) Thread 41495: 0 java.lang.Object.wait(Object.java:-2) 1 java.lang.Thread.parkFor$(Thread.java:2137) 2 sun.misc.Unsafe.park(Unsafe.java:358) 3 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230) 4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2101) 5 java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467) 6 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1091) 7 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152) 8 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 9 java.lang.Thread.run(Thread.java:764)
【问题讨论】:
标签: android xamarin xamarin.forms onesignal