Uncategorized

Playing around with Microsoft Hololens

Yesterday in the morning, Alessandro  invited me to join a meetup targeting the Hololens. As the Hololens is very rare outside the US, I just needed to join the event.

When I arrived, already one of the meetup attendees was introduced to the Hololens. After some time, it was then my turn. The first “challenge” one has to take is to adjust the device on your head. The Hololens has quite some weight – it is a full PC you are wearing on your head, so not much a surprise.

After I mounted the Hololens on my head, I needed to start the calibration app. You have to adjust four corners you are seeing on the display. This is quite a challenge, but once you have it done, you’re ready to go.

GianPaolo recommended me to play level one of the space shooter game “Project X-Ray”, to get a better feeling for the device. You may probably know this from various Microsoft demos already (if not, click here). The game first scans the environment, and then you have to shot down all the alien robots that are coming out of the wall. As much fun as it is, it is challenging (at least at my age). Here is a shot of what I (and others) saw:

hololens2

After that, I tried the Galaxy Explorer app. It is amazing, you can zoom in and out of the point of interests in the 3D galaxy map, pretty much like we know already from some science-fiction movies. Here’s a shot of me in action:

hololens1

One thing needs to be clear. The Hololens does no longer interact with any object like we all are used to. It takes user interaction to a whole new level. You’ll have to learn some gestures, like the “bloom”-gesture to open the start menu. But that’s only how you control the device. We all will be able to add our own ways of interaction in our apps (that we will write one day, I bet!). I have already some ideas what I could do (well, also thanks to my kids and wife, tbh). One of them is a holographic version of my first app I ever wrote (which is a fishing knots tutorial app with animated step-by-step guide).

What about you? Do you have ideas for Hololens apps/games? Sound off in the comments, if you want to share your ideas. You can also find more info on Hololens development here on MSDN.

To close this post, I want to thank the team of IBV Solutions for this absolutely awesome opportunity. Thank you, guys!

Posted by msicc, 0 comments

[Updated] Why Windows Phone apps deserve a custom uri scheme (and how to add a simple launch uri)

app2app_Windows_Phone

Microsoft introduced custom uri schemes or uri associations in Windows Phone 8 along with the ability to launch apps based on a file type.

Sadly, this feature is not used across a broad range of apps yet. Why am I so interested in that point? I am going to explain you.

First, there is one big issue: You can share any app via NFC, and launch any app from the Store via NFC tag that has a launch app record. But you cannot launch any apps from your app – just those that have implemented a custom uri scheme. On the other two big operating systems, sharing between apps is meanwhile a standard feature used by a lot of developers.

Most of the settings pages have one of those uri schemes, for example the Wi-Fi settings page can be launched with this simple line of code:

await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings-wifi:"));

I don’t know if other developers just don’t know about this feature or if they don’t think it is necessary. I talked to a lot of users of my app NFC Toolkit for Windows Phone 8, and all asked me to add the possibility to launch a desired app at the end of my profiles (if you don’t know, my profiles launch programmable sequence of settings pages).

Searching for a solution to satisfy my user, I spent a few days with researching of all possibilities and talking to other developers. Some of them wanted use cases for adding that feature, here are three:

  • Every day I leave for work, I disable Wi-Fi, activate Bluetooth and switch the cellular connection from 2G to 3G/4G. I often use Nokia Music to listen to music while driving to work (about 45 minutes). This is one of the use cases.
  • The second scenario should be also familiar to some of you: I switch off all data connections because otherwise, my phone would ring very often during the night. In the morning, I switch them back on and check for news with a feed reader app. This would fit perfectly into a profile that I save on a NFC tag or launch via secondary tile.
  • Third one: there are a lot of blog reader apps out there. Sure, Windows Phone has social networks built in – but only Facebook (user only), Twitter and LinkedIn. What if I want to share to another network, for example Geeklist? Then I have to copy and paste instead of just hitting the share button.

There are more use cases, but I am leaving you with these three for the moment.

Back to the conversations I had with my users. They want and deserve a great user experience. This blog post is part of my efforts to provide users their deserved user experience.

Sadly, for a handful of developers it is not as easy to gain some attention for this. This is why I am trying to get DVLUP on board. By creating a challenge for this, more developers would join to earn the XP. The winners in this case are the users out there, because this way, their user experience will be improved. I know this should be done by Microsoft. In the meantime, it is up to us developers to improve. That’s why I ask you to vote for my idea case on DVLUP here: http://www.dvlup.com/Feedback?query=custom+uri+scheme+to+all+apps%21# (the first entry in the list is the one to vote).

There is one reason left why you should add a custom uri scheme to your app. This point is for you, the developer reading this article. You have a free possibility to promote your app across other apps. The most important point: it takes only 5 minutes to add a simple launch uri scheme.

Do you already have a custom uri scheme for your app? Great, then add it to this list: URI Association Schemes List – Nokia Developer Wiki. This way, other developers can use them to interact with your app and bring you new users, too.

To close this article, I want to show you how to add a simple custom uri launch scheme. I have done this with my app Mix Play & Share recently (update submitted, will add it to the list above as soon as it certified).

A simple launch uri – the code

First, open your WMAppManifest.xml by right-clicking on it and Open with… =>XML (Text) Editor.

After the </Tokens> Element, add the following code:

<Extensions>
     <Protocol Name="your-custom-uri-scheme-here" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>

Save and close the Document.

Add a new class to your project. Add the following code in your class:

    class UriSchemeMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());

            // updated code begins here:
            if (tempUri.Contains("your-custom-uri-scheme-here"))
            {
                return new Uri("/MainPage.xaml", UriKind.Relative);
            }
            //updated code ends here
            return uri;
        }
    }

To make your app using this custom uri scheme, you just have to add another line of code after the declaration of your RootFrame in App.xaml.cs:

//Handle custom uri scheme
RootFrame.UriMapper = new UriSchemeMapper();

That’s all, your app now is able to be launched by other apps!

You can also add more advanced custom uri schemes (up to 10 per app), to read more about it, check MSDN: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987(v=vs.105).aspx#BKMK_URIassociations

I hope after reading this post, you understand why I think it is important to add a custom uri scheme. With the simple code above, you’re done in 5 minutes.

Update 12/14/2013:

I needed to update the UriMapper class above, because without handling a scheme without parameters we will have no guarantee that the app launches. In my tests it works sometimes and sometimes not, but to make sure your app launches, please handle this case properly.

 

Until then, happy coding!

Posted by msicc, 9 comments

How to update a live tile in a background task with web data on Windows 8.1

scheduledtaskWindows

Like I wrote in my last post, I recently finished a PCL project with a Windows Phone and a Windows 8.1 app. Like the Windows Phone version, also the Windows 8.1 app has a live tile that fetches the same data from WordPress.

Taking advantage of our PCL solution structure, we are able to reuse the JSON data class from our PCL.

However, there are a few things that differ from the Windows Phone background agent.

First, we need to add a new project to our solution. In the new project dialog, select ‘Windows Runtime Component’ in the C# Windows Store section.

To make it a background task, implement the interface IBackgroundTask to the generated class in our Runtime component. In order to make it doing some work, we are going to add the ‘Run’-method that will start our background agent.

Here we are already with the first difference. The Windows Runtime does not support direct async Tasks of type string (I fetch all articles via HttpClient in an async task that returns the JSON string). That’s why we need to wrap it in an IAsyncOperation. To do this, add a new sealed class to your Windows Runtime background agent project.

Here is how the code for the IAyncOperation:

        public IAsyncOperation<string> GetLastPostJsonString(string url)
        {
            try
            {
                return AsyncInfo.Run((System.Threading.CancellationToken ct) => GetInternal(url));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            return null;
        }

        private static async Task<string> GetInternal(string url)
        {
            try
            {
                HttpClient getJsonStringClient = new HttpClient();
                getJsonStringClient.DefaultRequestHeaders.IfModifiedSince = DateTime.Now;

                var response = await getJsonStringClient.GetAsync(url);
                var JsonString = await response.Content.ReadAsStringAsync();
                return JsonString;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            return null;
        }

Let me explain the code. The IAsyncOperation starts and returns the string of our async Task<string>.  To achieve this, we need to start another async Run that delegates our Task<string> result to the main background task. Unlike a direct HttpClient call, we are not able to save the string directly to an string object. Instead, we need to read the stream.

I highly recommend to wrap this all in try/catch blocks to prevent any crashes of your app.

Let’s go back to our main background task class. Now we are able to fetch the JSON string from web service, we finally can start to implement the Run() method that will actually update our live tiles:

       public async void Run(IBackgroundTaskInstance taskInstance)
       {
           try
           {
               BackgroundTaskDeferral deferral = taskInstance.GetDeferral();

               PostfetcherForTileUpdate fetchJsonString = new PostfetcherForTileUpdate();

               Constants.latestPostsForLiveTileFromWordPressDotComResultString = await fetchJsonString.GetLastPostJsonString(Constants.GetLatestPostsForLiveTileFromWordPressDotComUriString);

               );

               UpdateTile();

               deferral.Complete();
           }
           catch (Exception ex)
           {
               Debug.WriteLine(ex.ToString());
           }
       }

The Run method needs to implement the Interface for IBackgroundTaskInstance. To inform the OS that our background agent may do work after the Run has returned data, we need to use the GetDeferral() method. If we would do that, it may happen that the task will be closed before all action has taken place.

After getting the JSON String from the IAsyncOperation, we can now write it to an object, call our UpdateTile() method and tell the system that our deferral is completed.

Within the UpdateTile() method, we are going to deserialize the JSON String and update our live tile. There are a lot of considerations for the live tiles in Windows 8 and 8.1, make sure you have read the guidelines for tiles and badges on MSDN. Make also sure you check the tile template catalogue to choose the right templates for your app.

Let’s have a look at the UpdateTile() code:

        private static void UpdateTile()
        {
            try
            {
                //create a new Tile updater and allow it to be added to the notification queue
                var updater = TileUpdateManager.CreateTileUpdaterForApplication();
                updater.EnableNotificationQueue(true);
                updater.Clear();

        //deserialize the JSON string
                var LatestPostFromWordpress = JsonConvert.DeserializeObject<json_data_class_Posts.Posts>(Constants.latestPostsForLiveTileFromWordPressDotComResultString);

        //fill in the Tile Templates
                foreach (var item in LatestPostFromWordpress.posts)
                {
            //supporting both Medium and Wide tiles
                    XmlDocument WidetileXML = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150PeekImage04);
                    XmlDocument SquareTileXML = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150PeekImageAndText04);

            //setting the text on our tiles
                    var title = item.title;
                    WidetileXML.GetElementsByTagName("text")[0].InnerText = title;
                    SquareTileXML.GetElementsByTagName("text")[0].InnerText = title;

            //providing the remote image source 
            //if not empty:
                    if (item.featured_image != string.Empty)
                    {
                        XmlNodeList tileImageAttributes = SquareTileXML.GetElementsByTagName("image");
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("src", item.featured_image);
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("alt", "no image");

                        XmlNodeList tileWideImageAttributes = WidetileXML.GetElementsByTagName("image");
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("src", item.featured_image);
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("alt", "no image");
                    }
            //if empty:
                    else if (item.featured_image == string.Empty)
                    {
                        XmlNodeList tileImageAttributes = WidetileXML.GetElementsByTagName("image");
            //this image has to be in the main Windows 8.1 project, not in the background task!
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("src", "ms-appx:///Images/NoImgPlaceholderMedium.png");
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("alt", "no image");

                        XmlNodeList tileWideImageAttributes = WidetileXML.GetElementsByTagName("image");
            //this image has to be in the main Windows 8.1 project, not in the background task!
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("src", "ms-appx:///Images/NoImgPlaceholderWide.png");
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("alt", "no image");
                    }

            //perform the update of our live tiles
                    updater.Update(new TileNotification(WidetileXML));
                    updater.Update(new TileNotification(SquareTileXML));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

To make the background task updating our tile, we need to use the TileUpdateManager class. As we are updating our main tile, we are using the CreateTileUpdaterForApplication() method. To make sure our tile is able to queue our update request, we are setting the EnableNotificationQueue property to true.

After deserializing the JSON string, we fill the Template by using DOM methods. I used the GetElementsByTagName(string) method to find the title and the image ChildNodes in the template. This way, I don’t need to care for the Xml structure.

The title content can be set by using the InnerText property. For providing the images source, we need to go through the NodeList, searching for the image NodeChild and use the SetAttribute() method of the XmlElement class.

With the code above, the tile gets a placeholder image, if the JSON string does not return an url for the  featured image. Important: the placeholder image has to be in your main Windows 8 project, not in the background task project. Make also sure that the image(s) have a unique name and do not use the same file name like your base tile image.

That’s all we need to do in our background task project.

Let’s have a look at our main app project. First, we have to declare our background task to make our app registering for the periodic notifications. Open the Package.appxmanifest of your app and navigate to the ‘Declarations’ tab.

Screenshot (259)

Under ‘Available Declarations’, select ‘Background Tasks’ and ‘Add’.

Screenshot (259)

 

Under ‘Description’ check the ‘Timer’ Option. Make sure you referenced your background task project and add it as ‘Entry Point’.

That’s all that wee need to set up in the first step. Now we are going to write our method to register the background task:

        //needs to be async because of the BackgroundExecutionManager
        public async void RegisterBackgroundTask()
        {
            try
            {
        // calling the BackgroundExecutionManager
        //this performs the message prompt to the user that allows the update of our tiles and the permissions entry
                var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

        //checking if we have access to set up our live tile
        if (backgroundAccessStatus == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity ||
                    backgroundAccessStatus == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity)
                {
            //unregistering our old task, if there is one                   
            foreach (var task in BackgroundTaskRegistration.AllTasks)
                    {
                        if (task.Value.Name == taskName)
                        {
                            task.Value.Unregister(true);
                        }
                    }

            //building up our new task and registering it
                    BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
                    taskBuilder.Name = taskName;
                    taskBuilder.TaskEntryPoint = taskEntryPoint;
                    taskBuilder.SetTrigger(new TimeTrigger(60, false));
                    var registration = taskBuilder.Register();
                }
            }
        //catching all exceptions that can happen
            catch (Exception ex)
            {
        //async method used, but wil be marked by VS to be executed synchronously
                var message = new MessageDialog("we were not able to activate the live tile. Please restart the application to try again.");
                message.Title = "Sorry,";
                message.ShowAsync();

            }

        }

We are calling the BackgroundExecutionManager of Windows 8.1. This adds the Permissions dialog on the app’s first run as well as the entry in the settings charm. Only if we are allowed by the user, our tile will be updated.

Unregistering already running tasks and re-adding them is a common practice, which I did also here.

After that, I build up a new background task with the BackgroundTaskBuilder class, referencing to the taskEntryPoint I set up in the Declarations tab before.

Unlike the Windows Phone background agent, we can change the time of the background task. I used 60 minutes for this app. You will need to specify a trigger (minimum of 15 minutes). I tried it without, which lead to an exception.

I am catching all exceptions and display a message to the user here. The method will be marked as executing synchronously, but it will work. The reason is that no async methods are allowed in the catch block.

Like always, I added this to my App.xaml.cs file, as this is set up application wide. To start the task, I just call it in the Application.Launched event. It would also work in the OnWindowCreated event, if you want your Launched event free.

Setting up a background task to update your live tile with data from web is not as easy as on Windows Phone, but with this article you will be able to get started on that.

As always, I hope that this post is helpful for some of you.

Happy coding, everyone!

Posted by msicc, 1 comment

How to work with the user’s music library on Windows Phone

wp_ss_20131111_0002b

I am currently exploring a lot of APIs that I never used before  in my Windows Phone apps as I am adding more features to my NFC Toolkit.

Like I always do, I create sample applications to explore what is possible and then integrate them into my main app.

One of those APIs is the MediaLibrary class on Windows Phone. You might think: there are tons of examples out there, why another post? Well, I agree, there are a lot of samples, but I want to cover a whole scenario.

In my sample, I am getting a list of all Albums stored in Library, start them playing, and display the current playing song as well as handle state managements of the playing song.

First, you will need to add the capabilities ID_CAP_MEDIALIB_AUDIO and ID_CAP_MEDIALIB_PLAYBACK to your app. If you will not do that, every call against the APIs will end up with an NotAuthorizedException.

For any access to the MediaLibrary and the MediaPlayer classes we are using the Namespace “Microsoft.Xna.Framework.Media”. Here our trouble begins already.

Xna is Microsoft’s framework to create games on Windows Phone 7.  As Windows Phone 8 supports also native code, this is mainly used in 7 games. That’s why you might run in some TargetInvocationExceptions while you debug apps that use them.

To avoid this, we need to add a Framework Dispatcher that simulates a game loop for us. Add the following method to your App.xaml.cs:

        private void StartGameLoop()
        {
            GameTimer gameTimer = new GameTimer();
            gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);

            gameTimer.Update += delegate
            {
                try
                {
                    FrameworkDispatcher.Update();
                }
                catch
                { }
            };

            gameTimer.Start();

            FrameworkDispatcher.Update();
        }

We are starting a new GameTimer and delgate it to our UI using the FrameworkDispatcher.Update() method. By adding it to App.xaml.cs and calling this method in Lauching and Activated event of our app, we have it running through our whole app and are done with this.

There are several methods to this, I found this the most easy version. I would pay credits, but don’t remember where I saw this – sorry.

Before we came to our first call against the MediaLibrary, we need to add a class for our List<T> or ObservableCollection<T>. I don’t know if this is the best practice in this case, but it made working with the List of Albums very easy for me:

        public class AlbumFromStorage
        {
            public string AlbumName {get; set;}

            public string AlbumArtist {get; set;}

            public WriteableBitmap AlbumCover {get; set;}

            public SongCollection AlbumSongs { get; set; }

        }

To use this class, just add a new List<T>/ObservableCollection<T> to the Page class. Do the same for a MediaLibrary object and an AlbumCollection object:

public ObservableCollection<AlbumFromStorage> AlbumsList = new ObservableCollection<AlbumFromStorage>();
public MediaLibrary lib = new MediaLibrary();
public AlbumCollection albumslist;

Now we are prepared for fetching all local stored albums. Add the following code to your corresponding method:

            albumslist = lib.Albums;

            if (albumslist.Count != 0)
            {
                foreach (var item in albumslist)
                {
                    AlbumsList.Add(new AlbumFromStorage()
                    {
                        AlbumArtist = item.Artist.ToString(),
                        AlbumName = item.Name,
                        AlbumCover = PictureDecoder.DecodeJpeg(item.GetThumbnail()),
                        AlbumSongs = item.Songs
                    });
                }

                MusicAlbumListBox.ItemsSource = AlbumsList;
            }
            else
            {
                await MessageBox.Show("It seems you have not stored any music on your phone.", "Sorry :(", MessageBoxButton.OK);
            }

Let me explain the code. First, we are using our AlbumCollection object to asign the MediaLibrary.Albums property. This will give us a collection of all albums. Then we need to check first, if the count in the collection is not 0 (it will throw ugly exceptions if a user doesn’t have any music stored if you won’t to this).

Then we add these albums to our ObservableCollection<AlbumFromStorage> picking the interesting properties of each album for us.

As the thumbnail for the album cover is a Stream, we need to use a WriteableBitmap for calling the GetThumbnail() method. The last step adds our ObservableCollection<AlbumFromStorage> as ItemSource to our ListBox.

This will be the result (based on my current albums list):

wp_ss_20131111_0002

Now all we need to do is to make a tapped album playing with Windows Phone’s media Player.  Add the following code to the Listbox ItemTap Event:

             if (Microsoft.Xna.Framework.Media.MediaPlayer.State != MediaState.Playing)
             {
                 //to delete the recent song (if there is any), just add this
                 MediaPlayer.Stop();

                 var selectedItem = this.MusicAlbumListBox.SelectedItem as AlbumFromStorage;

                 // play the SongCollection of the selected Album
                 MediaPlayer.Play(selectedItem.AlbumSongs);
             }
             else if (Microsoft.Xna.Framework.Media.MediaPlayer.State == MediaState.Playing)
             {
                 MessageBox.Show("You are already playing music. Please stop the music first.");

                 //your own handling could be different here, like asking the user for the desired action and perform  it then

             }

As you can see, I use the MediaPlayer.State property to get the album playing. The album is a SongCollection that holds all songs of the album. I recommend you to stop the last played song (if there is any) first with the MediaPlayer.Stop() method before start playing the first album song with the MediaPlayer.Play() method. Otherwise, it may happen that the user hears a second from the old song.

Very important: you must handle the case that the user has already music playing. If not, your app is likely to not pass certification.

After we started playing the music, we naturally want to display the current song.

To achieve this, we need to add two events to our page constructor: MediaPlayer.ActiveSongChanged and MediaPlayer.MediaStateChanged.

Within the MediaPlayer_MediaStateChanged event, add the following code:

            if (MediaPlayer.State == MediaState.Playing)
            {
                var activeSong = MediaPlayer.Queue.ActiveSong;
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTileTitleBlock.Text = string.Format("playing:\n{0}\n{1}", activeSong.Name, activeSong.Artist);

                });

            }
            else if (MediaPlayer.State == MediaState.Paused)
            {
                var activeSong = MediaPlayer.Queue.ActiveSong;
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTitleBlock.Text = string.Format("paused:\n{0}\n{1}", activeSong.Name, activeSong.Artist);                    
                });
            }
            else if (MediaPlayer.State == MediaState.Stopped)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTitleBlock.Text = "music stopped"; 
                 });
            }

This way, we use the MediaState to display the the current state as well as the title and artist. As we are updating the UI thread, as Dispatcher is used to update the Text.

To change the title and the artist of the current playing song, use this code within the MediaPlayer_ActiveSongChanged event:

            var activeSong = MediaPlayer.Queue.ActiveSong;
            Dispatcher.BeginInvoke(() =>
            {
                MusicTileTitleBlock.Text = string.Format("{0}\n{1}", activeSong.Name, activeSong.Artist);

            });

If you want to display also the album image, you will need to cache the image from the ItemTap event before, which would work fine with albums. If you choose Playlists instead of Albums, this will not work out well as you will not be able to get the image from MediaPlayer.Queue.ActiveSong.

I did a lot of research to get this feature(s) working the way they should. I took me several hours to figure everything out exactly, and I hope this post helps some of you out there to save some time on this.

With this post, you will be able to generate the whole experience your users deserve from the beginning to the end.

Until the next post, happy coding!

Posted by msicc, 1 comment

The very weird way of checking if Bluetooth or Location is enabled

BT_GPS_WP_Blog

As I am in constant development of new features for my NFC Toolkit, I came to the point where I needed to detect if Bluetooth and Location is enabled or not.

I searched about an hour across the internet, searched all well known WPDev sites as well as the MSDN Windows Phone documentation.

The solution is a very weird one.

As I change the opacitiy of an Image depending on the stauts (on/off), I created the following async Task to check:

private async Task GetBluetoothState()
 {
 PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";

            try
 {
 var peers = await PeerFinder.FindAllPeersAsync();

                Dispatcher.BeginInvoke(() =>
 {
 BluetoothTileImage.Opacity = 1;
 });
 }
 catch (Exception ex)
 {
 if ((uint)ex.HResult == 0x8007048F)
 {
 Dispatcher.BeginInvoke(() =>
 {
 BluetoothTileImage.Opacity = 0.5;
 });
 }
 }
 }

As you can see above, we are searching for already paired devices with the Proximity API of Windows Phone. If we don’t have any of our already paired devices reachable, and we don’t throw an exception with the HResult of “0x8007048F”, Bluetooth is on. If the exception is raised, Bluetooth is off.

In a very similar way we need to check if the location setting is on:

private async Task GetLocationServicesState()
 {
 Geolocator geolocator = new Geolocator();

try
 {
 Geoposition geoposition = await geolocator.GetGeopositionAsync(
 maximumAge: TimeSpan.FromMinutes(5),
 timeout: TimeSpan.FromSeconds(10)
 );

Dispatcher.BeginInvoke(() =>
 {
 LocationStatusTileImage.Opacity = 1;
 });

}
 catch (Exception ex)
 {
 if ((uint)ex.HResult == 0x80004004)
 {
 Dispatcher.BeginInvoke(() =>
 {
 LocationStatusTileImage.Opacity = 0.5;
 });
 }
 else
 {
 //tbd.
 }

}
}

For the location services, the HResult is “0x80004004”. We are trying to get the actual GeoLocation, and if the exception is thrown, location setting is off.

On Twitter, I got for the later one also another suggestion to detect if the location settings is enabled or not, by Kunal Chowdhury (=>follow him!):

geoLocator.LocationStatus == PositionStatus.Disabled;

This would work technically, but PositionStatus has 6 enumarations. Also, as stated here in the Nokia Developer Wiki, this can be a battery intese call (depends on the implementation). I leave it to you which one you want to use.

Back to the header of this post. Catching an exception to determine the Status of wireless connections just seems wrong to me. I know this is a working “solution” and we can use that. But it could have been better implemented (for example like the networking API).

I hope this post is helpful for some of you.

Until then, happy coding!

Posted by msicc, 0 comments