6

I have two pages say Page1 and page2. In Page-1 I have a listview and an Image button(tap gesture). Here if I click listview item, it navigates to Page2 where it plays a song.

Navigation.PushModalAsync(new page2(parameter1));

Song continues to play. Then I go back to page1 by clicking back button. Then as mentioned I have an imagebutton in page1, if I click this image button, I want to go the same page which was shown earlier(page2) with same status song continues to play (it should not play from the beginning).

I understand, if I click the back button, it destroys the model page. For some reason, I can't use pushasync(). Is this possible?

MLavoie
  • 9,671
  • 41
  • 36
  • 56
uncle_scrooge
  • 409
  • 1
  • 5
  • 28
  • When close the page during back save the song and its position, in the page appearing event set position – Krishna Apr 18 '17 at 13:25
  • First what came to mind is to have that page as a singleton, and pass as parameter to `PushModalAsync()`, not creating it each time – Alex Apr 18 '17 at 13:25
  • I think it is possible, you can get the pause state of the song and save that in the ViewModel using MessagingCenter & again when the page is launched you should be able to retrieve the data from VM and play the song from where it was paused. – Dilmah Apr 18 '17 at 13:26
  • I cant do pause..song should be playing in background – uncle_scrooge Apr 18 '17 at 13:40
  • Could you offer more details about "song should be playing in background"? What did you use for audio playing? Maybe share a basic demo to show what you are trying. – Elvis Xia - MSFT Apr 19 '17 at 05:59
  • song playing means..it may be any song..But my question is about navigation,Basically when i click listview item in page 1,song starts playing in page2,then when i click back button it goes to page1,till now song should be continue to play,now in page1 when i click image button (e.g. image can be now playing... image)it should display page2 with continued song playing.. – uncle_scrooge Apr 19 '17 at 06:02
  • When you press back the page is destroyed, when you go forwards the page is always recreated. You could save the track progress in storage and then resume? – James Mundy Apr 21 '17 at 11:37
  • Thanks for replying James,Actually I am using a 3rd party media library,So I cant save the track progress(also there are some other reasons).Is there a way to just hide the page2 when we click the back button,Can we write something in back button click event ..just to hide the page and again when I click button then page appears(like visibilty and hidden properties for control) – uncle_scrooge Apr 21 '17 at 13:09
  • Sorry for not replying sooner, didn't get a notification. There's not an easy way to hide the page rather than get rid of it completely, have you thought about maybe having a global player instance for your app? Not exactly a best practice but you could then keep the same player instance (and therefore the last saved location). – James Mundy Apr 25 '17 at 21:39

2 Answers2

4

Would recommend not to tightly couple your audio/media player logic with your navigation logic or Page objects - especially if you want it to continue playing in the background.

Simplest approach would be to have a AudioPlayerService class that subscribes to MessengingCenter for audio player commands - such as play, pause etc. When a play command is published, it can initiate a background thread to play the audio file.

MessagingCenter.Subscribe<Page2, AudioPlayerArgs> (this, "Play", (sender, args) => {
      // initiate thread to play song
});

Now, when you navigate from page1 to page2, you can publish/send a command to the AudioPlayerService class through MessengingCenter to start playing the song. This way, any number of back-and-forth between page1 or page2 won't affect the audio player as it can ignore the play commands if it is already playing the same audio file.

MessagingCenter.Send<Page2, AudioPlayerArgs> (this, "Play", new AudioPlayerArgs("<sound file path>"));

Note: I personally avoid using MessengingCenter in my code - A better approach would be to rather introduce an interface for IAudioPlayerService with appropriate methods to play, pause etc. and use DependencyService to maintain the AudioPlayerService state as a global object (which is default behavior)

public interface IAudioPlayerService {
     bool PlayAudio(string file);
     bool PauseAudio();
     bool StopAudio();
}

[assembly: Xamarin.Forms.Dependency (typeof (IAudioPlayerService))]
public class AudioPlayerService : IAudioPlayerService {
      //implement your methods
}

And, use following code to control your audio player service in your Page/ViewModel objects.

DependencyService.Get<IAudioPlayerService>().Play("<sound file path>");
Sharada Gururaj
  • 13,471
  • 1
  • 22
  • 50
  • I am wondering if [MVVM light](https://mvvmlight.codeplex.com) could be used in this situation – mbob Apr 27 '17 at 07:37
2

You may try to pass the same instance of a global or local variable, whatever is appropriate:

var secondpage = new page2(parameter1); // Global scope.
...
Navigation.PushModalAsync(secondpage);

Hope it helps.

asewefy
  • 109
  • 9
  • @uncle_scrooge This is the right answer, simply don't start playing the song on the `OnAppearing` event, check if the song is already playing and if it is don't start it again. If you want real help, add your code. – Gusman Apr 28 '17 at 01:23
  • My intention of asking this question was,Whether there is a way to hide a page like we do for controls(visiblity)as modal page destroys once we go back. – uncle_scrooge Apr 28 '17 at 07:15