Archives For Uncategorized

Looking for #WPDev opinions

October 2, 2014

In October, I’m interested in getting thoughts and opinions from the Windows platform development community in my ~annual pulse of the Windows developer community. This year’s survey focuses in on asking less about what you’re doing, and more on why you’re doing what you’re doing. This information will be used by my team to adjust where we spend our focus in the next 3-18 months.

To participate, head over and complete the survey here.

Every year, my team looks to gather information from our mobile developer community about what is working and what isn’t for you. We use this information in a few ways:

  1. Provides longitudinal progress and quantitative measurement (obvious item)
  2. Informs what is top of mind for developers, and where the team should spend our dev readiness and marketing dollars to provide additional guidance/code samples/etc
  3. Informs our conversations with engineering on what we need to try to solve in the platform

As part of my job, I do a lot of research, both at small scale (i.e., focus groups, call downs, design reviews, etc.) and at large scale (e.g., our VisionMobile partnership). This is one of those surveys that have a direct impact on what is built for you, and what comes out of Redmond starting next month (rather than engineering investments that can take many months/quarters to get out into the market).

Last year, we received almost 400 responses. If you can help us get over 500 responses, I can commit to publishing out a survey here by the end of the 2014.

Looking back at the Spring 2013 survey

Last year (2013), I ran a version of a survey in two places: first in one of our Spring 2013 newsletters (and via Twitter), as then as a survey sent out to Build 2013 attendees (I was recruiting for a few research groups we ran on-site).

The goal for the Spring 2013 survey was different than this month’s survey. The 2013 survey had a much stronger drive to asking questions around publication bridges and barriers, and personal drivers to why folks were building mobile apps. Most of this information was used to help inform some of our work that landed at Build 2014 (the keynote story, the Build floor, the //publish/ event structure, etc.). So if you participated in the 2014 survey – we appreciate your assistance in helping us craft our story! Smile I also learned a lot about how to better phrase and ask about development practices based on this survey.

One of the largest reasons I didn’t do a report out on this data was because there are a number of holes in the way I asked questions. I used this learning in a number of studies we ran last year…which is a long way of saying I know there are problems with some of the data groupings below (and here’s where I point out that my background is in computer science, and not in research). As you’ll notice as you take this month’s survey, it’s gotten a lot better. Smile

image

Looking at the devs responding, the responses primarily came from developers publishing into to the Store, but there were also a number of hobbyists and moonlighters building for the platform.

This also showed up in he monetization strategies used by those who have published up to the store – 48% of the responses showed no in-store monetization intended from the apps.

image

Returning to my point about key learnings since fielding this DIY survey, the ‘no monetization’ option is easy to misread. What is missing from this question is the reflection that a number of publishers don’t monetize their apps directly – the group that we refer to as ‘brand extenders’. For the brand extender, mobile is not their primary monetization channel (but it may be a important part). In surveys following this one, the ‘I don’t monetize my app in the store’ option has grown into a few different options.

And you also told us that you felt pretty strongly around the languages that you used – the majority of folks use (and love XAML + C#), with a smattering of WinJS usage. This has been an important data point that we’ve used to guide our readiness investments and tone over the past year.

image

As you can see above, there was definitely an HTML contingent, but the representation was much smaller than the .NET faithful. Similarly, I believe the .NET usage also played as a factor into why Windows Phone was selected as a platform, with many folks saying that the primary driver in selecting Windows Phone as a target platform tended to group around the docs and platform familiarity.

image

The platform selection piece jives pretty well with the developer segmentation work that VisionMobile published last year, and also tends to play into the strengths of the platform – after all, Microsoft has always been a developer-centric company – from tooling to docs, Microsoft has set the bar for dev productivity for some time. What was nice to see with this survey is the growth of the user segment citing revenue as a selection driver, as well as rising satisfaction levels with the revenue they are making on the platform.

Lastly, I had a few questions for those who hadn’t yet published into the Store yet; and while skill development was very strong with the survey responses, intent to monetize was much stronger this year than in the prior year. In prior years, data tended to weigh much stronger towards skill development and personal apps (not for publishing).

image

And unpublished developers reported that there weren’t many blockers for getting their apps into the store – most reported that the app is still in development and on the way. In the two prior years, the largest blocker tended to be not having a good idea or inability to run the emulator.

image

 

At any rate, I’m looking forward to hearing more from the community this month with the survey. As I’ve said on Twitter, feel free to be verbose. I read everything you send and share it up and around the group.

So…one last appeal…go fill it out! Smile

Best regards,
Cliff

As I started working with SQLite as a place to store my data, I began thinking about my app’s changing data scheme and I wondered: ‘how do I handle change management in my local database?’ This blog entry outlines my approach to solving this issue, which basically boils down to tracking the data scheme version in the database and doing a wholesale drop and recreate when the schema changes.

Why drop and recreate?

For my app, I use SQLite for data caching of server-side information – providing performance and offline capabilities for the user. Prior to using SQLite, I had been using in-memory serialization to store the object collections in isolated storage, which had a number of performance issues (memory and CPU).

For non-cached user information (account information, preferences, etc.), I don’t use SQLite – I store those items in the isolated storage property bag. As I take my app to the Windows Runtime platform, I’ll bring this information into the roaming data area (for preference information) and credentials locker (for account information).

For the cached app data, I’m now storing this as a SQLite database. My issue is that each version sees continued improvement around the richness of the data (adding review information from a variety of sites, news entries, etc.) – which means scheme modifications. Many of the websites describing using SQLite talk about how to create the database, but leave it to the user to figure out database updates. I played around DDL tracking with complicated UPDATE scripts and decided this was taking way too long for basically volatile cache data…and I went with a simpler approach – ship the app with a current snapshot of the full cache (~7mb) and simply do a drop and recreate each time the schema changes.

Tracking Database schema state

To track the state of the database, I created a class called DBMetadata that I can use for a variety of things in my app, including the schema version (what we’re explaining here), and things like the last time I retrieved a particular dataset (to help balance data pulls that don’t need to be run every time the app runs). The class looks like the following:

[Table("Metadata")]
public class DbMetadata {

  [PrimaryKey, AutoIncrement]
  public int Id { get; set; }

  public string SettingName { get; set; }

  public int SettingValueMajor { get; set; }

  public int SettingValueMinor { get; set; }

  public string SettingInt { get; set; }

  public string SettingString { get; set; }

  public DateTime SettingDateTime { get; set; }

}

 

To track the database schema version, I use constants in my LocalData class like the following:

const string DBMETA_SCHEMA_VERSION_NAME = "DbSchemaVersion";
const int DBMETA_SCHEMA_VERSION_MAJOR = 1;
const int DBMETA_SCHEMA_VERSION_MINOR = 2;

 

With this code in place, I have the following two methods in my LocalData class to interact and check if the database is running the most current:

private async static Task<bool> ValidateIsLatestDbVersion() {

  try {

    int _table = await LocalData.DbConnection.ExecuteScalarAsync<Int32>("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='Metadata';");

    if (_table == 0) return false; 

    if ((await LocalData.DbConnection.Table<DbMetadata>().Where(t => t.SettingName == DBMETA_SCHEMA_VERSION_NAME).CountAsync()) > 0) {
      var _ret = await LocalData.DbConnection.Table<DbMetadata>().Where(t => t.SettingName == DBMETA_SCHEMA_VERSION_NAME).FirstAsync();

      if (_ret != null && _ret.SettingValueMajor > DBMETA_SCHEMA_VERSION_MAJOR) {
        return true;
      } else if (_ret.SettingValueMajor == DBMETA_SCHEMA_VERSION_MAJOR && _ret.SettingValueMinor >= DBMETA_SCHEMA_VERSION_MINOR) {
        return true;
      } 
    }
  } catch (Exception _e) {
  }

  return false;
}


private async static Task<bool> MarkDbVersion() {

  try {
    if ((await LocalData.DbConnection.Table<DbMetadata>().Where(t => t.SettingName == DBMETA_SCHEMA_VERSION_NAME).CountAsync()) > 0) {
      var _ret = await LocalData.DbConnection.Table<DbMetadata>().Where(t => t.SettingName == DBMETA_SCHEMA_VERSION_NAME).FirstAsync();
      _ret.SettingValueMajor = DBMETA_SCHEMA_VERSION_MAJOR;
      _ret.SettingValueMinor = DBMETA_SCHEMA_VERSION_MINOR;
      await LocalData.DbConnection.UpdateAsync(_ret);
    } else {
      await LocalData.DbConnection.InsertAsync(new DbMetadata() { SettingName = DBMETA_SCHEMA_VERSION_NAME, SettingValueMajor = DBMETA_SCHEMA_VERSION_MAJOR, SettingValueMinor = DBMETA_SCHEMA_VERSION_MINOR });
    }
    return true;
  } catch (Exception _e) {
    return false;
  }
}

 

With the above in place, it’s pretty easy to now handle the check and drop, as needed.

Open/Create/Delete

So now with the plumbing in place, it’s time to put in place the business logic that does the database creation. I do this when I open the database for the first time in my Windows Phone app.

private async static Task OpenLegoDB() {

  string DBPATH = System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, DBNAME_LEGO_SETS);
  try {
    await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME_LEGO_SETS);
    _legoDbConnection = new SQLiteAsyncConnection(DBPATH);

    //Check the schema version, and replace the database if it's an old one
    if (!await ValidateIsLatestDbVersion()) {
      _legoDbConnection = null;
      await LocalData.DeleteLegoDB();
    }

  } catch (FileNotFoundException) {
  } catch (SQLiteException) {
    _legoDbConnection = null;
  }
  if (_legoDbConnection == null) {
    await LocalData.CreateLegoDB();
    _legoDbConnection = new SQLiteAsyncConnection(DBPATH);
  }
}


private async static Task DeleteLegoDB() {
  string DBPATH = System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, DBNAME_LEGO_SETS);
  try {
    var _file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME_LEGO_SETS);

    SQLite.SQLiteConnectionPool.Shared.Reset();
    await _file.DeleteAsync();
  } catch (FileNotFoundException) {
  }

}


private async static Task CreateLegoDB() {
  try {

    string DBPATH = System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, DBNAME_LEGO_SETS);

#if DEBUG
    _legoDbConnection = new SQLiteAsyncConnection(DBPATH);
    await _legoDbConnection.CreateTableAsync<LegoTheme>();
    await _legoDbConnection.CreateTableAsync<LegoSubtheme>();
    await _legoDbConnection.CreateTableAsync<LegoSet>();

    await _legoDbConnection.CreateTableAsync<DbMetadata>();
    await LocalData.MarkDbVersion();
    return;
#endif


    StorageFile dbFile = null;
    try {
      dbFile = await StorageFile.GetFileFromPathAsync(DBPATH);
    } catch (FileNotFoundException) {
      if (dbFile == null) {
        // Copy file from installation folder to local folder.
        IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();

        // Create a stream for the file in the installation folder.
        using (Stream input = System.Windows.Application.GetResourceStream(new Uri("Assets\\LegoSets.Snapshot.sqlite", UriKind.Relative)).Stream) {
          // Create a stream for the new file in the local folder.
          using (IsolatedStorageFileStream output = iso.CreateFile(DBPATH)) {
            // Initialize the buffer.
            byte[] readBuffer = new byte[4096];
            int bytesRead = -1;

            // Copy the file from the installation folder to the local folder. 
            while ((bytesRead = input.Read(readBuffer, 0, readBuffer.Length)) > 0) {
              output.Write(readBuffer, 0, bytesRead);
            }
          }
        }
      }
    }

  } catch (Exception _e) {
    return;
  }
}

 

There’s a bunch of cool stuff happening in the code above (the delete step alone took me a few hours on StackOverflow to get right). But the basic logic here is as follows:

  1. Open the database file
  2. If the file is there, check the version number
    1. Validate that the settings table exists (that we have a version number to check Smile)
    2. If the database is the same or newer version, then all is good!
    3. If the database has an old version, delete the file and clear the variable
  3. If we have an open database file, proceed; if we don’t, then create a new one
    1. If we’re running in DEBUG, then create the file and the tables from scratch
    2. If we’re not running in DEBUG, then use the snapshot that shipped with the app

Note that the above applies to an app written for Windows Phone Silverlight. When I do bring this over to the Windows Runtime platform (targeting Windows client, as well as phone), I will likely add some #IF checks to handle where the files are located and the like. But that’s for a future consideration (I have a tablet version of my code, but put it on hold while I get the SQLite and Amazon integration done).

Hope that helps

That about does it for how I manage my SQLite database in my app; I hope this helps!

There are a variety of other things that I’ve adopted over time based on this strategy that may be worth noting (e.g., breaking my SQLite DB into a few different databases to enable part of the cache to be cleared without clearing all of a user’s past traffic). Also, I’m in the process of wiring this up with the Bing Translator, which also warrants a blog post in the coming months.

wp_ss_20140418_0001One of the common questions I’ve been getting over the past week from folks has been how to take advantage of this semi-obscure ‘Project my Screen’ entry that was added to the settings collection with Windows Phone 8.1.

This entry is enabled in one of two ways: by using Miracast capabilities delivered in 8.1, and by using the Project my Screen app on a PC and connecting your phone to your PC using a USB cable (sorry – no WiFi yet).

I believe the ‘Project my Screen’ application has been one of the more eagerly awaited features by developers and technical enthusiasts alike. Since we launched Windows Phone 7.0, I’ve received at least a 2-3 mails/questions a month on how they can do demos like Microsoft presenters. With this enabled, anyone can fire up their phone and project a demo of their app or their phone. So, let me lay out how you can demo your app and phone. Smile

Project my Screen requirements
The application is a desktop/x86 application (not a Windows Store app), and should run on Windows 7 and later. And, talking to the team, there is currently no plan to expand this to a Store app, nor is there a plan to enable this to connect to a television or non-PCs. A lot of this stems from the core purpose of this viewing application is to enable demos. The use case for televisions and other device types will come along with Miracast support (I don’t have any details on this, but I will post more on this as I get more information).

How to install it
To make use of the Project my Screen app, you need to do the following:

  1. Download and install the Project My Screen app from the Microsoft Download Center
  2. Start up the application using the ‘Project my Screen’ shortcut on the desktop or program list. This will start up a full-screen – click <ESC> to get that puppy to window down
  3. Connect your phone to your computer using a data-transfer quality USB cable
  4. You should get a prompt for permission to allow screen projection, click ‘yes’
    wp_ss_20140418_0002
  5. At this point, your phone screen should show up (similar to below)

4-18-2014 2-09-47 PM

 

Command cheat sheet

There is a limited number of commands available in the application to control the demo experience. The table below summarizes the commands available to you (you can get this list in app by hitting F1):

Action/Command Key
View the help screen <F1>
Quit to windowed mode <ESC>
Toggle background image on/off B
Toggle the expanded screen mode E
Toggle full-screen mode F or <Alt>+<Enter>
Toggle the phone shell image P
Toggle visibility of ‘touch dots’ T
Display the current [desktop] frame rate R
Force orientation to landscape left Left arrow key
Force orientation to landscape right Right arrow key
Force orientation to portrait up Up arrow key
Force orientation to portrait down Down arrow key
Reset orientation to match phone <spacebar>

…if your screen won’t project…

4-18-2014 2-27-16 PM

If you don’t get a prompt on your phone and the Project my Screen app remains blank/black, you may have some old phone drivers hanging around. To get rid of them, head over to your machine’s device manager (my preferred way of getting there on Windows 8.1 is to secondary-mouse-click on the Start button and select ‘Device Manager’ from the pop-up menu).

Once in the Windows Device Manager, you’ll want to remove + uninstall the drivers related to your device. When removing these drivers, it’s important that you get them all – not only the actual device itself, but the related USB device drivers.

To do this, do the following steps, keeping the plugged in:

  1. Right-click on each driver you want to delete and select ‘uninstall’
  2. A dialog will pop up asking you to confirm uninstallation. If you also have the option to delete/remove the drivers, select that
  3. Once they’ve all been uninstalled, unplug and replug in your phone back in and Windows should take care of the driver magic
  4. You should also now get the screen projection prompt shown above

4-18-2014 2-29-46 PM

 

Happy projecting!
Cliff

We went and did some more biking on the SVT this past weekend – much of the same trail as the weekend before.

We started at the same place, the Duvall trail-head, and biked a few miles past the 124th St traffic circle. Alas, we didn’t get down to the blackberry bushes this time – it would have been a few more miles, and we started late in the evening (we got caught in other household chores and got started much later than originally expected). But it was a fun time.

As part of the biking trip, we had to stop by the bike shop and pick up some new items – which includes a full-scale bike pump (the hand-pump only gets you so far), a tire repair kit, and a cheap speedometer. We used the bike pump right there at the trail, which it paid for itself in that one afternoon – IMHO, and I need to add the other two accessories to the bike this upcoming weekend as we prep for the hardwood installers to come and visit next week.

I will be hitting the trail again this weekend with Peter (and a few other coworkers). We’ll be starting a bit further down the trail this time – probably starting in Carnation, WA – and trying to see exactly how far down the trail we can get. My personal hope is to get down to the Snoqualmie Falls, if not the end of the trail, but we’ll see where we end up.