0

У меня есть список со словами (около 200), которые я хочу играть в плеер. Эти слова воспроизводятся из SpeechSynthesisStream. Когда я запускаю его на своем ПК, все слова играют идеально, но в моем телефоне играют только одно слово и не переходят к следующему.BackgroundAudio не работает в windows 10 mobile

#region Helper methods 

    string GetCurrentTrackId() 
    { 
     if (playbackList == null) 
      return null; 

     return GetTrackId(playbackList.CurrentItem); 
    } 

    string GetTrackId(MediaPlaybackItem item) 
    { 
     if (item == null) 
      return null; // no track playing 

     return item.Source.CustomProperties[TitleKey] as string; 
    } 
    #endregion 

    #region IBackgroundTask and IBackgroundTaskInstance Interface Members and handlers 
    /// <summary> 
    /// The Run method is the entry point of a background task. 
    /// </summary> 
    /// <param name="taskInstance"></param> 
    public void Run(IBackgroundTaskInstance taskInstance) 
    { 
     Debug.WriteLine("Background Audio Task " + taskInstance.Task.Name + " starting..."); 

     // Initialize SystemMediaTransportControls (SMTC) for integration with 
     // the Universal Volume Control (UVC). 
     // 
     // The UI for the UVC must update even when the foreground process has been terminated 
     // and therefore the SMTC is configured and updated from the background task. 
     smtc = BackgroundMediaPlayer.Current.SystemMediaTransportControls; 
     smtc.ButtonPressed += smtc_ButtonPressed; 
     smtc.PropertyChanged += smtc_PropertyChanged; 
     smtc.IsEnabled = true; 
     smtc.IsPauseEnabled = true; 
     smtc.IsPlayEnabled = true; 
     smtc.IsNextEnabled = true; 
     smtc.IsPreviousEnabled = true; 

     // Read persisted state of foreground app 
     var value = ApplicationSettingsHelper.ReadResetSettingsValue(ApplicationSettingsConstants.AppState); 
     if (value == null) 
      foregroundAppState = AppState.Unknown; 
     else 
      foregroundAppState = EnumHelper.Parse<AppState>(value.ToString()); 

     // Add handlers for MediaPlayer 
     BackgroundMediaPlayer.Current.CurrentStateChanged += Current_CurrentStateChanged; 

     // Initialize message channel 
     BackgroundMediaPlayer.MessageReceivedFromForeground += BackgroundMediaPlayer_MessageReceivedFromForeground; 

     // Send information to foreground that background task has been started if app is active 
     if (foregroundAppState != AppState.Suspended) 
      MessageService.SendMessageToForeground(new BackgroundAudioTaskStartedMessage()); 

     ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.BackgroundTaskState, BackgroundTaskState.Running.ToString()); 

     deferral = taskInstance.GetDeferral(); // This must be retrieved prior to subscribing to events below which use it 

     // Mark the background task as started to unblock SMTC Play operation (see related WaitOne on this signal) 
     backgroundTaskStarted.Set(); 

     // Associate a cancellation and completed handlers with the background task. 
     taskInstance.Task.Completed += TaskCompleted; 
     taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled); // event may raise immediately before continung thread excecution so must be at the end 
    } 

    /// <summary> 
    /// Indicate that the background task is completed. 
    /// </summary>  
    void TaskCompleted(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args) 
    { 
     Debug.WriteLine("MyBackgroundAudioTask " + sender.TaskId + " Completed..."); 
     deferral.Complete(); 
    } 

    /// <summary> 
    /// Handles background task cancellation. Task cancellation happens due to: 
    /// 1. Another Media app comes into foreground and starts playing music 
    /// 2. Resource pressure. Your task is consuming more CPU and memory than allowed. 
    /// In either case, save state so that if foreground app resumes it can know where to start. 
    /// </summary> 
    private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) 
    { 
     // You get some time here to save your state before process and resources are reclaimed 
     Debug.WriteLine("MyBackgroundAudioTask " + sender.Task.TaskId + " Cancel Requested..."); 
     try 
     { 
      // immediately set not running 
      backgroundTaskStarted.Reset(); 

      // save state 
      ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.TrackId, GetCurrentTrackId() == null ? null : GetCurrentTrackId().ToString()); 
      ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.Position, BackgroundMediaPlayer.Current.Position.ToString()); 
      ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.BackgroundTaskState, BackgroundTaskState.Canceled.ToString()); 
      ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.AppState, Enum.GetName(typeof(AppState), foregroundAppState)); 

      // unsubscribe from list changes 
      if (playbackList != null) 
      { 
       playbackList.CurrentItemChanged -= PlaybackList_CurrentItemChanged; 
       playbackList = null; 
      } 

      // unsubscribe event handlers 
      BackgroundMediaPlayer.MessageReceivedFromForeground -= BackgroundMediaPlayer_MessageReceivedFromForeground; 
      smtc.ButtonPressed -= smtc_ButtonPressed; 
      smtc.PropertyChanged -= smtc_PropertyChanged; 

      BackgroundMediaPlayer.Shutdown(); // shutdown media pipeline 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex.ToString()); 
     } 
     deferral.Complete(); // signals task completion. 
     Debug.WriteLine("MyBackgroundAudioTask Cancel complete..."); 
    } 
    #endregion 

    #region SysteMediaTransportControls related functions and handlers 
    /// <summary> 
    /// Update Universal Volume Control (UVC) using SystemMediaTransPortControl APIs 
    /// </summary> 
    private void UpdateUVCOnNewTrack(MediaPlaybackItem item) 
    { 
     if (item == null) 
     { 
      smtc.PlaybackStatus = MediaPlaybackStatus.Stopped; 
      smtc.DisplayUpdater.MusicProperties.Title = string.Empty; 
      smtc.DisplayUpdater.Update(); 
      return; 
     } 

     smtc.PlaybackStatus = MediaPlaybackStatus.Playing; 
     smtc.DisplayUpdater.Type = MediaPlaybackType.Music; 
     smtc.DisplayUpdater.MusicProperties.Title = item.Source.CustomProperties[TitleKey] as string; 

     var albumArtUri = item.Source.CustomProperties[AlbumArtKey] as Uri; 
     if (albumArtUri != null) 
      smtc.DisplayUpdater.Thumbnail = RandomAccessStreamReference.CreateFromUri(albumArtUri); 
     else 
      smtc.DisplayUpdater.Thumbnail = null; 

     smtc.DisplayUpdater.Update(); 
    } 

    /// <summary> 
    /// Fires when any SystemMediaTransportControl property is changed by system or user 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="args"></param> 
    void smtc_PropertyChanged(SystemMediaTransportControls sender, SystemMediaTransportControlsPropertyChangedEventArgs args) 
    { 
     // If soundlevel turns to muted, app can choose to pause the music 
    } 

    /// <summary> 
    /// This function controls the button events from UVC. 
    /// This code if not run in background process, will not be able to handle button pressed events when app is suspended. 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="args"></param> 
    private void smtc_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args) 
    { 
     switch (args.Button) 
     { 
      case SystemMediaTransportControlsButton.Play: 
       Debug.WriteLine("UVC play button pressed"); 

       // When the background task has been suspended and the SMTC 
       // starts it again asynchronously, some time is needed to let 
       // the task startup process in Run() complete. 

       // Wait for task to start. 
       // Once started, this stays signaled until shutdown so it won't wait 
       // again unless it needs to. 
       bool result = backgroundTaskStarted.WaitOne(5000); 
       if (!result) 
        throw new Exception("Background Task didnt initialize in time"); 

       StartPlayback(); 
       break; 
      case SystemMediaTransportControlsButton.Pause: 
       Debug.WriteLine("UVC pause button pressed"); 
       try 
       { 
        BackgroundMediaPlayer.Current.Pause(); 
       } 
       catch (Exception ex) 
       { 
        Debug.WriteLine(ex.ToString()); 
       } 
       break; 
      case SystemMediaTransportControlsButton.Next: 
       Debug.WriteLine("UVC next button pressed"); 
       SkipToNext(); 
       break; 
      case SystemMediaTransportControlsButton.Previous: 
       Debug.WriteLine("UVC previous button pressed"); 
       SkipToPrevious(); 
       break; 
     } 
    } 



    #endregion 

    #region Playlist management functions and handlers 
    /// <summary> 
    /// Start playlist and change UVC state 
    /// </summary> 
    private void StartPlayback() 
    { 
     try 
     { 
      // If playback was already started once we can just resume playing. 
      if (!playbackStartedPreviously) 
      { 
       playbackStartedPreviously = true; 

       // If the task was cancelled we would have saved the current track and its position. We will try playback from there. 
       var currentTrackId = ApplicationSettingsHelper.ReadResetSettingsValue(ApplicationSettingsConstants.TrackId); 
       var currentTrackPosition = ApplicationSettingsHelper.ReadResetSettingsValue(ApplicationSettingsConstants.Position); 
       if (currentTrackId != null) 
       { 
        // Find the index of the item by name 
        var index = playbackList.Items.ToList().FindIndex(item => 
         GetTrackId(item).ToString() == (string)currentTrackId); 

        if (currentTrackPosition == null) 
        { 
         // Play from start if we dont have position 
         Debug.WriteLine("StartPlayback: Switching to track " + index); 
         playbackList.MoveTo((uint)index); 

         // Begin playing 
         BackgroundMediaPlayer.Current.Play(); 
        } 
        else 
        { 
         // Play from exact position otherwise 
         TypedEventHandler<MediaPlaybackList, CurrentMediaPlaybackItemChangedEventArgs> handler = null; 
         handler = (MediaPlaybackList list, CurrentMediaPlaybackItemChangedEventArgs args) => 
         { 
          if (args.NewItem == playbackList.Items[index]) 
          { 
           // Unsubscribe because this only had to run once for this item 
           playbackList.CurrentItemChanged -= handler; 

           // Set position 
           var position = TimeSpan.Parse((string)currentTrackPosition); 
           Debug.WriteLine("StartPlayback: Setting Position " + position); 
           BackgroundMediaPlayer.Current.Position = position; 

           // Begin playing 
           BackgroundMediaPlayer.Current.Play(); 
          } 
         }; 
         playbackList.CurrentItemChanged += handler; 

         // Switch to the track which will trigger an item changed event 
         Debug.WriteLine("StartPlayback: Switching to track " + index); 
         playbackList.MoveTo((uint)index); 
        } 
       } 
       else 
       { 
        // Begin playing 
        BackgroundMediaPlayer.Current.Play(); 
       } 
      } 
      else 
      { 
       // Begin playing 
       BackgroundMediaPlayer.Current.Play(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex.ToString()); 
     } 
    } 

    /// <summary> 
    /// Raised when playlist changes to a new track 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="args"></param> 
    void PlaybackList_CurrentItemChanged(MediaPlaybackList sender, CurrentMediaPlaybackItemChangedEventArgs args) 
    { 
     // Get the new item 
     var item = args.NewItem; 
     Debug.WriteLine("PlaybackList_CurrentItemChanged: " + (item == null ? "null" : GetTrackId(item).ToString())); 

     // Update the system view 
     UpdateUVCOnNewTrack(item); 

     // Get the current track 
     string currentTrackId = null; 
     if (item != null) 
      currentTrackId = item.Source.CustomProperties[TrackIdKey] as string; 

     // Notify foreground of change or persist for later 
     if (foregroundAppState == AppState.Active) 
      MessageService.SendMessageToForeground(new TrackChangedMessage(currentTrackId)); 
     else 
      ApplicationSettingsHelper.SaveSettingsValue(TrackIdKey, currentTrackId == null ? null : currentTrackId.ToString()); 
    } 

    /// <summary> 
    /// Skip track and update UVC via SMTC 
    /// </summary> 
    private void SkipToPrevious() 
    { 
     smtc.PlaybackStatus = MediaPlaybackStatus.Changing; 
     playbackList.MovePrevious(); 
    } 

    /// <summary> 
    /// Skip track and update UVC via SMTC 
    /// </summary> 
    private void SkipToNext() 
    { 
     smtc.PlaybackStatus = MediaPlaybackStatus.Changing; 
     playbackList.MoveNext(); 
    } 
    #endregion 

    #region Background Media Player Handlers 
    void Current_CurrentStateChanged(MediaPlayer sender, object args) 
    { 
     if (sender.CurrentState == MediaPlayerState.Playing) 
     { 
      smtc.PlaybackStatus = MediaPlaybackStatus.Playing; 
     } 
     else if (sender.CurrentState == MediaPlayerState.Paused) 
     { 
      smtc.PlaybackStatus = MediaPlaybackStatus.Paused; 
     } 
     else if (sender.CurrentState == MediaPlayerState.Closed) 
     { 
      smtc.PlaybackStatus = MediaPlaybackStatus.Closed; 
     } 
    } 

    /// <summary> 
    /// Raised when a message is recieved from the foreground app 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void BackgroundMediaPlayer_MessageReceivedFromForeground(object sender, MediaPlayerDataReceivedEventArgs e) 
    { 
     AppSuspendedMessage appSuspendedMessage; 
     if (MessageService.TryParseMessage(e.Data, out appSuspendedMessage)) 
     { 
      Debug.WriteLine("App suspending"); // App is suspended, you can save your task state at this point 
      foregroundAppState = AppState.Suspended; 
      var currentTrackId = GetCurrentTrackId(); 
      ApplicationSettingsHelper.SaveSettingsValue(ApplicationSettingsConstants.TrackId, currentTrackId == null ? null : currentTrackId.ToString()); 
      return; 
     } 

     AppResumedMessage appResumedMessage; 
     if (MessageService.TryParseMessage(e.Data, out appResumedMessage)) 
     { 
      Debug.WriteLine("App resuming"); // App is resumed, now subscribe to message channel 
      foregroundAppState = AppState.Active; 
      return; 
     } 

     StartPlaybackMessage startPlaybackMessage; 
     if (MessageService.TryParseMessage(e.Data, out startPlaybackMessage)) 
     { 
      //Foreground App process has signalled that it is ready for playback 
      Debug.WriteLine("Starting Playback"); 
      StartPlayback(); 
      return; 
     } 

     SkipNextMessage skipNextMessage; 
     if (MessageService.TryParseMessage(e.Data, out skipNextMessage)) 
     { 
      // User has chosen to skip track from app context. 
      Debug.WriteLine("Skipping to next"); 
      SkipToNext(); 
      return; 
     } 

     SkipPreviousMessage skipPreviousMessage; 
     if (MessageService.TryParseMessage(e.Data, out skipPreviousMessage)) 
     { 
      // User has chosen to skip track from app context. 
      Debug.WriteLine("Skipping to previous"); 
      SkipToPrevious(); 
      return; 
     } 

     TrackChangedMessage trackChangedMessage; 
     if (MessageService.TryParseMessage(e.Data, out trackChangedMessage)) 
     { 
      var index = playbackList.Items.ToList().FindIndex(i => (string)i.Source.CustomProperties[TrackIdKey] == trackChangedMessage.TrackId); 
      Debug.WriteLine("Skipping to track " + index); 
      smtc.PlaybackStatus = MediaPlaybackStatus.Changing; 
      playbackList.MoveTo((uint)index); 
      return; 
     } 

     UpdatePlaylistMessage updatePlaylistMessage; 
     if (MessageService.TryParseMessage(e.Data, out updatePlaylistMessage)) 
     { 
      CreatePlaybackList(updatePlaylistMessage.Songs); 
      return; 
     } 
    } 
    /// <summary> 
    /// Create a playback list from the list of songs received from the foreground app. 
    /// </summary> 
    /// <param name="songs"></param> 
    /// 
    void CreatePlaybackList(IEnumerable<SongModel> songs) 
    { 
     // Make a new list and enable looping 
     playbackList = new MediaPlaybackList(); 
     playbackList.AutoRepeatEnabled = true; 
     // Add playback items to the list 
      foreach (var song in songs) 
      { 
       Task.Run(async() => { 
       SpeechSynthesisStream synthesisStream = await GetStream(song.Verbs); 
       var source = MediaSource.CreateFromStream(synthesisStream,synthesisStream.GetType().ToString()); 
       source.CustomProperties[TrackIdKey] = song.ID; 
       source.CustomProperties[TitleKey] = song.Title; 
       source.CustomProperties[AlbumArtKey] = song.AlbumArtUri; 
       playbackList.Items.Add(new MediaPlaybackItem(source)); 
       }); 
      } 

     // Don't auto start 
     BackgroundMediaPlayer.Current.AutoPlay = false; 

     // Assign the list to the player 
     BackgroundMediaPlayer.Current.Source = playbackList; 

     // Add handler for future playlist item changes 
     playbackList.CurrentItemChanged += PlaybackList_CurrentItemChanged; 
    } 

    #endregion 


    private async Task<SpeechSynthesisStream> GetStream(string verb) 
    { 
     SpeechSynthesisStream synthesisStream; 
     SpeechSynthesizer synthesizer = new SpeechSynthesizer(); 
     var voices = SpeechSynthesizer.AllVoices; 
     bool speechFound = false; 
     foreach (VoiceInformation voice in voices.OrderBy(p => p.Language)) 
     { 
      if (voice.Language == "de-DE") 
      { 
       synthesizer.Voice = voice; 
       speechFound = true; 
      } 
     } 
     if (speechFound) 
     { 
      synthesisStream = await synthesizer.SynthesizeTextToStreamAsync(verb); 
      return synthesisStream; 
     } 
     return null; 
    } 

Я изменил только этот метод

void CreatePlaybackList(IEnumerable<SongModel> songs) 
    { 
     // Make a new list and enable looping 
     playbackList = new MediaPlaybackList(); 
     playbackList.AutoRepeatEnabled = true; 
     // Add playback items to the list 
      foreach (var song in songs) 
      { 
       Task.Run(async() => { 
       SpeechSynthesisStream synthesisStream = await GetStream(song.Verbs); 
       var source = MediaSource.CreateFromStream(synthesisStream,synthesisStream.GetType().ToString()); 
       source.CustomProperties[TrackIdKey] = song.ID; 
       source.CustomProperties[TitleKey] = song.Title; 
       source.CustomProperties[AlbumArtKey] = song.AlbumArtUri; 
       playbackList.Items.Add(new MediaPlaybackItem(source)); 
       }); 
      } 

     // Don't auto start 
     BackgroundMediaPlayer.Current.AutoPlay = false; 

     // Assign the list to the player 
     BackgroundMediaPlayer.Current.Source = playbackList; 

     // Add handler for future playlist item changes 
     playbackList.CurrentItemChanged += PlaybackList_CurrentItemChanged; 
    } 

Может быть проблема заключается в SpeechSynthesisStream? И он тратит много памяти, потому что в плейлисте более 200 песен?

+1

Это код, который нужно копать. Дайте нам некоторые подсказки о том, где вы думаете, что проблема ... – WillardSolutions

+0

Существует [Фоновый аудио-образец] (https://github.com/Microsoft/Windows-universal-samples/tree/e13cf5dca497ad661706d150a154830666913be4/Samples/BackgroundAudio), он работает в телефоне. –

+0

Является ли BackgroundAudio WindowsRuntimeComponent? – Archana

ответ

1

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

Смежные вопросы