MonoDroid, Fizy ve Gizli Uygulamam IAmMusicBox

MonoDroidDaha önceden blog üzerinden duyurmadığım ikinci bir android uygulamam daha var. Adı I Am MusicBox. Burada duyurmak istedim fakat bir türlü kısmet olupta bir iki satır yazıp tanıtımını yapamadım. https://play.google.com/store/apps/details?id=com.erhanbaris.iammusicbox buradan indirip deneyebilirsiniz. Bu uygulama benim için Monodroid’de ne nasıl yazılır konusunda kafamda ki soru işaretlerini gidermeme oldukça yardımcı oldu. Gecelerce oturup saatlerce uğraşıp sonunda bu ürünü ortaya çıkarttım. Her ne kadar pek talep olmasa da ortaya çıkan çocuk benim çocuğum ondan dolayıda onu seviyorum :) Uygulamanın kodlarını parça parça blogumda yayınlayıp MonoDroid’e meraklı olan kişiler için belki bir faydası dokunur diye yayınlama kararı aldım. İlk olarak internet üzerinden müzik dinletmemi sağlayan kısımdan başlamak istedim. 

fizyUygulamanın arkaplanında Fizy.com sitesinin kendi sunucularından faydalandım. Fizy’de ki arkadaşlara bu konuda email atsam da bana geri dönüş yapmadılar bende sorun olmaz diye internette özgürce uygulamamı yayınladım :) Sizlerede o kısımın kodunu paylaşayım.

 IMusicServer.cs

namespace ErhanBaris.ListenMusic.Core.Server
{
    using System;
    using System.Collections.Generic;

    using ErhanBaris.ListenMusic.Core.Model;

    /// 
    /// The MusicServer interface.
    /// 
    public interface IMusicServer : IDisposable, ICloneable
    {
        List GetSongs(string searchText);

        string GetSongUrl(SongInfo songInfo);
    }
}

Öncelikli olarak Fizy’e erişim kodlarını yazmadan önce bana gerekli olan sınıfın interface’ini yazdım ki daha sonradan Fizy ile ilgili bir sorun yada sıkıntı yaşar isem heryeri değiştirmek yerine bu interfaceden türetilmiş bir sınıf yazıp yerine koymak daha az uğraşmalı olacak ve aynı zamanda uygulamayı test etmem gerektiğinde Dummy sınıfını yazıp daha rahat testlerimi yapmama yardımcı olduğundan bu şekilde yapıyı kurguladım.  Burada dikkat ederseniz iki tane fonksiyon var. Birisinde şarkı listesini çeken, öbüründe de şarkının Url’sini alan fonksiyonlar.

FizyMusicServer.cs

    namespace ErhanBaris.ListenMusic.Core.Server
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.Specialized;
        using System.Globalization;
        using System.Net;
        using System.Text;

        using ErhanBaris.ListenMusic.Core.Model;
        using ErhanBaris.ListenMusic.Utils;

        /// 
        /// The fizy music server.
        /// 
        public class FizyMusicServer : IMusicServer
        {
            /// 
            /// The web client.
            /// 
            protected internal WebClient webClient = null;

            /// 
            /// The cookie.
            /// 
            private string cookie = string.Empty;

            /// 
            /// Gets the get cookie.
            /// 
            private string getCookie(string searchTerm)
            {
                if (string.IsNullOrEmpty(this.cookie))
                {
                    this.webClient = new WebClient();
                    this.webClient.Headers.Clear();
                    this.webClient.Headers.Add("X-Requested-With", "XMLHttpRequest");
                    this.webClient.Headers[HttpRequestHeader.Referer] = "http://fizy.com/search/" + searchTerm;
                    this.webClient.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                    this.webClient.Headers[HttpRequestHeader.UserAgent] =
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";

                    this.webClient.DownloadData("http://fizy.com/");

                    this.cookie = this.webClient.ResponseHeaders.Get("Set-Cookie");
                }

                return this.cookie;
            }

            /// 
            /// The dispose.
            /// 
            public void Dispose()
            {
                if (this.webClient != null)
                    this.webClient.Dispose();
            }

            /// 
            /// The get songs.
            /// 
            /// 
            /// The search text.
            /// 
            /// 
            /// The .
            /// 
            public List GetSongs(string searchText)
            {
                var returnValue = new List();
                var randomNumber = new Random().NextDouble();
                var values = new NameValueCollection
                    {
                        { "doctype", "" },
                        { "glx", "0.7353848288878037" },
                        { "length", "" },
                        { "p", "0" },
                        { "query", searchText },
                        { "rows", "60" },
                        { "search_type", "title" },
                        { "type", "audio" }
                    };

                var str1 = string.Empty;
                var stringBuilder = new StringBuilder();
                foreach (string str2 in values.AllKeys)
                {
                    stringBuilder.Append(str1);
                    stringBuilder.Append(ErhanBaris.ListenMusic.Core.Utils.HttpUtility.UrlEncode(str2));
                    stringBuilder.Append("=");
                    stringBuilder.Append(ErhanBaris.ListenMusic.Core.Utils.HttpUtility.UrlEncode(values[str2]));
                    str1 = "&";
                }

                this.webClient = new WebClient();
                this.webClient.Headers[HttpRequestHeader.Cookie] = "type=audio; doctype=all; duration=all; fma_shop=1; volume=0.5; fizy_session_id=\"ZWJiY2FiZWJkYjg0YmM0ZDQ4M2Q1MmUwMTQwNjBmOGFkZDg5ZDdiMjdlYzRjNTNmNDQ2ZTA2MGMzNzA1OTc2Mw==|1368019258|d605b25083945f9c4c03e5a66298b99704258fbe\"; fizy_session_validator=\"OWYyMDUxNmFmOWU0NGNlZjUyN2JjMjdhYjgxNzQzOGJkZDU4MmViNDAwZTI1NDk0MmQ2NGFkYjMxMzY2ZDljNA==|1368019258|950b74d65959774fb6901081fb6af20ad2cb8eed\"; xd=1; __webmon_visitor=4F33EB02-73F8-44FC-8C75-15287FC22C75; __utma=32863657.960651069.1368019270.1369248754.1369248790.8; __utmz=32863657.1368019270.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); bbnaut=dc90fb530ec0dff6; __utmc=32863657; volume=0.5; fma_blur=1; type=audio; doctype=all; duration=all; __utmd=1; __utmb=32863657.1.10.1369248790";
                //this.webClient.Headers.Add("Referer", "http://fizy.com/");
                //this.webClient.Headers[HttpRequestHeader.Host] = "fizy.com";
                this.webClient.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0";
                this.webClient.Headers[HttpRequestHeader.Referer] = "http://fizy.com/search/" + searchText;
                this.webClient.Headers[HttpRequestHeader.Accept] = "application/json, text/javascript, */*; q=0.01";
                this.webClient.Headers[HttpRequestHeader.AcceptLanguage] = "tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3";
                //this.webClient.Headers[HttpRequestHeader.ContentLength] = stringBuilder.Length.ToString();
                this.webClient.Headers.Add("X-Requested-With", "XMLHttpRequest");

                byte[] result = webClient.UploadValues("http://fizy.com/search", "POST", values);
                string ResultAuthTicket = Encoding.UTF8.GetString(result);

                var data = JsonUtil.GetObject(ResultAuthTicket);

                for (int i = 0; i < data.results.Count; i++)
                {
                    var minute = data.results[i].duration / 60;
                    var second = data.results[i].duration - (minute * 60);
                    returnValue.Add(
                        new SongInfo
                            {
                                SongData = data.results[i],
                                AlbumName = data.results[i].albumName,
                                Duration = data.results[i].duration,
                                SongId = data.results[i].ID,
                                SongName = data.results[i].title,
                                DurationReadable = minute.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0') + ":" + second.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0')
                            });
                }

                return returnValue;
            }

            /// 
            /// The get song url.
            /// 
            /// 
            /// The song info.
            /// 
            /// 
            /// The .
            /// 
            public string GetSongUrl(SongInfo songInfo)
            {
                var returnValue = string.Empty;
                try
                {
                    var values = new NameValueCollection
                    {
                        { "SID", songInfo.SongId }
                    };
                    var str1 = string.Empty;
                    var stringBuilder = new StringBuilder();
                    foreach (string str2 in values.AllKeys)
                    {
                        stringBuilder.Append(str1);
                        stringBuilder.Append(ErhanBaris.ListenMusic.Core.Utils.HttpUtility.UrlEncode(str2));
                        stringBuilder.Append("=");
                        stringBuilder.Append(ErhanBaris.ListenMusic.Core.Utils.HttpUtility.UrlEncode(values[str2]));
                        str1 = "&";
                    }

                    this.webClient = new WebClient();
                    //this.webClient.Headers[HttpRequestHeader.Cookie] = this.getCookie;
                    //this.webClient.Headers.Add("Referer", "http://fizy.com/");
                    //this.webClient.Headers[HttpRequestHeader.Host] = "fizy.com";
                    this.webClient.Headers[HttpRequestHeader.UserAgent] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
                    this.webClient.Headers[HttpRequestHeader.Accept] = "application/json, text/javascript, */*; q=0.01";
                    this.webClient.Headers[HttpRequestHeader.AcceptLanguage] = "tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3";
                    //this.webClient.Headers[HttpRequestHeader.ContentLength] = stringBuilder.Length.ToString();
                    //this.webClient.Headers.Add("X-Requested-With", "XMLHttpRequest");

                    byte[] result = webClient.UploadValues("http://fizy.com/fizy::getSong", "POST", values);
                    string ResultAuthTicket = Encoding.UTF8.GetString(result);

                    var data = JsonUtil.GetObject(ResultAuthTicket);


                    returnValue = data.source;
                }
                catch (Exception ex)
                {

                }

                return returnValue;
            }

            /// 
            /// The clone.
            /// 
            /// 
            /// The .
            /// 
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }

        public class FizySearchQueryResultModel
        {
            public string msg { get; set; }

            public string code { get; set; }

            public int numFound { get; set; }

            public double query_time { get; set; }

            public List results { get; set; }
        }

        public class FizySearchQueryResultSongModel
        {
            public string songID { get; set; }

            public string performer { get; set; }

            public int listenCount { get; set; }

            public string title { get; set; }

            public int sourceNumber { get; set; }

            public bool has_lyrics { get; set; }

            public string albumName { get; set; }

            public bool live { get; set; }

            public bool downloadable { get; set; }

            public string provider { get; set; }

            public int duration { get; set; }

            public string _id { get; set; }

            public string type { get; set; }

            public string ID { get; set; }

            public string songName { get; set; }
        }

        public class FizyPlayQueryResultModel
        {
            public string songID { get; set; }

            public int providerNumber { get; set; }

            public string title { get; set; }

            public string albumPic { get; set; }

            public string source { get; set; }

            public int duration { get; set; }

            public string type { get; set; }
        }
    }

Ekran biraz dar olduğundan dolayı kodların bazı yerleri karmaşık olarak görünüyor. Özellikle Fizy sunucuna kendimizi Firefox olarak tanıtık Cookie’leri gönderdiğimiz kısımlar bir karışık görünüyor. Fakat o kısımlar da aslında standart Http Header kısımlarından oluşuyor. Bu kısımları incelediğinize göre onların da ne olduğuna ve ne iş yaptığına dair fikriniz var diye düşünüyorum.

Kodlamayı bu şekilde yapmamın başka bir nedeni de Xamarin IOS ile kullanma durumunda IOS’a özgü bazı kısıtlamalar var ise onları daha rahat bir şekilde geçmek için. Yani eğer ki kullandığım bazı eklentiler yada kütüphaneler MonoTouch desteklenmezse (ki MonoDroid ile kullanılan şeylerin büyük bir çoğu MonoTouch ile de kullanlabiliyor) oraları değiştirmede sorun yaşamamak için.

Bu kısımda hiç bir şekilde Regex kullanmadım. Çünkü saolsun Fizy bana Json verisi döndürdüğünden dolayı tek yaptığım Model sınıflarımı oluşturup bu Json verilerini bu sınıfa atamak oldu. Ondan sonra da benden bu bilgiyi isteyen katmana bilgileri göndermek oldu.

Hepsi bu kadar :)

Aklıma gelmişken burada dikkat ettiyseniz Url geri çeviriyorum. Yani isteyen arkadaşlar Fizy için downloader yada daha farklı amaçlar içinde kullanılabilir 😉

Facebook Comments

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir