Вы слышите…мой новый WebTone? Как легко и быстро загрузить и настроить рингтоны Windows Phone 7.1(5)

Грэг Дункан

Одной из изюминок Mango/Windows Phone 7.1(5) является то, что «реальные пользователи» (вроде моей племянницы), кажется, в полном восторге от настраиваемых мелодий для звонка. Это вдохновило ряд разработчиков на приложения, реализующие это желание.

Сегодняшний проект описывает одно такое приложение.

WebTone 1.1 выходит на Marketplace

Первоначальная версия WebTone появилась на Windows Phone Marketplace в начале сентября, и после одного или двух выпусков, необходимых для прохождения сертификации, вышла версия 1.1.

Что нового?

Одной часто упоминаемой вещью в отзывах было отсутствие возможности загрузки из форумов и подобных мест. Проблемой является то, что приложение проверяло .mp3 или .wma в ссылке. Теперь, когда встречается такая ссылка, приложение спросит, какой это тип файла…

Приложение WebTone доступно на нескольких языках. Более точно: на английском, испанском, датском, итальянском, китайском (упрощенном и традиционном).

Что мне нравиться, так это то, что Скотт опубликовал исходный код своего приложения, при том, что он обновляет его почти ежедневно. Другой вещью, которую не часто увидишь в приложениях для Windows Phone 7.1(5), является поддержка дополнительных языков.

Давайте взглянем на решение:

clip_image002

Замечание. Если вы скачаете исходники и столкнетесь с проблемами, связанными со ссылками на GalaSoft, то они устраняются с помощью NuGet. Все остальные ссылки на месте, и понятно, что такой прием сработает на куске кода не включающем этих двух DLL (Я говорил, как мне нравится NuGet?)

Мы говорили о поддержке дополнительных языков…

clip_image004

Ядром проекта является загрузка. Приложение должно не только справляться с обычными вещами при загрузке чего-либо, но и обрабатывать уникальные случаи для рингтонов Windows Phone 7.1(5), такие, как типы файлов и размеры, и другие варианты, для которых нет достаточного изолированного пространства памяти и запрашивать его.

 private void DoDownload()
{
     Deployment.Current.Dispatcher.BeginInvoke(() =>
     {
         ProgressText = "downloading file...";
         IsIndeterminate = true;
         ProgressChanged = 0;
     });
     downloadMP3Client = new WebClient();
     
     downloadMP3Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downloadMP3Client_DownloadProgressChanged);
     downloadMP3Client.OpenReadCompleted += new OpenReadCompletedEventHandler(downloadMP3Client_OpenReadCompleted);
     downloadMP3Client.OpenReadAsync(FinalUrl);
}

void downloadMP3Client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
     Deployment.Current.Dispatcher.BeginInvoke(() =>
         {
             if (!e.Cancelled)
             {
                 if (e.Error == null)
                 {
                     try
                     {
                         if (e.Result != null)
                         {
                             CurrentItem.TempFileName = string.Format("temp{0}", CurrentItem.FileExtension);

                             CurrentItem.RingtoneName = System.IO.Path.GetFileNameWithoutExtension(FinalUrl.ToString());

                             if (isolatedStorageFile.FileExists(CurrentItem.TempFileName))
                             {
                                 isolatedStorageFile.DeleteFile(CurrentItem.TempFileName);
                             }
                             bool checkQuotaIncrease = IncreaseIsolatedStorageSpace(e.Result.Length);

                             string AudioFile = CurrentItem.TempFileName;
                             using (isolatedStorageFileStream = new IsolatedStorageFileStream(AudioFile, FileMode.Create, isolatedStorageFile))
                             {
                                 using (BinaryWriter writer = new BinaryWriter(isolatedStorageFileStream))
                                 {
                                     long AudioFileLength = (long)e.Result.Length;
                                     byte[] buffer = new byte[32];
                                     int readCount = 0;
                                     using (BinaryReader reader = new BinaryReader(e.Result))
                                     {
                                         while (readCount < AudioFileLength)
                                         {
                                             int actual = reader.Read(buffer, 0, buffer.Length);
                                             readCount += actual;
                                             writer.Write(buffer, 0, actual);
                                         }
                                     }
                                 }
                             }
                             CurrentItem.LocalUrl = AudioFile;
                             IsDataLoaded = true;
                             DownloadingMP3 = false;
                             ProgressText = "";
                             IsIndeterminate = false;
                             if (DataLoaded != null)
                                 DataLoaded(this, new EventArgs());
                         }
                     }
                     catch (Exception ex)
                     {
                         SetError(ex.Message, Strings.Error);
                     }
                 }
                 else
                 {
                     SetError(e.Error.Message, Strings.Error);
                 }
             }
         });
}

void downloadMP3Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
     if (e.TotalBytesToReceive > 1048576)
     {
         downloadMP3Client.CancelAsync();
         Deployment.Current.Dispatcher.BeginInvoke(() => { SetError(Strings.FileSizeError, Strings.Information); });
     }
     else
     {
         Deployment.Current.Dispatcher.BeginInvoke(() =>
         {
             ProgressChanged = (double)e.ProgressPercentage / 100;
             CurrentItem.ToneSize = e.TotalBytesToReceive;
         });
     }
}

И мне хочется рассмеяться (по-доброму) над сообщениями об ошибках (микроВатсон… забавно!)

 // Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
     <strong>LittleWatson</strong>.ReportException(e.ExceptionObject, sender.ToString());
     if (System.Diagnostics.Debugger.IsAttached)
     {
         // An unhandled exception has occurred; break into the debugger
         System.Diagnostics.Debugger.Break();
     }

     e.Handled = true;
}       

Если вы установили WebTone (или запустили его на эмуляторе) и ищете места, откуда можно загрузить некоторые клёвые рингтоны, проверьте следующую ссылку:

Скачать звуки NASA

Здесь располагается коллекция звуков NASA от исторических космических полетов и современных миссий. Каждый раз при получении вызова можно слышать грохот запуска шаттла или знаменитое армстронговское «один маленький шаг для человека и гигантский скачок для всего человечества». Или можете слышать памятное «Хьюстон, у нас проблема» каждый раз, когда возникает ошибка на компьютере. Для загрузки мы включили файлы форматов MP3 и M4R (iPhone).

Да, «Хьюстон, у нас проблема» также работает в приложении как рингтон... clip_image006

Наконец, если вы запускаете приложение в эмуляторе и хотите использовать клавиатуру, причем не экранную клавиатуру, взгляните на эту статью «Отображение клавиатуры для эмулятора Windows Phone» (совет, нажмите Page Up на физической клавиатуре).

Кстати, если вы хотите помочь проекту, Скот ждет помощи по дополнительному переводу…