问题
I have a solution, which includes 2 projects: main progect, and PlayListFilePlayBackAgent.
in main project, in MainPage a have a listBox, which shows different content. Some content has audioformat, and when i see title, and performer in listbox's item - i click button "play" in this listbox's item. This button make some operations(take track's urls from some server) and than go to page AudioPage. In AudioPage some method make a playlist from those urls, than its saves in isolatedStorage in xml format(serialized). Here is PlayList.cs
public class Playlist
{
public Playlist()
{
Tracks = new List<PlaylistTrack>();
}
[XmlElement(ElementName = "Track")]
public List<PlaylistTrack> Tracks { set; get; }
[XmlElement(ElementName = "TrackCount")]
public int TrackCount { set; get; }
public static Playlist Load(string filename)
{
Playlist playlist = null;
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = storage.OpenFile(filename, FileMode.Open))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Playlist));
playlist = xmlSerializer.Deserialize(stream) as Playlist;
}
}
return playlist;
}
public void Save(string filename)
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = storage.CreateFile(filename))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Playlist));
xmlSerializer.Serialize(stream, this);
}
}
}
}
And a PlayBackAgent than deserializes this xml into playlist, and plays it.
That's all good, but when i want to listen tracks which were not in those item of listbox i have a problem.
I go back to my listbox, than i select some track and push button "play". In button handler, i .Clear();
my collection, take new urls of new tracks, go to AudioPage and make a new playlist. But in emulator i see the same music i listen before.I thought the problem was in that PlayListFilePlayBackAgent do not update a playlist from isolatedStorade. But when i click different buttons "play" - field TrackCount changes(don't mind to its name, it just says what number of track in playlist must play player), i can see it in output when write Debug.WriteLine(Convert.ToString(playlist.TrackCount));
in AudioPlayer.cs
. So what I have: an audioplayer, which plays music only from first playlist I gave to him. When I want to listen another playlist - in AudioPage i see old playlist and can listen music only from those old playlist. What I want: an audioplayer which can change playlist everytime when I push button "play", and can play this music.
PS: I use PlayListFilePlayBackAgent because it can play music even if i close this application. If you need more code - just tell me. Thanks.
Update: Button handler
private void Audio_Button_Click(object sender, RoutedEventArgs e)
{
string uri = null;
TextBox tb = null;
var grid = (Grid)((Button)sender).Parent;
foreach (var child in grid.Children)
{
if (child is TextBox && (string)((TextBox)child).Tag == "URL")
{
tb = (TextBox)child;
}
}
uri = tb.Text;
BackgroundAudioPlayer.Instance.SkipNext();
//MessageBox.Show(uri);
string url = string.Format("https://api.vk.com/method/audio.getById.xml?audios={0}&access_token={1}", uri, App.AccessToken);
var c = new WebClient();
c.OpenReadCompleted += (sender1, e1) =>
{
XDocument xml = XDocument.Load(e1.Result);
MessageBox.Show(xml.ToString());
var inf = from u in xml.Descendants("audio")
select u;
AudioPage.audios.Clear();
foreach (var item in inf)
{
AudioPage.audios.Add(new AudioAttachment((string)item.Element("url"), (string)item.Element("title"), (string)item.Element("artist")));
}
string destination = string.Format("/AudioPage.xaml");
NavigationService.Navigate(new Uri(destination, UriKind.Relative));
AudioPage.count = 0;
};
c.OpenReadAsync(new Uri(url));
}
OnUseraction.cs
protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
{
switch (action)
{
case UserAction.Play:
if (player.Track == null)
{
// Load playlist from isolated storage
if (playlist == null)
playlist = Playlist.Load("playlist.xml");
// Debug.WriteLine(playlist.Tracks[0].Title);
Debug.WriteLine(Convert.ToString(playlist.TrackCount));
currentTrack = playlist.TrackCount;
player.Track = playlist.Tracks[currentTrack].ToAudioTrack();
}
else
{
player.Play();
}
break;
case UserAction.Pause:
player.Pause();
break;
case UserAction.SkipNext:
if (currentTrack < playlist.Tracks.Count - 1)
{
currentTrack += 1;
player.Track = playlist.Tracks[currentTrack].ToAudioTrack();
}
else
{
player.Track = null;
}
break;
case UserAction.SkipPrevious:
if (currentTrack > 0)
{
currentTrack -= 1;
player.Track = playlist.Tracks[currentTrack].ToAudioTrack();
}
else
{
player.Track = null;
}
break;
case UserAction.Seek:
player.Position = (TimeSpan)param;
break;
}
NotifyComplete();
}
回答1:
If you change your playlist in the UI you will need some way of signalling to the agent that it needs to change what it is playing, otherwise it will continue playing the current track.
When user hits the play button, call BackgroundAudioPlayer.Instance.SkipNext
from your app, and when you get the OnUserAction
event in your agent code you'll be able to recheck your playlist XML file.
回答2:
if (playlist == null)
playlist = Playlist.Load("playlist.xml");
Where do you set playlist back to Null?
Man, I feel your pain. I have exactly same situation and used exactly the same approach (with the exception that I used IsolatedStorageSettings.ApplicationSettings collection instead of writing into the file).
It works perfectly for the 1st run.
The behavior is really weird.. I saw data updated on the foreground app, but reading same settings from the player would not give me new data. I also tried writing with a new settings key (in case BAP caches results or something) but I got some unstable results where it would work to 2-5 updates and then just stopped seeing new settings keys in the collection. Drives me crazy...
I also noticed that the Tag property of a audio track seems to be copied properly, so I tried to serialize my playlist and pass as a string value through the tag, but got an errors that some memory was not enough or something.. Looks like they have their own restrictions there.
Please let me know if you get find luck with this issue.
回答3:
Perhaps one of the most detailed info on playing audio on Windows Phone. Check the project here http://developer.nokia.com/community/wiki/Streaming_MP3_player_in_WP7.
However I must say in my case I had to load the Database and extract the information by looping through the Lists without using JSON. Below is the code;
private void LoadPlayListFromIsolatedStorage(BackgroundAudioPlayer player)
{
// clear previous playlist
_playList.Clear();
// access to isolated storage
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("AlbumsData.dat", FileMode.OpenOrCreate, isoStore))
{
if (stream.Length > 0)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(List<Album>));
List<Album> strm = serializer.ReadObject(stream) as List<Album>;
List<Song> _songs = strm[0].Songs;
for (int i = 0; i < _songs.Count; i++)
{
AudioTrack audioTrack = new AudioTrack(
new Uri(_songs[i].Directory, UriKind.Absolute), // URL
_songs[i].Title, // MP3 Music Title
"Artist", // MP3 Music Artist
"Album", // MP3 Music Album name
new Uri(_songs[i].AlbumArt, UriKind.Absolute) // MP3 Music Artwork URL
);
_playList.Add(audioTrack);
}
}
else
{
// no AudioTracks from Isolated Storage
}
// start playing
PlayTrack(player);
}
来源:https://stackoverflow.com/questions/13887052/how-to-reload-playlist-in-backgroundaudioplayer