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!