Запустите методы в фоновом режиме, которые находятся в ViewModels в Xamarin.ios - PullRequest
0 голосов
/ 25 июня 2018

Я работаю над приложением Xamarin.iOS. Я хочу, чтобы некоторая часть моих текущих функций также работала в фоновом режиме. У меня есть System.Timer, которое находится в App.cs(Load on start) и добавлено событие TimerElapsed в одном из viewcontroller, через который управление переходит к ViewModel по истечении таймера и выполняет все функции.

Теперь я хочу, чтобы та же функция работала в фоновом режиме, но не могла придумать, как этого добиться. Может ли кто-нибудь помочь мне в этом?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Backround ( при отправке приложения в фоновый режим с помощью кнопки home ) в IOS немного сложнее. Вы можете достичь несколькими способами

1) beginBackgroundTaskWithExpirationHandler, но имеет некоторое ограничение во времени

2) событие locationUpdate - но с таймером оно будет работать не очень хорошо. это более пригодно, когда вам нужно время от времени проверять что-либо

3) Сделай себе приложение Player. Плеер может работать даже в фоновом режиме

Я использую метод 3, и он прекрасно работает для меня

Вам необходимо добавить разрешение для фонового звука в файле plist

<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
</array>

Тогда в вашем AppDelegate вам нужно изменить FinishedLaunching метод

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        ...
        var currentSession = AVAudioSession.SharedInstance();
        currentSession.SetCategory(AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.MixWithOthers);
        currentSession.SetActive(true);
        ...

    }

И добавить следующий раздел, я тоже вставил в AppDelegat

    #region Background Work

    private BackgroundTask _backgroundTask;

    private readonly Lazy<TouchLogger> _logger = new Lazy<TouchLogger>(() => new TouchLogger());

    public override  void DidEnterBackground(UIApplication uiApplication)
    {
        base.DidEnterBackground(uiApplication);
        startBackgroundTask();
    }      


    public override void WillEnterForeground(UIApplication uiApplication)
    {
        base.WillEnterForeground(uiApplication);

        if (_backgroundTask == null)
        {
            _backgroundTask = new BackgroundTask(_logger.Value);
        }
        else if (_backgroundTask.IsRunned)
        {
            _backgroundTask.Stop();
            _logger.Value.Info("Background", "Task stopped");
        }
    }

    private void startBackgroundTask()
    {
        _logger.Value.Info("Background", "startBackgroundTask() called");

        var needBackgroundActivity = true;// if you timer is running set true, if not false

        if (needBackgroundActivity)
        {
            if (_backgroundTask == null)
                _backgroundTask = new BackgroundTask(_logger.Value);

            _backgroundTask.Start();

            _logger.Value.Info("Background", "Task runned");
        }
    }

    private class BackgroundTask
    {
        private const string EmptySoundFileName = "Sounds/empty";//wav file, I use 4 sec long file with no sound

        private TouchLogger _logger;

        private AVAudioPlayer _player;

        private NSTimer _debugTimer;

        public bool IsRunned { get; private set; }

        public BackgroundTask(TouchLogger logger)
        {
            _logger = logger;
        }

        public void Start()
        {
            IsRunned = true;

            if (_player != null && _player.Playing)
            {
                Stop();
            }

            var bundle = NSBundle.MainBundle.PathForResource(EmptySoundFileName, "wav");
            var sound = new NSUrl(bundle);


            _player = AVAudioPlayer.FromUrl(sound);
            _player.NumberOfLoops = -1;
            _player.Volume = 0.1f;
            _player.PrepareToPlay();
            _player.Play();
            startDebugTimer();
        }

        public void Stop()
        {
            IsRunned = false;

            if (_player != null && _player.Playing)
            {
                _player.Stop();
                _player.Dispose();
                _player = null;
            }
            stopTimer(ref _debugTimer);
        }

        private void startDebugTimer()
        {
            initAndStartTimer(ref _debugTimer, 5,
                () => _logger.Value.Info("Background", "Background is fine!"));
        }

        private void initAndStartTimer(ref NSTimer timer, int intervalMin, Action action)
        {
            timer?.Invalidate();
            if (action != null)
                timer =
                    NSTimer.CreateRepeatingScheduledTimer(
                        TimeSpan.FromMinutes(intervalMin),
                        t => action());
        }



        private void stopTimer(ref NSTimer timer)
        {
            timer?.Invalidate();
            timer = null;
        }

    }

    #endregion      

TouchLogger - отправьте несколько сообщений на консоль, для проверки фона вы можете удалить их. То же самое с _debugTimer, это просто записывает состояние фонового рабочего каждые 5 минут.

Если что-то не работает, скажите мне, я сделал это давным-давно, поэтому, возможно, что-то пропустил

0 голосов
/ 25 июня 2018

Самый простой способ сделать это будет что-то вроде этого

// Какой-то асинхронный метод

await Task.Run(async () =>
{
 // Code you want to run asynchronously 
 });

Гудлак!

В случае запроса вернуться!

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