【问题标题】:Xamarin Android Unfortunately App has StoppedXamarin Android 不幸的是应用程序已停止
【发布时间】:2014-09-28 13:36:06
【问题描述】:

我正在使用 Xamarin Android 开发 Android 应用程序。

我正在尝试通过

捕获全局异常
AndroidEnvironment.UnhandledExceptionRaiser += (sender, args) =>
            {
               //WRITE TO FILE
            };
            AppDomain.CurrentDomain.UnhandledException += (s, e) =>
            {
                /*
                 * When a background thread crashes this is the code that will be executed. You can
                 * recover from this.
                 */
            };

我仍然经常在各种设备上收到“不幸的是,应用程序已停止错误”。错误没有被捕获。

我怀疑是内存泄漏,但我不确定。我无法访问经常引发此错误的设备的 logcat 文件。我无计可施。任何人都可以对此有所了解吗?

附带说明,如果引发并捕获了全局异常,则 UnhandledExceptionRaiser 会在两者之间中断并且不会写入文件(我猜这是因为 Android 清理了进程?)

【问题讨论】:

  • @MysticMagic 你读过这个问题吗?
  • 是的。我读。我也读到了“错误没有被捕获”。但这无助于我们帮助你.. 所以无论如何,祝你好运。 :)
  • 那么,你让它工作了吗? @AniketSharma
  • @Alex.F 不。什么都试过了。应用程序仍然崩溃并且未调用未处理的异常引发程序。我仍在尝试不同的方法和技巧来解决问题。

标签: android xamarin xamarin.android


【解决方案1】:

分析 Google 崩溃报告后,我发现了实际错误。

11-12 22:36:31.410: E/AndroidRuntime(4835): FATAL EXCEPTION: main
11-12 22:36:31.410: E/AndroidRuntime(4835): java.lang.RuntimeException: Unable to start activity 
ComponentInfo{com.apptimator.pro.mayusha/com.apptimator.mayusha.HomeActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@42ab6ad8: Unmarshalling unknown type code 7209057 at offset 1064

......
11-12 22:36:31.410: E/AndroidRuntime(4835): Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@42ab6ad8: Unmarshalling unknown type code 7209057 at offset 1064
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.os.Parcel.readValue(Parcel.java:2038)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.os.Parcel.readMapInternal(Parcel.java:2255)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.os.Bundle.unparcel(Bundle.java:223)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.os.Bundle.getSparseParcelableArray(Bundle.java:1237)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:1969)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.app.Activity.onRestoreInstanceState(Activity.java:977)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.app.Activity.performRestoreInstanceState(Activity.java:949)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1155)
11-12 22:36:31.410: E/AndroidRuntime(4835):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2271)

此错误可能是由 this ("Proguard Causing Runtime exception") 引起的,或者在此 Xamarin Android 案例中,由于嵌套的保存状态实现,android 无法恢复保存的实例状态。

我在 Home Activity 中使用 SlidingMenuSharp(SlidingMenuSharp link) 库,它正在实现 IParcelable 并使用嵌套的 SavedState 类。可以找到相同的错误 here

不过,我设法修复了它,现在一切正常。要修复该错误,请按照提到的 SavedState、OnRestoreInstanceState 和 OnSaveInstanceState 的 Bundle 实现

public class SavedState : BaseSavedState
    {
        public int Item { get; private set; }

        public SavedState(IParcelable superState)
            : base(superState)
        {

        }

        public SavedState(Parcel parcel)
            : base(parcel)
        {
            Item = parcel.ReadInt();
        }

        public override void WriteToParcel(Parcel dest, ParcelableWriteFlags flags)
        {
            base.WriteToParcel(dest, flags);
            dest.WriteInt(Item);
        }

        [ExportField("CREATOR")]
        static SavedStateCreator InitializeCreator()
        {
            return new SavedStateCreator();
        }

        class SavedStateCreator : Java.Lang.Object, IParcelableCreator
        {
            public Java.Lang.Object CreateFromParcel(Parcel source)
            {
                return new SavedState(source);
            }

            public Java.Lang.Object[] NewArray(int size)
            {
                return new SavedState[size];
            }
        }
    }

    protected override void OnRestoreInstanceState(IParcelable state)
    {
        try
        {
            Bundle bundle = state as Bundle;
            if (bundle != null)
            {
                IParcelable superState = (IParcelable)bundle.GetParcelable("base");
                if (superState != null)
                    base.OnRestoreInstanceState(superState);
                _viewAbove.SetCurrentItem(bundle.GetInt("currentPosition", 0));
            }
        }
        catch
        {
            base.OnRestoreInstanceState(state);
            // Ignore, this needs to support IParcelable...
        }
    }

    protected override IParcelable OnSaveInstanceState()
    {
        var superState = base.OnSaveInstanceState();
        Bundle state = new Bundle();
        state.PutParcelable("base", superState);
        state.PutInt("currentPosition", _viewAbove.GetCurrentItem());

        return state;
    }

【讨论】:

  • 这也适用于 Xamarin 示例中的 CirclePageIndicator - 他们的 OnRestoreInstanceState 和 OnSaveInstanceState 在“Unmarshalling unknown type code”上崩溃的实现,您的方法有效
  • @rouen 请向他们报告/创建拉取请求 :)
  • 查看此解决方案后,我意识到我应该重新启动设备,这为我解决了问题。不知道是不是同一个问题。
  • @BlueRaja-DannyPflughoeft 不确定重启方法。您不能依赖用户重新启动设备。尽管如此,这个问题得到了确认,并且一个拉取请求被接受了:)
【解决方案2】:

您不应使用 AppDomain.CurrentDomain.UnhandledException 作为拦截未处理异常的方式,如 Xamarin docs 中所述:

注意:您不能依赖 AppDomain.UnhandledException 事件作为 MonoDroid 中永远不会处理托管异常;他们总是 在 catch(Exception) 内的 Android/托管边界处截获 块。

我建议继续使用AndroidEnvironment.UnhandledExceptionRaiser 并尽可能保持那里的操作效率。

还可以使用TaskScheduler.UnobservedTaskException 捕获后台线程中发生且未观察到的异常(并且不会导致未处理的异常)。

最后,我订阅了我的应用程序类(继承自 Android.App.Application 的类)中的所有异常处理事件,因为它是应用程序的第一个入口点,您甚至可以在主要活动之前出现异常开始(或从现在开始订阅的任何地方)

附:我也使用TaskScheduler.UnobservedTaskException 只是为了安全起见,但还没有发现任何异常。

【讨论】:

  • 我在我的应用程序类中使用 AndroidEnvironment.UnhandledExceptionRaiser。为了安全起见,我刚刚放入了 AppDomain.CurrentDomain.UnhandledException。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
相关资源
最近更新 更多