Изолированное хранилище для аудиофайлов, не использующих отдельные события нажатия

#c# #windows-phone-8 #audio-streaming

#c# #windows-phone-8 #потоковое аудио

Вопрос:

Я пришел к выводу, что упаковка всех этих аудиофайлов в xap была просто плохой идеей, поскольку теперь она выросла примерно до 60 Мб. Я бы хотел больше не упаковывать свои аудиофайлы в приложение, а использовать URL-адреса и загружать их в изолированное хранилище, когда пользователь нажимает звуковые кнопки. Я не уверен, как это сделать с моим приложением, поскольку мои кнопки не кодируются индивидуально. Они автоматически загружаются из модели представления в LongListSelectors. И воспроизведение в зависимости от того, какой из них нажат (data.filepath). Ниже я попытался использовать изолированное хранилище, но получаю ошибки.

ОБНОВЛЕН mainpage.cs:

 public partial class MainPage : PhoneApplicationPage
{
    public string FilePath { get; set; }
    WebClient _webClient;
    // Constructor
    public MainPage()
    {
        InitializeComponent();

        // Set the data context of the listbox control to the sample data
        DataContext = App.ViewModel;

        //webclient download
        _webClient = new WebClient();
        _webClient.OpenReadCompleted  = (s1, e1) =>
        {
            if (e1.Error == null)
            {
                try
                {
                    string fileName = FilePath.
                            Substring(FilePath.LastIndexOf("/")   1).Trim();
                    bool isSpaceAvailable = 
                        IsSpaceIsAvailable(e1.Result.Length);

                    if (isSpaceAvailable)
                    {
                        // Save mp3 to Isolated Storage
                        using (var isfs = new IsolatedStorageFileStream(
                                fileName, FileMode.CreateNew,
                                IsolatedStorageFile.GetUserStoreForApplication()))
                        {
                            long fileLen = e1.Result.Length;
                            byte[] b = new byte[fileLen];
                            e1.Result.Read(b, 0, b.Length);
                            isfs.Write(b, 0, b.Length);
                            isfs.Flush();
                        }
                    }
                    else
                    {
                        MessageBox.Show("Not enough to save space available to download mp3.");
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                MessageBox.Show(e1.Error.Message);
            }
        };
     }

    // Check to make sure there are enough space available on the phone
    // in order to save the image that we are downloading on to the phone
    private bool IsSpaceIsAvailable(long spaceReq)
    {
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {

            long spaceAvail = store.AvailableFreeSpace;
            if (spaceReq > spaceAvail)
            {
                return false;
            }
            return true;
        }
     }
        // Sample code to localize the ApplicationBar




    // Load data for the ViewModel Items
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        if (!App.ViewModel.IsDataLoaded)
        {
            App.ViewModel.LoadData();
        }
    }

    private void LongListSelector_SelectionChanged(
        object sender, SelectionChangedEventArgs e)
    {
        LongListSelector selector = sender as LongListSelector;

        // verifying our sender is actually a LongListSelector
        if (selector == null)
            return;

        SoundData data = selector.SelectedItem as SoundData;

        // verifying our sender is actually SoundData
        if (data == null)
            return;


        if (File.Exists(data.FilePath))
        {
            AudioPlayer.Source = new Uri(
                data.FilePath,  
                UriKind.RelativeOrAbsolute);
        }
        else
        {
            using (var storageFolder =
                IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var stream = new IsolatedStorageFileStream(
                        data.FilePath, FileMode.Open, storageFolder))
                {
                    AudioPlayer.SetSource(stream);
                }
            }
        }

        selector.SelectedItem = null;
 

Вот немного моей модели SoundModel. Я оставил один пример того, как он настроен сейчас с локальным хранилищем, которое работает. Другой — как мне нравится использовать URL-адрес.

 private SoundGroup CreateGamesGroup()
        {
            SoundGroup data = new SoundGroup();

            data.Title = "Games";
            string basePath = "assets/audio/Games/";

            data.Items.Add(new SoundData
            {
                Title = "Gauntlet Exit",
                FilePath = basePath   "GauntletExit.mp3",
                Groups = "VideoGames"
            });                  

            data.Items.Add(new SoundData
            {
                Title = "Gauntlet Exit",
                FilePath = 
                    "http://k007.kiwi6.com/hotlink/23lenhzr3h/GauntletExit.mp3",
                Groups="VideoGames"
            });
 

Поскольку Mainpage.cs ссылается на модель SoundData, я добавлю это и здесь:

  public class SoundData : ViewModelBase
{
    public string Title { get; set; }
    public string FilePath { get; set; }
    public string Items { get; set; }
    public string Groups { get; set; }


    public RelayCommand<string> SaveSoundAsRingtone { get; set; }


    private void ExecuteSaveSoundAsRingtone(string soundPath)
    {
        App.Current.RootVisual.Dispatcher.BeginInvoke(() =>
        {
            SaveRingtoneTask task = new SaveRingtoneTask();
            task.Source = new Uri("appdata:/"   this.FilePath);
            task.DisplayName = this.Title;
            task.Show();
        }
            );
    }   

    public SoundData()
    {
        SaveSoundAsRingtone = 
            new RelayCommand<string>(ExecuteSaveSoundAsRingtone);
    }
 

В настоящее время URL-адрес работает не так, как я ожидал. Я получаю эти ошибки:

Исключение первого случая типа ‘System.IO.IsolatedStorage.Исключение IsolatedStorageException’ произошло в mscorlib.ni.dll Исключение типа ‘System.IO.IsolatedStorage.Исключение IsolatedStorageException’ произошло в mscorlib.ni.dll но не был обработан в пользовательском коде Дополнительная информация: Операция не разрешена для IsolatedStorageFileStream.

Комментарии:

1. Я вижу, вы обновили свой вопрос. Обновленный ответ соответствующим образом.

Ответ №1:

Не уверен, что это основная причина ваших проблем, но вам нужно использовать appdata:/ для файлов, включенных в XAP, в противном случае используйте isostore:/

Если у вас есть элементы, привязанные к LongListSelector с помощью открытого свойства, вы можете назначить команду своим элементам и обрабатывать «клики» в вашей viewmodel.

Допустим, у вас есть следующее в вашей виртуальной машине:

 public ObservableCollection<SoundData> AudioFiles { get; set; }
public ICommand PlayCommand { get; set; }
 

Тогда связанный XAML будет выглядеть примерно так:

 <phone:LongListSelector
        x:Name="AudioFilesList" 
        ItemsSource="{Binding AudioFiles}"
        SelectedItem="{Binding SoundData}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Tap">
                <command:EventToCommand 
                    Command="{Binding PlayCommand}" 
                    CommandParameter="{Binding Path=SelectedItem, 
                        ElementName=AudioFilesList}" 
                    PassEventArgsToCommand="False" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <phone:LongListSelector.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Border BorderThickness="2" 
                            BorderBrush="{StaticResource PhoneForegroundBrush}"
                            Height="80">
                        <TextBlock 
                            Text="{Binding FilePath}" 
                            HorizontalAlignment="Center" 
                            VerticalAlignment="Center" 
                            Style="{StaticResource PhoneTextNormalStyle}" />
                    </Border>
                </Grid>
            </DataTemplate>
        </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
 

Важная часть выше — ItemsSource, SelectedItem и привязка PlayCommand для LongListSelector .

Я создал небольшой пример проекта @ Git, надеюсь, это поможет вам разобраться https://github.com/mikkoviitala/any-ringtone

Он получает несколько mp3-файлов по http, сохраняет файлы в IsoStore, а затем отображает элементы в LongListSelector. Нажатие на элемент списка запускает команду, которая выполняет Ringtonetask.

imgur