Xamarin Android不幸的是App已经停止了

时间:2014-09-28 13:36:06

标签: android xamarin xamarin.android

我正在使用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会清理进程吗?)

2 个答案:

答案 0 :(得分:3)

在分析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案例中导致,由于嵌套的保存状态实现而无法恢复已保存的实例状态。

我在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;
    }

答案 1 :(得分:0)

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

  

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

我建议继续使用AndroidEnvironment.UnhandledExceptionRaiser并尽可能高效地保持操作。

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

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

P.S。我也使用TaskScheduler.UnobservedTaskException只是为了安全起见,但从来没有发现任何例外。