Windows Phone 8'de Uri Association

0 dakikada yazıldı

35533 defa okundu

Düzenle

Windows Phone için geliştirdiğiniz bir uygulamada işletim sistemi
genelde bir entegrasyon noktası açmak veya belki de yazdığınız birden
çok uygulamanın birbirine referans data gönderebilmesini sağlamak için
kullanabileceğiniz yöntemlerden biri de UriAssociation yöntemi. Bu
yöntemde uygulama işletim sistemi genelinde kendi Uri formatını
tanımlıyor ve bu Uri protokolü ile navigasyon gerçekleştiren bir
uygulama olduğunda otomatik olarak sizin uygulamanız açılıyor. Örneğin
YouTube uygulamasının vnd.youtube protokolü ile bir navigasyon
yaparsanız eğer cihazda YouTube uygulaması yüklüyse direk o uygulama
açılacaktır. Tabi ki siz de uygulamalarınızda bu tip prokoller
tanımlayabilirsiniz. Eğer bu protokolleri uygulama sitenizde de
yayınlarsanız belki başkaları da kullanarak sizin uygulamanıza referans
veri gönderebilir ve bir anlamda entegre olabilirler.

Nasıl yaparız?

İlk olarak yeni navigasyon protokolünü yani UriAssociation'ı
tanımlayacak uygulamadan başlayalım. Bu uygulamanın
WMAppManifest.xml dosyasını Visual Studio içerisinde "Open With /
XML Editor" diyerek elle açmanız gerekiyor. Sonrasında da dosyanın içine
yine elle aşağıdaki gibi prokol tanımımızı ekleyebiliyoruz.

[WMAppManifest.xml]

          <BackBackgroundImageURI></BackBackgroundImageURI>
          <BackTitle></BackTitle>
          <DeviceLockImageURI></DeviceLockImageURI>
          <HasLarge></HasLarge>
        </TemplateFlip>
      </PrimaryToken>
    </Tokens>
    <Extensions>
      <Protocol Name="ozelprotokol" TaskID="_default"
      NavUriFragment="Uri=%s" />
    </Extensions>
    <ScreenResolutions>
      <ScreenResolution Name="ID_RESOLUTION_WVGA"/>
      <ScreenResolution Name="ID_RESOLUTION_WXGA"/>
      <ScreenResolution Name="ID_RESOLUTION_HD720P"/>
    </ScreenResolutions>

Yukarıda XML dosyasının sadece bir kısmını paylaştım zaten renkli kısım
da tam olarak eklenmesi gereken kısım. Burada Name olarak istediğinizi
yazabilirsiniz, tabi özel karakterler kullanmak yok çünkü buradaki isim
protokol ismi olarak da Uri de kullanılacak olan isim. TaskId'yi aynen
bırakıyoruz. NavUriFragment ise yine aynen kalabilir, değiştirmenin pek
bir anlamı yok. NaviUriFragment'ın sonuna hedef uygulamaya
yönlendirilmek istenen pathUri eklenecek. Birazdan ona da bakacağız.

Giriş aşamasında ayarlarımız bu kadar. Şu anda yeni bir protokol
yarattık ve ona sahip çıktık. Sıra geldi bu protokol ile bir Uri
açıldığında bunu algılamak ve gerekli aksyonu alabilmek. Bizim
örneğimizde yukarıda yaptığımız ayarlar çerçevesinde aşağıdaki gibi bir
Uri kullanılarak uygulamamız açılabilir.

ozelprotokol:MainPage?ID=1

Görüldüğü üzere protokol adı en başta bulunuyor. Sonraki kısım ise
NaviUriFragment'taki Uri parametresi olarak gelecek. Genelde bu kısımda
bir operasyon adı ve birkaç tane de parametre gönderilir. Biz
örneğimizde operasyon adı olarak "MainPage", parametre olarak da bir ID
göndereceğiz. Operasyon adı olarak MainPage saçma gelebilir ki zaten
saçma :) Genelde operasyon adı hedef uygulama içindeki mantıklı
birşeylere yönlendirilir. Ben işin bu kısmı ile uğraşmamak ve sadece
örneği çalıştırmak adına operasyon adının hedef uygulamadaki bir Page'in
adı ile aynı tuttum :) Birazdan neden böyle yaptığımı daha net
göreceğiz.

Şimdi, konumuza dönersek, diyelim ki yukarıdaki gibi bir Uri bize geldi.
Bunu yakalamamız, çözmemiz ve uygulamamız içerisinde uygun sayfalara
yönlendirmemiz gerekecek. Bunun için bir UriMapper yazarak
RootNavigasyon'a ekleyeceğiz.

[OzelUriMapper.cs]

    class OzelUriMapper : UriMapperBase
    {
        public override Uri MapUri(Uri uri)
        {
            var tempUri = uri.ToString();

            if (tempUri.Contains("/Protocol"))
            {
                //Eğer Protokol ile gelmişse decode edelim.
                tempUri = System.Net.HttpUtility.UrlDecode(tempUri);

                //Uri var mı kontrol edelim.
                if (tempUri.Contains("Uri"))
                {
                    //Burada
ReWrite kararlarını vermemiz gerek.


                    //ReWrite ettiğimiz yeni Uri ile Redirection yapıyoruz.
                    return new Uri(yeniUriKind.Relative);
                }
            }
            return uri;
        }
    }

Yukarıda UriMapperBase'den gelen yeni bir UriMapper görebilirsiniz.
UriMapper'a direk uygulamaya gelen tüm Uri'ler gelecek, hatta zaten bu
Mapper'ı doğrudan uygulamanın RootFrame'ine ekleyeceğiz. O nedenle
aslında uygulama içerisindeki tüm navigasyonlar zaten buradan geçecek.
Mapping esnasında yaptığımız ilk kontrol gelen Uri'nin bizim protokol
ile gelip gelmediğini kontrol etmek. Eğer durum öyle ise parametresinde
bulunan veriyi Decode etmemiz gerekiyor.

Protok üzerinden gelen Uri bilgisi bu şekilde.
Protok üzerinden gelen Uri bilgisi bu şekilde.

Decoding sonrası da tam da elimize bizim istediğimiz ve en üstte
bahsettiğimiz Uri geçmiş olacak. O noktadan sonra da protokolün
çeşidine, operasyon adına ve geri kalan parametrelere bakarak farklı
kararlar verebiliriz.

[OzelUriMapper.cs]

    class OzelUriMapper : UriMapperBase
    {
        
public override Uri MapUri(Uri uri)
        {
            
var tempUri = uri.ToString();

            
if (tempUri.Contains("/Protocol"))
            {
                
//Eğer Protokol ile gelmişse decode edelim.
                tempUri = System.Net.HttpUtility.UrlDecode(tempUri);

                
//Uri var mı kontrol edelim.
                if (tempUri.Contains("Uri"))
                {

                    string operasyon = "";
                    string Id = "";

                    // Uri'de protokol şablonu var mı?
                    string ProtocolSablonu = "/Protocol?Uri=";

                    //Operasyonlar doğrudan farklı sayfalara maplenebilir.
                    int operasyonAdUzunlugu = tempUri.IndexOf("?"ProtocolSablonu.Length);
                    int IdUzunlugu = tempUri.IndexOf("="operasyonAdUzunlugu + 1);

                    operasyon = tempUri.Substring(ProtocolSablonu.LengthoperasyonAdUzunlugu 
                        - ProtocolSablonu.Length);
                    //ID o sayfaya gönderilebilecek bir başka parametre. Bunun gibi farklı
                     parametreler eklenebilir.

                    Id = tempUri.Substring(IdUzunlugu + 1);

                    string yeni = String.Format("/{0}.xaml?ID={1}"operasyonId);

                    //ReWrite ettiğimiz yeni Uri ile Redirection yapıyoruz.
                    return new Uri(yeniUriKind.Relative);
                }
            }
            
return uri;
        }
    }

Yukarıdaki kodun içine gerekli olan parsing işlemlerini de ekleyince
aslında istediğimiz tüm bilgileri almış oluyoruz. Elimizde operasyonun
adı var, parametrenin adı ve değeri de var. Ben basit bir şekilde
operasyon adını uygulamadaki sayfa adına map ediyoruz ve gelen Id
parametresini de o sayfaya ID parametresi olarak gönderiyorum. Sanırım
operasyon adını neden sayfa adı olarak kullandığımızı anlamışsınızdır :)
Tembellikten. Siz böyle yapmayın :)

ReWrite işlemi sonrası her zamanki gibi herhangi bir sayfa
OnNavigateTo'da bu bilgileri yakalayabilir.

[MainPage.xaml]

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            try
            {
                MessageBox.Show(NavigationContext.QueryString["ID"]);
            }
            catch (Exception)
            {
            }
            
            base.OnNavigatedTo(e);
        }

Yine diyorum, ben uygulama ilk açılırken çatlamasın diye hatayı yuttum
yukarıda, siz yapmayın :) Makalelerde kullandığım örneklerde anlatılan
konu dışındaki implementasyonları örnek almayın lütfen. Maksat konuyu
anlatmak :)

Son olarak yapmamız gereken birşey daha var. Tüm bu UriReWrite
olaylarının çalışması için hazırladığımız Mapper'ı RootFrame'e atamamız
gerek.

[App.xaml.cs]

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            
if (phoneApplicationInitialized)
                
return;

            
// Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            
// Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            
// Handle reset requests for clearing the backstack
            RootFrame.Navigated += CheckForResetNavigation;
            RootFrame.UriMapper = new OzelUriMapper();
            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

Hemen uygulamanın App.xaml.cs dosyasını açarak yukarıdaki
OzelUriMapper'lı satırı ekleyin ve işimiz bitsin :) Şimdi istediğiniz
bir uygulamadan aşağıdaki şekilde navigasyonlar verip direk bu
uygulamanın çalışmasını sağlayabilirsiniz.

[Başka uygulama, button_click]

        private async void Button_Click(object senderRoutedEventArgs e)
        {
            //Başka bir uygulamayı özel olarak tanımlı bir protokol üzerinden başlatıyoruz.
            await Windows.System.Launcher.LaunchUriAsync(new System.Uri("ozelprotokol:MainPage?ID=1"));
        }

Bunu sadece siz değil herkes yapabilir. Eğer aynı telefonda aynı
protokolü kullanan birden çok uygulama varsa bu sefer işletim sistemi
hedef uygulama seçtirmek için bir liste gösterecektir. Daha da güzeli
eğer bu şekilde bir link kullanılır ve linki kullanabilen bir uygulama
telefonda yoksa WP otomatik olarak marketplace'den bu protoklü açabilen
uygulamaları da listeleyip kullanıcıya tavsiye edebiliyor. Tabi ki o
listede sizin uygulamanız da yer alacak. Hem de bunlar için ek hiçbirşey
yapmanıza gerek yok.

Dikkat edilmesi gerekenler!

İlk dikkat edilmesi gereken nokta zaten işletim sistemi tarafından
kullanılan protokolleri kullanmamak. Bunların bir listesini
MSDN'de
bulabilirsiniz. Ek olarak bir de Nokia'nın ve marketplace'deki bazı
popüler uygulamaların kullandıkları protkoller var. Bu protokollerin bir
kısmının listesine de
Nokia'nın
sitesinden ulaşabilirsiniz. Bu protokolleri siz de kullanabilirsiniz.
Hem bu protokolleri kaynak olabilir hem de bu protokolleri hedef olarak
kullanabilirsiniz. Son olarak bu özel protokolleri NFC üzerinden
taranarak alınmış, mail içerisinde gönderilmiş, bir web sitesindeki HTML
linke tıklanarak edinilmiş, web redirectionla yönlendirilmiş de
olabilir. Hepsi de çalışacaktır.

Makaledeki örneği iki Windows Phone uygulaması olarak çalışır şekilde
indirmek isterseniz örnekler GitHub'da!

https://github.com/daronyondem/WPMakaleOrnekleri/tree/master/uri_association

Görüşmek üzere!