Странный дескриптор должен быть допустимым исключением в диалоге - PullRequest
3 голосов
/ 15 апреля 2020

Я получаю сообщения о том, что в моем приложении происходит неправильное поведение. Я показываю syn c успешное диалоговое окно, чтобы пользователь знал, что его данные синхронизированы. Некоторые пользователи сказали, что они не получают syn c успешное диалоговое окно, а индикатор выполнения просто остается на 100% / 100%, и им нужно нажать обратно, чтобы выйти.

Проблема не легко воспроизвести На самом деле, я не могу этого сделать, но журналы, которые мы создаем и в которых используются исключения, показывают область, в которой возникла проблема.

using System;
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
using Classes;
using Microsoft.AppCenter.Crashes;
using Services;
using System.Threading;
using Helpers;

namespace Dialogs
{
    public class ProgressBarDialog : DialogFragment
    {
        private ProgressBar progressBar;
        private OnProgressFinished onProgressFinished;
        int _countSeconds;
        object _lock = new object();
        private TextView progressText;
        private LinearLayout titleBackground;
        private Button yes, no;
        private static string title, description;
        private OnItemClick callback;

        public interface OnItemClick
        {
            void OnItemClick(int id);
        }

        public interface OnProgressFinished
        {
            void OnProgressFinished(int id);
        }

        public static ProgressBarDialog NewInstance(Bundle bundle, string passedTitle, string passedDesc)
        {
            var fragment = new ProgressBarDialog();
            title = passedTitle;
            description = passedDesc;
            return fragment;
        }

        public override void OnAttach(Android.Content.Context context)
        {
            base.OnAttach(context);
            try
            {
                callback = (OnItemClick)context;
            }
            catch (Exception e)
            {
                Crashes.TrackError(e);
            }

            try
            {
                onProgressFinished = (OnProgressFinished)context;
            }
            catch (Exception e)
            {
                Crashes.TrackError(e);
            }
        }

        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            //return customview for the fragment
            View view = inflater.Inflate(Resource.Layout.ProgressDialog, container, false);
            progressBar = view.FindViewById<ProgressBar>(Resource.Id.progressBar1);
            progressText = view.FindViewById<TextView>(Resource.Id.progressText);
            progressBar.Max = 100;
            SampleDatabase db = new SampleDatabase();
            SampleRESTFulService save = new SampleRESTFulService(Activity);
            List<Sample> samples = db.Get();
            int sampleCount = samples.Count;

            if (sampleCount > 0)
            {
                Activity.RunOnUiThread(async () =>
                {
                    using (var cancellationTokenSource = new CancellationTokenSource())
                    {
                        cancellationTokenSource.CancelAfter(TimeSpan.FromMinutes(5));

                        try
                        {
                            int successfullySynced = 0;
                            foreach (Sample sample in samples.ToArray())
                            {
                                cancellationTokenSource.Token.ThrowIfCancellationRequested();
                                if (sample.Tag.Equals("NR"))
                                {
                                    db.Delete(sample);
                                }

                                bool isSuccess = await save.SaveAsync(sample, cancellationTokenSource.Token);
                                if (isSuccess)
                                {
                                    ++successfullySynced;
                                    db.Delete(sample);
                                    samples.Remove(sample);
                                    progressBar.Progress = successfullySynced * 100 / sampleCount;
                                    progressText.Text = progressBar.Progress.ToString() + "%";
                                }
                                else if (isSuccess == false && cancellationTokenSource.IsCancellationRequested)
                                {
                                    onProgressFinished.OnProgressFinished(1);
                                    Dismiss();
                                }

                                CheckProgress(progressBar.Progress);
                            }
                        }
                        catch (Exception ex)
                        {
                            LoggerHelper.LogUser("ProgressBarDialog OnCreateView Error", ex.ToString());

                            Console.WriteLine(ex);
                        }

                        if (cancellationTokenSource.IsCancellationRequested)
                        {
                            Dismiss();
                            onProgressFinished.OnProgressFinished(1);
                        }
                        else if (progressBar != null && progressBar.Progress < 100)
                        {
                            Dismiss();
                            onProgressFinished.OnProgressFinished(1);
                        }
                    }
                });
            }
            return view;
        }

        // This is the function where the exception is kicking off.
        public void CheckProgress(int progress)
        {
            try
            {
                lock (_lock)
                {
                    if (progress >= 100)
                    {
                        Dismiss();
                        onProgressFinished.OnProgressFinished(0);
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerHelper.LogUser("ProgressBarDialog CheckProgress Error", ex.ToString());
            }

        }
    }
}

Исключение, которое я получаю:

4/10/2020 1:15:58 PM] - System.ArgumentException: дескриптор должен быть действительным. Имя параметра: экземпляр в Java .Interop.JniEnvironment + InstanceMethods.CallObjectMethod (Java .Interop.JniObjectReference экземпляр, Java .Interop.JniMethodInfo метод, Java .Interop.JniArgumentValue * 000 в аргументах) 0) в аргументах) 8cb56b2f65354c9f9fbb25da78a6cf09>: 0 в Android .Runtime.JNIEnv.CallObjectMethod (метод задания System.IntPtr, метод System.IntPtr, Android .Runtime.JValue * parte * 0). PutString (ключ System.String, значение System.String) [0x0006c] в: 0 в Activity.SampleListActivity.OnProgressFinished (id System.Int32) [0x00154] в: 0 в Dialogs.ProgressBarDialog.CheckProgress (прогресс System.Int32) [0x00022 ] in: 0

Моя функция обратного вызова выглядит следующим образом:

public void OnProgressFinished(int id)
        {
            if (id == 1)
            {
                if (!IsFinishing && informDialog != null && IsForeground)
                {
                    editor.PutString("Name", "");
                    editor.Commit();
                    updateAdapter();
                    informDialog.Dismiss();

                    SampleDatabase sDb = new SampleDatabase();
                    if(sDb.Get().ToArray().Count() > 0)
                    {
                        TrySyncAgain();
                    }
                    else
                    {
                        if (!IsFinishing && informDialog != null && IsForeground)
                        {
                            editor.PutString("PASSEDHERD", "");
                            editor.Commit();
                            AlertDialog.Builder alert = new AlertDialog.Builder(this);
                            alert.SetTitle("Sync Successful");
                            alert.SetMessage("You're samples have been synced successfully.");
                            alert.SetPositiveButton("Yes", (senderAlert, args) =>
                            {
                                LoggerHelper.LogUser(passedHerd.Tech_ID, string.Format("{0} clicked OK on sync successful.", passedHerd.Tech_ID));
                                LoggerHelper.Log(passedHerd.Herd_Test_ID, String.Format("User: {0}, pressed Yes on sync successful", passedHerd.Tech_ID));
                                End(true);
                            });
                            Dialog dialog = alert.Create();
                            dialog.Show();
                        }
                    }

                }
            }
            else if (id == 0)
            {
                if (!IsFinishing && informDialog != null && IsForeground)
                {
                    editor.PutString("PASSEDHERD", "");
                    editor.Commit();
                    AlertDialog.Builder alert = new AlertDialog.Builder(this);
                    alert.SetTitle("Sync Successful");
                    alert.SetMessage("You're samples have been synced successfully.");
                    alert.SetPositiveButton("Yes", (senderAlert, args) =>
                    {
                        LoggerHelper.LogUser(passedHerd.Tech_ID, string.Format("{0} clicked OK on sync successful.", passedHerd.Tech_ID));
                        LoggerHelper.Log(passedHerd.Herd_Test_ID, String.Format("User: {0}, pressed Yes on sync successful", passedHerd.Tech_ID));
                        End(true);
                    });
                    Dialog dialog = alert.Create();
                    dialog.Show();
                }
            }
        }

Я попытался передать Null в обратный вызов, но он не будет принят из-за необходимого значения Int.

Любая помощь будет принята с благодарностью. Спасибо

Ответы [ 2 ]

0 голосов
/ 22 апреля 2020

Ошибка, по-видимому, связана с сборщиком мусора Tarjan, который был представлен в Xaramarin. Android версия 7 ("Cycle8"). Тем не менее, люди сообщают, что проблема возможна со старым сборщиком мусора, с меньшей вероятностью. Глядя на ваш код:

else if (id == 0)
{
    if (!IsFinishing && informDialog != null && IsForeground)
    {
        editor.PutString("PASSEDHERD", ""); //-- This is the line causing you issues.
        editor.Commit();
        ...
     }
}

Мне кажется, что в какой-то момент в системах с этой ошибкой сборщик мусора работает не в ту точку (возможно, когда в системе недостаточно памяти, но У меня нет возможности проверить это).

Кажется, есть несколько исправлений и обходных путей. Во-первых, добавьте флаг " MONO_GC_PARAMS = bridge-creation = old " в сборку, однако это только уменьшит частоту проблемы, но не удалит ее полностью. Далее следует использовать Xamarin. Android 7 («Цикл 7») или ниже, если проблема не возникает, однако это большое снижение, если вы используете обновление до текущей версии.

Наконец, есть исправление, исправленное в версии 0.9.0 Xamarin.Essentials, где они утверждали, что исправили проблему SharedPrefereces.

Вот мое исследование для этого: https://xamarin.github.io/bugzilla-archives/51/51478/bug.html https://xamarin.github.io/bugzilla-archives/47/47577/bug.html

https://github.com/xamarin/Essentials/issues/380 https://github.com/xamarin/Essentials/pull/386

0 голосов
/ 18 апреля 2020

Попробуйте использовать Firebase Testlab и установите Crashlytics. Это поможет вам увидеть в реальном времени, когда пользовательское приложение cra sh. Это мне очень помогло

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...