image

Windows Phone… услышав название этой мобильной системы, поневоле начинаешь с теплотой вспоминать своего недавнего, такого необычного мобильного друга, как будто прошло всего пару месяцев с момента смены смартфона на iPhone/Android. А ведь с момента фактической смерти Windows Phone прошло уже почти 10 лет! Увы, время вспять уже не повернуть, а мобильное подразделение Nokia не спасти, однако при наличии навыков разработки мобильных приложений, большом энтузиазме и фанатизме, есть шанс вернуть жизнь своему старому другу! Недавно я снова загорелся диким энтузиазмом и смог вернуть жизнь старенькой «люмии», написав собственные клиенты нужных мне сервисов с нуля — и готов поделиться этим с вами во всех подробностях!

Сегодня вы узнаете о моей мотивации привносить жизнь старым смартфонам, о тонкостях разработки мобильных приложений, чем Windiows Phone был на голову выше Android в техническом плане и о том, почему провал Windows Phone — одна из самых больших потерь мобильного рынка. Интересно? Тогда добро пожаловать в статью!

Предыстория


Пожалуй, довольно большой процент моих читателей и подписчиков когда-либо владел и пользовался смартфонами на Windows Phone. Мнение пользователей этой мобильной платформы во многом разнится — кто-то восхваляет по настоящему продуманный и плавный интерфейс, кто-то ругает Microsoft за «кидалово» с обновлениями, но большинство людей сходится во мнении, что Windows Phone — была действительно необычной и имела собственную изюминку.

image

Конечно же, Windows Phone была далеко не первым опытом Microsoft на мобильном рынке. До этого, Редмондская компания поддерживала очень крутую платформу для коммуникаторов и КПК под названием Windows Mobile. Фактически, это был полноценный компьютер в кармане — большинство кнопочных телефонов могли максимум запускать простенькие J2ME-приложения, в то время как WM позволял запускать множество самых разных программ — как написанных на C++/Pascal, так и написанных на C#/VB.Net. Мобильная платформа во всём пыталась подражать своему старшему брату — API системы было очень похоже на то, что мы видим в обычной Windows — тут и полноценная оконная система, и waveout для вывода звука, и GDI для вывода графики.

image

Windows Mobile прочно занимал свою нишу на мобильном рынке: HTC постоянно представляла новые модели коммуникаторов, которые довольно хорошо продавались. Но тут пришёл первый iPhone, который перевернул всё с ног на голову. Оказывается смартфоном можно управлять полностью пальцами, нажимая на красивые, анимированные элементы интерфейса! Это перевернуло всю индустрию — даже Nokia с её Symbian было тяжело конкурировать с продуктом от Apple. Microsoft видела, что пользователи хотят не столько свободы и кастомизации в системе, сколько плавности интерфейса, стабильности и простоты использования.

image

Плеер Zune HD стал дебютом свежего подхода к созданию интерфейсов — Metro UI. И хотя сам девайс не сыскал особой популярности, став в некоторой степени провальным, Microsoft взяла на вооружение концепцию этого интерфейса, дабы реализовать её уже в полноценной мобильной ОС. В октябре 2010 года выходит первая версия новой мобильной платформы Microsoft — Windows Phone 7, заложившая фундамент той самой системы, которую мы с вами до сих пор вспоминаем с теплотой!

image

На WP7 вышло весьма много устройств: тут и девайсы от HTC, и смартфоны Lumia от Nokia, и даже продолжение линейки Omnia от Samsung! Но были у этой платформы и серьезные минусы: она базировалась на ядре обычной Windows CE (оно же использовалось в Windows Mobile) и из-за желания повысить безопасность системы, Microsoft отключила возможность использовать код на нативных языках в своих приложениях. Кроме того, во многих аспектах WP7 была достаточно сырая — хотя для неё регулярно выходили обновления.

Почему провал WP — трагедия для мобильного рынка?


Конечно же параллельно с доработкой WP7, Microsoft разрабатывала новую версию ОС, которая должна была объединить мобильные и десктопные приложения в одну общую концепцию. Кроме того, разработчики решили отказаться от лёгкого ядра Windows CE в пользу более тяжелого и продвинутого ядра Windows NT, которое используется в полноценных версиях Windows.

image

К сожалению, апгрейда с WP7 на WP8 предусмотрено не было, что многие пользователи считают «кидаловом» со стороны Microsoft. Отчасти это так, но проблема была в том, что даже флагманские устройства на WP7 имели 512мб ОЗУ, чего было недостаточно для первой версии WP8. Думаю, в какой-то степени Microsoft просто не хотели портить имидж максимально плавных смартфонов тормозами обновленной системы, хотя примеры шустрой работы на 512мб ОЗУ есть — например, Lumia 520.

image

Но вот где WP8 была передовой, так это «под капотом». Microsoft смогли сделать что-то невообразимое для мира ARM-устройств: они реализовали нормальный слой абстракции от «железа» и ввели концепцию ACPI, знакомую нам из обычных десктопных ПК. Вкратце, ACPI — это что-то типа списка железа в устройстве, под которое ОС должна найти и загрузить драйверы, не забыв под это всё выделить ресурсы (devicetree в Linux реализует похожую концепцию). Кроме того, Microsoft реализовала полноценный UEFI в своих смартфонах, что позволяло, например, сделать дуалбут в будущем. На практике это всё означает то, что даже неподдерживаемые No-Name смартфоны можно было обновить до Windows 10, банально поменяв пару ключей в реестре: на Android-устройствах такое невообразимо. Фактически, это стандартизация ARM-железа.

image

На этом технические фишки Windows Phone не заканчиваются. Переходя к пользовательской части, стоит упомянуть фреймворк для построения интерфейса (WPF/Silverlight), который из коробки работает очень шустро, отлично масштабируется под разные размер экрана и предлагает мощные возможности по анимации и кастомизации интерфейса под стиль приложения. Да и само SDK навязывало изначально правильную концепцию программирования, заставляя выделять все задачи в отдельные потоки, не только задействуя дополнительные ядра процессора, но и улучшая пользовательский опыт от приложения (неправильно написанные Android-приложения легко могут подвисать при выполнении какой-то работы).

image

И третья классная фишка, про которую почему-то все забыли — это поддержка DirectX 11. Конечно в WP7 уже была поддержка Xna (именно на его базе написана Terraria), что позволяло писать игры одновременно для Windows, Xbox 360 и собственно мобилок, но он имел некоторые ограничения и был прослойкой между графическим API (как Direct3D или OpenGL) и самой игрой. Windows Phone 8 же давал настоящий, полноценный DirectX 11 — хотя и поддерживал максимум вторые шейдеры, но при этом умел те фишки, которые не умел Android — инстансинг для оптимальной отрисовки геометрии, установка стейтов «пачками» и эффективное «bindless» управление ресурсами шейдеров. Теоретически, это давало возможность портировать полноценные игры с ПК/Xbox на Windows Phone, хотя на практике не так много кто этим пользовался.

image

Ну и вспоминая аргумент про кидалово Microsoft с обновлениями, нужно помнить, что обратная совместимость с приложениями для более ранних версий системы была: на Windows Phone 8 можно было играть в годноту с Windows Phone 7 (NFS Undercover, NFS Hot Pursuit, Mirrors Edge и ещё некоторые классные мобильные игры), а на Windows 10 Mobile можно было запускать почти любое приложение для Windows Phone 8.

image

Так в чём же потеря WP — трагедия для мобильного рынка? А вы посмотрите на свой Android-смартфон сейчас. Сколько в нём ОЗУ? 4гб? 8гб? 12гб? Смущает ли вас то, что Android умудряется неприятно подтормаживать даже с такими ресурсами? А теперь вспомните Lumia 520: Snapdragon 200, 512 мегабайт оперативной памяти. Вот так она работает из коробки:



Думаю, это всё красноречиво объясняет то, что без WP случилась дуополия на рынке — Android продолжает жиреть, впустую жрать ресурсы и при этом практически не получать новых фишек из года в год, а iPhone хоть и остаётся всё такой же плавной и шустрой, ребята из Apple явно не чувствуют конкуренции и их смартфоны стагнируют в плане дизайна и в некоторой степени интерфейса…

image


Мотивация


Мои давние читатели знают мою любовь к смартфонам прошлых лет. Для меня нет понятия запланированного устаревания: если под устройство есть комплект разработки и документация, то при большом желании я могу дописать нужные мне приложения сам.
Мой проект SelfEco (сам себе экосистема) как раз об этом — почти полгода назад я написал клиент YouTube и ВК для Android 2.2+. Фактически это означает, что мои приложения работали на ВСЕХ Android смартфонах от 2010 года и новее.

image

Исходным кодом своих приложений я свободно делюсь — как в качестве примера читателям, так и для возможности каких-то фиксов в будущем или даже модов. В 2021-2022 году я ходил с Lumia 640XL с Win10 Mobile на борту, как с основным смартфоном. И в целом, меня все устраивало и всё нравилось: там и годный клиент ВК был (LunaVK), и клиент телеги нормальный, и браузер кое-какие страницы всё ещё нормально переваривал. Но больше всего мне нравится Windows Phone 8 — она работает ещё шустрее и несколько более строгая в плане дизайна. Да и «люмии» сейчас стоят сущие копейки — моя 640XL обошлась мне в 100 российских рублей (~1.5$ по тому курсу), я не шучу. А на онлайн-барахолках можно найти живые, целые аппараты с нормальными аккумуляторами по 200-500 рублей, иногда даже в родных коробочках!

image

Lumia 1320 и Lumia 640XL — подарки читателя Kotenilla!
Дак почему бы не применить всю эту круть и мощь во благо, учитывая дешевизну смартфонов? Решено: Качаем SDK и пишем собственный клиент ВК и YouTube — это минимально-необходимые для меня приложения!

Подготовка


Для того, чтобы отлаживать и устанавливать сторонние приложения на смартфоны с Windows Phone, их нужно предварительно разблокировать и сделать «Interop Unlock». Процедура несложная и занимает немного времени на большинстве люмий. Дабы сильно не затягивать статью, я не буду описывать процесс разлочки здесь — его можно найти на 4pda для разных поколений устройств.

image

YouTube


Начинаем с клиента ютуба. Собственно, концепция отнюдь не поменялась с прошлой статьи — мы всё так же используем API Invidous для получения информации о видео. Нативное API YouTube — полная дичь, да ещё и с ограничениями на один токен, в то время как Invidous сам распоряжается токенами и распределяет их как нужно. Нам лишь остаётся написать «морду», которая будет отображать полученные с сервера данные и передавать ссылку на видео в встроенный плеер.

image

В отличии от Android, никаких проблем с TLS не возникло: смартфон смог без проблем связаться с инстансом Invidous и получить данные о видео в трендах. Сам по себе, формат ответов очень простой и возвращается в виде JSON, который можно описать такой иерархией:

public class VideoInfo
    {
        public string type { get; set; }
        public string title { get; set; }
        public string videoId { get; set; }
        public string author { get; set; }
        public string authorId { get; set; }
        public string authorUrl { get; set; }
        public bool authorVerified { get; set; }
        public List<VideoThumbnail> videoThumbnails { get; set; }
        public string description { get; set; }
        public string descriptionHtml { get; set; }
        public int viewCount { get; set; }
        public string viewCountText { get; set; }
        public int published { get; set; }
        public string publishedText { get; set; }
        public int lengthSeconds { get; set; }
        public bool liveNow { get; set; }
        public bool premium { get; set; }
        public bool isUpcoming { get; set; }
    }

Практически сразу система нам навязывает распараллелленую парадигму написания кода — часть API банально не имеет синхронных аналогов! Например, из WebRequest убрали GetResponse, дабы неопытные разработчики не делали ошибок и не пытались вызывать долгие I/O операции в главном потоке (что вызывает подвисания приложения). .NET сам по себе имеет крутой механизм тасков (многопоточных задач) и реализацию концепции async/await, которая позволяет подождать выполнение операции, не блокируя остальное приложение.

private void RequestURL(string method, Action<string> onReady, string fmt, params object[] args)
        {
            string defaultArgs = string.Format("region=RU&hl={0}", "ru");
            HttpWebRequest req = WebRequest.CreateHttp("https://vid.priv.au/api/v1/" + method + "?" + defaultArgs + string.Format(fmt, args));
            req.Method = "GET";

            req.BeginGetResponse((IAsyncResult res) =>
            {
                HttpWebResponse response = (HttpWebResponse)req.EndGetResponse(res);
                StreamReader reader = new StreamReader(response.GetResponseStream());

                line = reader.ReadToEnd();
                onReady(line);
            }, null);
        }

public void QueryTrendingList(Action<List<VideoInfo>> onReady)
        {
            HasPendingOperation = true;

            RequestURL("trending", (string json) =>
            {
                List<VideoInfo> ret = JsonConvert.DeserializeObject<List<VideoInfo>>(json);
                
                onReady(ret);
                HasPendingOperation = false;
            }, "");
        }

Я решил придержаться более привычной мне концепции на коллбэках, которая позволяет более четко обрабатывать ошибки в подобных кейсах, да и в целом я не очень люблю подобный синтаксический сахар (а async/await и есть «сахар», поскольку разворачивается в стейт-машину). В качестве десериализатора (механизма парсинга JSON напрямую в экземпляры классов, используя рефлексию) я использовал классический Newtonsoft.Json.

image

После того, как механизм получения и обработки данных с сервера был готов, я начал реализовывать интерфейс приложения. И вот тут WP показал себя во всей красе. ListView? RecycleView? Нафиг эти костыли, винфон умеет нормально рисовать элементы интерфейса, которые вы выделили в ScrollView. И что забавно: в Android даже реализация с ScrollView при активной подгрузке данных вызывала лаги — на WP такого нет вообще! Тут всё просто работает из коробки!

Механизм анимаций здесь тоже декларативный и реализован в концепции т.н «сторибордов» — наборов действий, которые позволяют создавать достаточно сложные анимации вручную.

<Storyboard x:Name="progressFadeIn">
                    <DoubleAnimation
                        Storyboard.TargetName="progressBar"
                        Storyboard.TargetProperty="Opacity"
                        From="0.0" To="1.0"
                        Duration="0:0:1" />
                </Storyboard>
                <Storyboard x:Name="progressFadeOut">
                    <DoubleAnimation
                        Storyboard.TargetName="progressBar"
                        Storyboard.TargetProperty="Opacity"
                        From="1.0" To="0.0"
                        Duration="0:0:1" />
                </Storyboard>

Буквально через пару часов после создания проекта, у меня уже была готова загрузка и отображение списка трендов:

image

А затем и логика воспроизведения видео, которая запускает встроенный плеер и передаёт в него ссылку на видео — которая выбирается относительно кодека (только mp4), разрешения устройства и предпочтений пользователя:

private void PlayVideo(VideoInfo info, VideoDescriptor desc)
        {
            int[] resTable = { 240, 360, 480, 720, 1080 };
            int desiredResolution = AppSettings.Instance.DesiredQuality == 0 ? (int)Application.Current.Host.Content.ActualHeight : resTable[AppSettings.Instance.DesiredQuality - 1];
            FormatStream strm = YTInstance.PickBestFormat(desc, desiredResolution);
            
            Log("Requested video {0}", desc.videoId);
            Log("Picked format {0}, while desired {1}", strm.resolution, AppSettings.Instance.DesiredQuality);

            Microsoft.Phone.Tasks.MediaPlayerLauncher mpLauncher = new Microsoft.Phone.Tasks.MediaPlayerLauncher();
            mpLauncher.Controls = Microsoft.Phone.Tasks.MediaPlaybackControls.All;
            mpLauncher.Media = new Uri(strm.url);
            mpLauncher.Show();

            if (AppSettings.Instance.SaveHistory)
                History.AddEntry(info);
        }

image

Кроме того, в приложение нужно было добавить настройки — для этого WP8 не предоставляет встроенных средств, нужно реализовывать логику самому. Впрочем, ничего сложного в этом нет — глобальный синглтон с полями настроек и логикой сохранения/загрузки:

public enum DesiredVideoQuality
    {
        Auto, // According to screen size
        Q240p,
        Q360p,
        Q480p,
        Q720p,
        Q1080p
    }

    public class AppSettings
    {
        const string ConfigName = "config.json";
        public static AppSettings Instance;

        public bool LoadPreviews;
        public bool SaveHistory;
        public int DesiredQuality;
        
        static AppSettings()
        {
            Instance = new AppSettings();
        }

        public static void Load()
        {
            var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();

            if(storage.FileExists((ConfigName)))
            {
                StreamReader reader = new StreamReader(storage.OpenFile(ConfigName, FileMode.Open));
                string str = "";

                while (!reader.EndOfStream)
                    str += reader.ReadLine();

                reader.Close();
                Instance = JsonConvert.DeserializeObject<AppSettings>(str);
            }
            else
            {
                // Load default settings
                Instance.SaveHistory = true;
                Instance.LoadPreviews = true;
                Instance.DesiredQuality = 0;
            }
            
        }

        public static void Save()
        {
            var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();

            StreamWriter writer = new StreamWriter(storage.CreateFile(ConfigName));
            writer.Write(JsonConvert.SerializeObject(Instance));
            writer.Close();
        }
    }

WP предоставляет специальное изолированное хранилище для пользовательских программ — IsolatedStorage, в которое нельзя добраться из остальной системы (без разблокированного загрузчика и режима Mass Storage). Там же можно хранить и конфиги — правда с некоторым API для файлов сильно перемудрили — навязывать распараллеливание чтения обычно маленьких файлов — это совсем уже.

Итак, буквально за сутки разработки у меня получилось реализовать приложение, которое может выводить списки ютуба по региону (тренды/популярное), может искать видео и воспроизводить ролики с различными разрешениями. Кроме того, приложение умеет подгружать превьюшки и имеет собственный раздел истории. Неплохо за 24 часа для программиста, который фактически не имел опыта с платформой UWP/WinRT в прошлом, да? :)

ВК


Теперь пришло время реализовать клиент ВК! Фактически, ничего сложного в реализации клиента с базовым функционалом нет — это всё такая же «морда» к данным с сервера, к которым добавляется необходимость получать уведомления и реализовывать логику обновления данных.
На этот раз, я решил выбрать API WP8.1: оно гораздо более богатое на возможности и ближе к современному UWP, чем Silverlight из WP8. Так уж сложилось, что API обычного WP8 ближе к WP7 и совместимо с WP8.1 только с помощью специальной прослойки.

Я не ставил целью написать полноценную замену ныне не рабочему официальному клиенту, но я хотел чтобы моё приложение поддерживало базовый функционал:

  • Мессенджер: Конечно же, самое важное в нашем клиенте — это мессенджер.
  • Музыка: Куда ж без удобной ВК музыки? Её реализация в кастомных клиентах отнюдь несложная, но достаточно костыльная из-за политики ВК в отношении лицензирования аудио. Снова будем идти на хаки, дабы получить работающее приложение!
  • Новости: Помимо общения и прослушивания музыки, бывает потребность полистать ленту — дабы узнать новости, или посмотреть свежие мемчики.

Начал я с реализации окна с диалогами и продумывания навигации приложения. WP8.1 всё ещё не имел концепции боковых менюшек, поэтому реализовывать панель навигации пришлось самому. Вместе с ней была реализована верхняя часть, которая содержит в себе заголовок со статусом и анимацию загрузки:

image

Класс-менеджер для общения с API ВК я решил реализовать по тому же принципу, что и для клиента YouTube: у нас есть два метода на всё-про всё, один сразу десериализовывает ответ в виде объекта Root (для каждого типа ответа — он свой, все они описаны в Data.Packet.Root):

public void RequestMethod<T>(string method, Action<T> onReady, Action<string> onError, string argFormat, params object[] args)
        {
            string url = string.Format("{0}/method/{1}?access_token={2}&v={3}{4}", APIUrl, method, token, APIVersion, string.Format(argFormat, args));

            HttpWebRequest webRequest = WebRequest.CreateHttp(url);
            webRequest.Method = "GET";
             
            Log.WriteLine("Requested method {0}", method);

            webRequest.BeginGetResponse((IAsyncResult res) =>
            {
                try
                {
                    Log.WriteLine("Async response");
                    WebResponse response = webRequest.EndGetResponse(res);
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    string json = reader.ReadToEnd();

                    Log.WriteLine("Got response");

                    JObject obj = JObject.Parse(json);
                    if(obj.Property("error") != null)
                    {
                        Log.WriteLine("API error occured: {0} {1}", obj["error"]["error_code"], obj["error"]["error_msg"]);
                        onError(obj["error"]["error_msg"].ToString());
                    }
                    else 
                    {
                        Log.WriteLine("Deserializing");
                        T t = JsonConvert.DeserializeObject<T>(json);

                        if (t != null)
                            onReady(t); 
                        else
                            onError("Deserialization failed");
                    }
                }
                catch (WebException e)
                {
                    Log.WriteLine("WebException error occured");
                    onError("WebException: " + e.Message);
                }
            }, null);
        }

До async/await я не дозрел и здесь :)
Спустя достаточно короткое время, у меня уже была готова подгрузка диалогов:

image

Реализация обновления во всех разделах одинаковая: есть метод RequestUpdate, который начинает процедуру обновления и получает данные с сервера, а затем ставит в очередь задачу на обновление UI из основного потока с помощью UpdateUI:

private void UpdateUI(Data.Messages.Root root)
        {
            foreach(Data.Messages.Item item in root.response.items)
            {
                UI.MessageView msgView = new UI.MessageView();
                msgView.SetInfo(item, item.from_id != profile.id);

                contentMain.Children.Add(msgView);
            }
        }

        private void RequestUpdate()
        {
            VKAPI.Instance.RequestMethod<Data.Messages.Root>("messages.getHistory", (Data.Messages.Root root) =>
            {
                Utils.SubmitOnUiThread(Dispatcher, () =>
                {
                    UpdateUI(root);
                });
            }, DefaultErrorHandler, "&user_id={0}&count=200", profile.id);
        }


И механизма загрузки/отправки сообщений.
В целом, с этим ничего сложного нет, однако теперь самое время разобраться с нотификациями. Пуши я пока-что поднять не смог, вместо них пока что лонгполлинг — достаточно для нотификаций пока приложение находится в фоне, но система со временем «прибивает» неактивные задачи, а сделать «бесконечный» фоновый таск как в Android не выйдет — система очень строго относится к любой фоновой работе.

image

Пришло время заняться музыкой — вот это действительно важный функционал! Для работы с аудио, я использовал довольно старый, но известный способ, который ВК пока что не пофиксил. Не то чтобы это из вредности, просто сами ВК особо не идут на контакт для интеграции аудио в своё приложение — исключением стали лишь очень крупные клиенты, как Kate Mobile — а значит можно реализовать действительно важные штуки: например, скачивание треков напрямую в музыкальную библиотеку, дабы их можно было послушать оффлайн! Вся работа с музыкой производится через прокси-сервер, поэтому аудио должно быть открыто.

image

Реализация фонового прослушивания музыки достаточно похожа на другие платформы, но в то же время заметно отличается. Само приложение может воспроизводить звуки с помощью MediaElement или BackgroundMediaPlayer, однако при сворачивании звук будет приостановлен (в отличии от MediaPlayer на Android). Для фонового прослушивания музыки, Microsoft решили сделать отдельный сервис BackgroundMusicPlayer, который запускается при попытке получить доступ к плееру из программы. Общаться с этим сервисом можно через межпроцессные вызовы — RPC и система предоставляет для него API. Вкратце: нам нужно создать фоновую задачу в виде отдельного модуля WinRT, который будет получать RPC-посылки от Foreground приложения и если нужно — отсылать ответы обратно. Ничего сложного!

private void OnReceiveMessage(object sender, MediaPlayerDataReceivedEventArgs e)
        {
            string method = (string)e.Data["method"];

            switch (method)
            {
                case "play":
                    string url = (string)e.Data["url"];
                    BeginPlay(url);

                    break;
                case "info":
                    string track = (string)e.Data["title"];
                    string artist = (string)e.Data["artist"];
                    UpdateSMTC(track, artist);

                    break;
                case "pause":
                    BackgroundMediaPlayer.Current.Pause();
                    break;
            }
        }

image

Отдельного внимания заслуживает механизм скачивания музыки в библиотеку. В WP, программы не могут просто так «вторгнуться» в личное пространство пользователя — им обязательно нужны разрешения. Но это ладно, запросить разрешение — совсем не проблема. Зато настоящая проблема — ПОЛНОСТЬЮ асинхронный API. Захотел найти дескриптор файла в ФС — асинхронно, захотел его открыть — снова асинхронно. Поскольку у меня вся работа по скачиванию ведется в отдельном воркере и я не боюсь за дедлоки, пришлось лепить костыли с Task.Wait() :)

HttpWebResponse response = (HttpWebResponse)webReq.EndGetResponse(res);
                    System.IO.Stream stream = response.GetResponseStream();
                    byte[] buffer = new byte[response.ContentLength + 128]; // 128 - ID3v1 length
                    int ptr = 0;
                    
                    while(ptr < response.ContentLength)
                    {
                        int len = 4096;

                        if (response.ContentLength - ptr < 4096)
                            len = (int)response.ContentLength - ptr;

                        ptr += stream.Read(buffer, ptr, len);
                        onProgress(ptr / response.ContentLength);
                    }

А ещё ВК возвращает mp3 без ID3-тегов, поэтому мне пришлось вручную их дописывать, дабы музыка в плеере удобно сортировалась:

Utils.ID3Tag.Fill(desc.artist, desc.title, "Неизвестен").CopyTo(buffer, (int)response.ContentLength);


Кроме того, дабы иметь возможность управлять музыкой из других приложений и экрана блокировки, Microsoft предоставляет т.н интерфейс SMTC — общий оверлей окна регулировки громкости, который позволяет управлять воспроизведением музыки. Его реализация простая до жути — просто включаем нужные кнопки (IsPlayEnabled, IsPauseEnabled и.т.п), добавляем обработчик события нажатия кнопки и обновляем информацию и обложку с помощью DisplayUpdater.

image

Заключение


Вот таким образом, буквально за несколько дней мы реализовали клиенты нужных нам приложений с базовым функционалом. Разработка клиента YT заняла ровно сутки, разработка клиента ВК — двое суток. Но можно ли всем этим добром по настоящему пользоваться и как оно работает на настоящем устройстве? Смотрите ниже:

Весьма достойно, да? Ещё до публикации статьи, я выложил клиент YT на 4pda и в профильный Telegram-чатик — люди благодарны и действительно довольны. Только в англоязычном чате о WP8.1 (не вклюая WM10 и WP7/WP8) более 2х тысяч человек! Так что да, девайсы прошлых лет действительно нужны достаточно большому числу пользователей.

image

image

Ну а разработка клиентов для меня была эдаким челленджом — пилить что-то полезное под новым API всегда интересно, дак ещё и сами девайсы очень крутые с точки зрения UX и скорости работы. А вы как считаете? Жду ваше мнение в комментариях!

image

Возможно, захочется почитать и это:



Комментарии (71)


  1. bodyawm Автор
    30.08.2023 08:04
    +9

    Друзья! Ну вы посмотрите на этот балдежный девайс - HP Elite X3! Это реально крутейшая пушка для своих лет была. Snapdragon 8xx, Windows 10 Mobile, здоровый дисплей с огромным разрешением и док-станция для подключения к монитору... Какой же это крутяк неописуемый!

    Именно из-за таких девайсов винфон и должен был жить! Когда нить я таким и сам обзаведусь.

    А Samsung Ativ S? Практически Galaxy S4 на базе Windows Phone! А как они шустро работали. Просто сказка


    1. bodyawm Автор
      30.08.2023 08:04
      +1

      Судя по предыдущей статистике, статьи о написание приложений под девайсы прошлых лет весьма интересны вам :)

      Постараюсь об этом писать побольше - в том числе с подобными инструкциями о поиске SDK в закромах архивов, деплоинге и подробном описании API каждой платформы и что в ней было интересного


    1. MaFrance351
      30.08.2023 08:04
      +3

      Ещё и дизайн этого Elite обалденный, под стать топовому железу...


      1. bodyawm Автор
        30.08.2023 08:04

        Когда нить я и сам похожоу с ним))


    1. Quackerjack
      30.08.2023 08:04
      +2

      Пользуясь случаем, ситуация дурацкая. У меня валяется не использованный, но распакованы чехол этот HT Elite X3, и кажется еще защитное стекло (не уверен). Я начал покупку гаджета с с конца, с обвеса, а потом передумал брать сам телефон... Отдам бесплатно, владельцу девайса, если такие остались. В свое время он действительно казался "пушкой", особенно в контексте корпоративного использования! =)


      1. bodyawm Автор
        30.08.2023 08:04

        Ееех, вот если я себе закажу его!))


  1. sparhawk
    30.08.2023 08:04
    +2

    Фактически, это стандартизация ARM-железа.

    Это не стандартизация, это заточенность только под одного производителя SoCQualcomm


    Пока разработчики Linux мучались с поддержкой всего разнообразия устройств под все платформы, разработчки Windows ждали, пока вендоры сами напишут драйвера. Под Windows для ПК вендоры писали, деваться было некуда.
    А на Windows Phone все ожидаемо забили. Договорились только с Qualcomm и NVidia. Еще каким-то чудом в списке есть устройство на Rockchip с графикой Mali (вряд ли эксперимент был удачным), вроде еще поддерживалась графика от Vivante.


    1. bodyawm Автор
      30.08.2023 08:04

      Вообще, именно с точки зрения концепции - с заточкой под квалков не соглашусь, т.к реализовали UEFI судя по всему не они, а именно Microsoft. У квалков вторичный загрузчик (который после BootROM) может быть у каждого вендора свой - на ведрах это производные от lk (little kernel), у каждого свой набор фишечек. Но по факту так и получилось, что все девайсы были на квалке :)

      Microsoft в 2015 году очень хотели запилить поддержку MediaTek в своих девайсах. Но вопрос был в том, что у медиатека большой парк железа сам по себе и существующие дрова под ведроид жуткие.


      1. sparhawk
        30.08.2023 08:04

        Согласен, концепция с опорой на стандарт UEFI хорошая. Жаль даже, что Intel внезапно не стала ее поддерживать, используя свой SFI (и мы не увидели Windows PC Phone — смартфоны на x86 и классическом ядре Windows NT с потенциальной поддержкой всего софта, что есть для PC).


        У Qualcomm, как понимаю, с тех пор UEFI является одним из этапов загрузки на всех устройствах, даже с Android.


        Но есть еще и другие стандарты, особенно вывода графики. DirectX — не очень-то распростарненный стандарт, если брать всё многообразие платформ для устройств с GUI.


        1. MaFrance351
          30.08.2023 08:04
          +1

          Хотя вот X86-мобилы вполне себе были. Асус и Хреново их выпускали. Но дальше запуска Windows через QEMU KVM вроде бы дело не дошло.


          Хотя задумка телефона на полноценной Windows наверняка была неплохой.


          1. sparhawk
            30.08.2023 08:04
            +2

            Были смартфоны на Intel Atom, но в них почему-то использовался стандарт загрузки SFI, а не более общепринятый UEFI, совместимый с Windows


            1. MaFrance351
              30.08.2023 08:04

              А это не те ли самые, о которых я? Asus Zenfone 2 и Lenovo какой-то серии К.


              1. bodyawm Автор
                30.08.2023 08:04

                Те. Вон я запостил один из таких Lenovo ниже :) Еще был ZTE Geek


        1. bodyawm Автор
          30.08.2023 08:04
          +3

          Согласен, концепция с опорой на стандарт UEFI хорошая. Жаль даже, что Intel внезапно не стала ее поддерживать, используя свой SFI (и мы не увидели Windows PC Phone — смартфоны на x86 и классическом ядре Windows NT с потенциальной поддержкой всего софта, что есть для PC).

          Вот насчет x86 атомов в мобилках дико плюсую. Там были реально крутые перспективы запилить настоящие стандартизированные смартфоны, которые можно легко обновить и на которых можно запускать самые разные ОС! У меня сейчас есть Lenovo K900 - очень нравится, хоть и горяччч!

          UEFI как стандарт в квалках вроде чуть-чуть позже появился, до этого юзался все так же lk (как и в медиатеках):

          DragonBoard™ 410c based on Qualcomm Snapdragon™ 410E processor Little Kernel Boot Loader Overview (manuals.plus)

          Direct3D сам по себе - это API. Как он реализовывается под капотом - это забота вендора драйвера. Те же самые снепдрегоны с вп отлично работали с GLES2.0 - 3.0 на Android :) Я хвалил D3D именно за те фишки, в которых он изначально превосходит GL


        1. XenRE
          30.08.2023 08:04
          +1

          Я упоролся и портировал на SFI freeldr от ReactOS, он может и WinXP загрузить если что. В принципе хоть как-то запустить винду на SFI — задача вполне решаемая, но потом встает другая проблемма — откуда взять драйвера. Но если кто-то захочет развить эту тему — могу помочь по возможности.


    1. bodyawm Автор
      30.08.2023 08:04

      Да и если вспомнить, Qualcomm имела какое-то соглашение с майками. Nokia изначально не хотела работать с квалками из-за каких-то юридических проблем, привыкнув к ламповым омапам, которые юзались и в N900, и в N9, и в Symbian-смартфонах


  1. gtwenty
    30.08.2023 08:04
    +1

    Эх, а я было подумал, что под WP7. Уж думал накатить на старенький HTC HD2 Windows Phone 7 и погонять как в старые добрые времена. Что ж, попробую сам.


    1. bodyawm Автор
      30.08.2023 08:04

      Приветствую! На хд2 есть возможность поставить уже анлокнутый WP7, так что скорее всего даже отладка прям из визуалки будет работать :)

      API там не сильно отличается от восьмерки (но не 8.1) и YouTube можно попробовать бэкпортировать без проблем.


      1. gtwenty
        30.08.2023 08:04
        +1

        Вчера достал HD2 из коробки, включил (сейчас он на стоковой WM6.5 с божественным HTC Sense), решил усложнить себе челлендж - написать мини-клиент ВК под WM6.5


        1. bodyawm Автор
          30.08.2023 08:04

          Документацию можно найти на

          https://dev.vk.com

          Для Json можно попытаться заюзать старую версию Newtonsoft.Json - с таргетом на 2.0.

          В репозитории в конце статьи можно найти пример как с этим всем работать :)


          1. gtwenty
            30.08.2023 08:04
            +1

            Уже работал с ВКшным API. Тут, скорее, будет проблема со специфичными для платформы моментами - работа в фоне, уведомления и т.д. Пока застрял на уведомлениях.


            1. bodyawm Автор
              30.08.2023 08:04
              +1

              Такс, смотри, я тож под винмобайл писал подобие клиента вкшечки (только сообщения). По порядку:

              1. Приложения в фоне могут крутится хоть 24/7, WinCE не имеет механизма для автоматического закрытия старых приложений.

              2. Уведомления можно реализовать либо в виде виндовых нотификаций (как при подключении к Wi-Fi и.т.п), либо самому, создавая окно поверх всех остальных.

              3. Можешь организовать уведомления в отдельном процессе - так будет даже более правильно, поскольку будет возможность выгрузить основной гуй из памяти. Поскольку пушей у нас все равно нет, лучше всего делать проверки относительно редко - раз в 20-30 секунд. Как альтернатива пушам - Longpolling.

              Для деплоя используй виртуалку с WinVista/WinXP и VS2005/VS2008.


  1. timur__timur
    30.08.2023 08:04
    +2

    Круто ) Ностальгические эмоции, будто вернулся в 2014, когда сам тоже пытался писать клиент под ВК, но для BlackBerry


    1. bodyawm Автор
      30.08.2023 08:04

      Под блекберри нативно уже ничего не задеплоить вроде-бы :(


      1. MaFrance351
        30.08.2023 08:04
        +1

        Насколько помню, там с отключением серверов производителя пропала возможность подписывания приложений, увы.


  1. MaFrance351
    30.08.2023 08:04
    +2

    Неплохо, неплохо!
    У самого есть несколько аппаратов на WP. Увы, не довелось ею попользоваться в эпоху её актуальности, но сама система мне очень нравилась.
    Даже было желание попробовать что-то под неё написать, но руки так и не дошли. Хотя в сравнении с более старыми платформами в плане поиска софта, сборки программы, запуска и отладки там уже всё намного проще, насколько я слышал.


    Хах, ещё и спустя три года простоя оживил хаб разработки под WP…


    1. bodyawm Автор
      30.08.2023 08:04

      Да, разработка под WP - одно удовольствие, если не принимать во внимание перегиб с async'ами в некоторых местах но в целом все прям реально классно! XAML - очень мощная и крутая система, датабиндинг - крутая штука, система анимаций довольно мощная (я там поднаврал - её можно создавать как декларативно, так и императивно).

      Кроме того, для каких-то модулей можно использовать C++. Ну и игры тоже пишутся как на плюсах, так и на C# (SharpDX)


  1. ymir
    30.08.2023 08:04
    +2

    С каждой вашей новой статьей я все больше хочу воскресить свою нокию люмию 1320 ????


    1. bodyawm Автор
      30.08.2023 08:04

      Их чутка геморнее разблокировать, но пользоваться софтом можно)


      1. MaFrance351
        30.08.2023 08:04

        Их чутка геморнее разблокировать

        О, кстати. А как обстоят дела с разработкой под старые ябблы? Реально ли где-то намутить древний Xcode и попробовать собрать что-то, скажем, под iPhone 3GS?


        1. bodyawm Автор
          30.08.2023 08:04

          Да, вообще легко, если для тебя objective-c не проблема. Swift'а, увы, не будет.

          Джейлбрейкни девайс и сделай вот так:

          iphone - Is it possible to compile and run an Xcode project on a jailbroken device without a paid developer certificate? - Ask Different (stackexchange.com)

          Я лично проверял и смог задеплоить из VMWare на реальное устройство.


          1. MaFrance351
            30.08.2023 08:04
            +1

            О, неплохо.


            Кстати, раз уж упомянули: а не думал написать что-то про старые компы Apple на базе PowerPC? Какой-нибудь там Mac Mini A1103 можно вполне за приемлемую цену купить...


            1. bodyawm Автор
              30.08.2023 08:04
              +2

              Да, мне подарили PowerBook G4 в началае лета :)


        1. tonyrouge
          30.08.2023 08:04

          древний xcode можно скачать прямо на сайте эпла, предварительно там же зарегистрировавшись как разработчик (никаких взносов платить не надо), мне как-то нужна была некроверсия xcode — без проблем скачал и собрал нужный проект


          1. bodyawm Автор
            30.08.2023 08:04
            +2

            Даже регистрироваться не нужно, если аппарат с джейлом :) Проверено лично!


  1. tonyrouge
    30.08.2023 08:04
    +1

    однако теперь самое время разобраться с нотификациями. Пуши я пока-что поднять не смог

    Вроде как это из-за отключения серверов WP на стороне M$. То есть, ничего не получится сделать :(


    1. bodyawm Автор
      30.08.2023 08:04

      Вп8.1 юзает общую систему пушей с W10/W11, так что вроде еще должно работать


      1. tonyrouge
        30.08.2023 08:04

        так на wp10 давно пуши не работают, закончились вроде даже раньше чем вотсап убрал поддержку


        1. bodyawm Автор
          30.08.2023 08:04

          В LunaVK рбаотали вроде


          1. tonyrouge
            30.08.2023 08:04

            тут не подскажу, ибо не юзаю лет десять

            от телеги очень давно умерли, увы (при том что сама программа древней версии работает)


    1. Didimus
      30.08.2023 08:04

      Можно поднять прокси для пушей.


  1. Dark_Purple
    30.08.2023 08:04
    +5

    Классные корпуса были у Нокиа из поликарбоната.


    1. bodyawm Автор
      30.08.2023 08:04

      Согласен!


      1. MaFrance351
        30.08.2023 08:04
        +1

        А ещё у многих этих нокий камеры с лёгкостью уделывают практически любые средненькие нынешние ведроиды.


        1. Didimus
          30.08.2023 08:04

          Я видел вблизи фото с 40- мегапиксельной люмии. Чудо не произошло


  1. hurtavy
    30.08.2023 08:04
    +2

    Круто. Кто бы ещё сделал клиент того же ВК для десктопной винды :))


    1. Didimus
      30.08.2023 08:04

      Так в браузерах есть специальные мини приложения?


      1. hurtavy
        30.08.2023 08:04

        Хотелось бы без браузера


        1. vssavin
          30.08.2023 08:04

          Вот это https://github.com/danyadev/vk-desktop не пробовали?


          1. lennylizowzskiy
            30.08.2023 08:04

            Так это Электрон жеж


          1. hurtavy
            30.08.2023 08:04

            Судя по описанию, он ничего не умеет, кроме текстовых сообщений


        1. AdvTechnoKing
          30.08.2023 08:04

          1. hurtavy
            30.08.2023 08:04

            да, спасибо, я уже посмотрел :) Неожиданно даже обнаружил, что ВК таки стали дорабатывать свой клиент. Хотя у них куча новых глюков наплодилось. Да и за 5 часов этот клиент у меня выжрал 3 гига памяти


    1. elorucov
      30.08.2023 08:04

      Есть такое: https://elor.top/laney. Даже Windows 10 mobile поддерживает.


    1. iworld2rist
      30.08.2023 08:04

      Есть решение от стороннего разработчика: https://elor.top/laney/
      Проект хороший, не без багов, будем говорить честно, однако разработчик слышит свою аудиторию и по мере возможностей исправляет ошибки.


    1. kleverg
      30.08.2023 08:04

      Есть Laney


  1. Didimus
    30.08.2023 08:04

    Только вчера достал 525 люмию. Ожидаемо, ничего не устанавливается. Ветка на 4пда закрыта (ведь никому не нужно).

    Хотелось бы клиентов Яндекс карт, диска, телеграм.

    Отличный телефон школьника бы получился


    1. Kudelkin
      30.08.2023 08:04

      Если бы браузер открывал все ресурсы, можно было бы пользоваться и в нынешнее время.


  1. Deff_on
    30.08.2023 08:04

    Lumia 740 у меня афигенный аппарат и по нынешним временам тоже, не пользуюсь уже лет 5, но скоро чувствую снова начну


  1. CrashLogger
    30.08.2023 08:04

    >неправильно написанные Android-приложения легко могут подвисать при выполнении какой-то работы

    Android запрещает выполнять IO операции в UI потоке. При попытке это сделать, приложение будет убито системой. Подвисания Android обычно вызваны общей нехваткой памяти, когда система начинает выгружать временно неиспользуемые компоненты, а потом, когда они понадобятся, загружать их обратно. При этом тормозит обычно не конкретное приложение, а вообще весь аппарат )


    1. bodyawm Автор
      30.08.2023 08:04

      Если приложение Foreground, то до наступления ANR ведроид точно не прибьет приложение, но при этом лаг будет виден :


      1. mike872
        30.08.2023 08:04

        "В отличии от Android, никаких проблем с TLS не возникло: смартфон смог без проблем связаться с инстансом Invidous и получить данные о видео в трендах. " -


        а можно в этом месте немного поподробнее?, какой версией TLS пришлось пользоваться, и не отключены ли там "отключает процедуру проверки SSL/TLS-сертификатов", почитал телеграмм канал и хотя там и указано, что платежки и некоторые соц сети работать не будут, вопрос в приватности данных WP8-WP10, те же VK и google/youtube аккаунты.
        Тема актуальна, читал где-то что (и не только читал) в Европе подумывают разрешить удаленный доступ к камерам и микрофонам телефонов, не говоря уже о перемещениях, геолокации и адресах и предпологаемом соц. положении, эта статистика может быть при желании доступна магазинам и т.д., которые даже подсчитывают сколько потенциальных покупателей проходят мимо витрин, думаю уязвимы телефоны с операционками android и ios, (хотя данные сливают и отдельные приложения) а платформа WP в силу своей малочисленности никому не сдалась. У пользователей WP есть редкая возможность оставаться относительно анонимными, пользуясь относительно современным функционалом. Если только... получить доступ к службам или сервисам какого-либо из приложений не будет крайне просто....

        Цитата: SSL/TLS-соединения софта уязвимы для широкого спектра MitM-атак. При этом MitM-атаку можно провести зачастую даже без подделки сертификатов и без похищения приватных ключей, которыми серверы подписывают свои сертификаты. MitM-атаку можно провести, просто эксплуатируя логические уязвимости, которые присутствуют в процедуре проверки SSL/TLS-сертификата на стороне клиентского софта.

        В результате MitM-злоумышленник может, например, собирать токены авторизации, номера кредитных карт, имена, адреса и прочее — у любого продавца, который использует уязвимые веб-приложения обработки платежей.

        Поставщики мобильного софта, которые берут за основу семпл-код AdMob для связи своих приложений с AdMob-аккаунтом, тоже уязвимы — они позволяют атакующему захватывать учетные данные и получать доступ ко всем его Google-сервисам. К примеру, из-за некорректной проверки сертификатов в таких мессенджерах, как Trillian и AIM, MitM-злоумышленник может похитить учетные данные для входа ко всем сервисам Google (включая Gmail), Yahoo и также к сервисам Windows Live (в том числе SkyDrive)."


        1. bodyawm Автор
          30.08.2023 08:04

          На вп давно уже нет ни нативной рекламы, ни похоже даже пушей :(


  1. daggert
    30.08.2023 08:04
    +2

    Я вот держу свой HTC Radar в руках и все еще радуюсь его интерфейсу и его дизайну. Это просто прекрасно, все эти плитки, строгие анимации и плавный скроллинг.
    Смотрю на него и вспоминаю почему я с WP 7 ушел на WP 10 (lumia 650) - только ради синхронизации контактов и из-за чертового Zune. ВК тогда еще был рабочий, про телегу не помню. А сейчас еще взял в руки люмию на 10тке... Все-таки они мне нравятся. Приятные смартфоны.


  1. grvelvet
    30.08.2023 08:04

    Был lumia 640, очень приятный телефончик. И снимал лучше чем какой нибудь сяоми редми. Жаль что собственными руками убили такой проект.


  1. bolkogor
    30.08.2023 08:04

    Перепробовал много телефонов на винде: htc 8x и 8s, lumia 520, 720, 920 и 1020. Шикарные аппараты и система, но к сожалению прекращение поддержки WhatsApp вынудило перейти на андроид. 1020 был первый аппарат, который я починил с помощью донора после залития.

    А первый был 8x, до сих пор помню этот восторг при первом использовании.


  1. saboteur_kiev
    30.08.2023 08:04
    +1

    Основная проблема винфонов - они не выпускаются, не продаются и не поддерживаются.
    Заменить батарею в стареньком винфоне уже проблема. Пройдет еще пару лет и все. А если не будет железа, не будет смысла писать под него софт вообще.

    Я бы хотел, чтобы в МС появился кто-то с яйцами и снова открыл направление winphone. Пусть бы оно было маленьким, и убыточным (маленькое убыточное проще поддерживать чем большое убыточное), но мне кажется что они вполне могли бы довести его до стабильного состояния и забрать свою часть рынка.


    1. bodyawm Автор
      30.08.2023 08:04

      Как это было и у BlackBerry когд-ато


  1. altman
    30.08.2023 08:04

    Было 3 люмии, 830, 920 и 1020 (могу приврать в моделях) Дизайн нравился жутко и интерфейс тоже. Я страдал от недостатка софта и продолжал верить в светлое будущее платформы... действительно жалко, что не взлетело


  1. hudyakov74
    30.08.2023 08:04

    Проблема микрософта - берутся за все, так же легко выбрасывают.


  1. PeterKhud
    30.08.2023 08:04

    Я тоже когда-то был счастливым обладателем люмии (уже и модель не помню). Согласен с автором, уход MS с рынка мобильных устройств потеря. У ребят был готовый рецепт успеха - делаешь спокойно свои телефоны, допиливаешь экосистему (пк на винде + телефон) так как это всегда делали ребята с Купертино и давишь рынок катком. Да, эппл они бы не перебили (учитывая то как майкрософт любит класть на все здоровенный болт), но третий крупный игрок у нас был бы и пожалуй я бы уже седьмой год не ходил бы с айфоном а был бы счастливым обладателем того же WP/