Tuesday, March 29, 2011

The marketplace needs a higher quality bar for screenshots!

I know nothing's perfect and I know the Marketplace team are doing a great job of a difficult task. It just seems like more should be done to

From the Windows Phone 7 Application Certification Requirements (section 4.6).
"Screenshots must only contain application graphics, and must not include any emulator chrome."

But then there are these: (images linked directly from the marketplace.)


These screenshots show a combination of browser chrome and developer frame rate (performance) counters.

Yes, I've seen lots more examples.
No, I don't think it reflects well on the Marketplace as a whole. :(

What would I like to see?
4.6 being more rigorously enforced.
and a new clause being added to the certification requirements that screenshots don't include performance counters.
Is that too much to ask for?

Saturday, March 26, 2011

TombstoneHelper now in NuGet

My new Windows Phone 7 library for helping with tombstoning (http://tombstonehelper.codeplex.com/) is now available via NuGet.


Also at http://www.nuget.org/List/Packages/WP7TombstoneHelper

Please use, and suggest improvements.

Friday, March 25, 2011

Tombstoning = A Top Tweet


I thought a "Top Tweet" was something only celebrities got.

Seems tombstoning is a popular subject. Check out http://tombstonehelper.codeplex.com/ and let me know if it's helpful or you have any questions on using it.

If you want to see more on handling it, also check out this post by Peter Torr.

Thursday, March 24, 2011

Making tombstoning easier [#wp7dev]

Sometimes tombstoning can be tricky.
Often it takes a lot of boilerplate code.

Things just got much easier.

Now all it takes is 2 lines of code:
    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);

        this.SaveState();  // <- first line
    }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        this.RestoreState();  // <- second line
    }
Get all the tombstone helper goodness from http://tombstonehelper.codeplex.com/ Already got some tombstoning support in your app but not handling the scrollviewer scroll position? Just do this:
this.SaveState(typeof(ScrollViewer));
Head on over to codeplex: http://tombstonehelper.codeplex.com/ for more details and please be sure to let me know what you think.

Wednesday, March 16, 2011

Binding to static classes in Windows Phone 7

It's a common request to be able to bind to a global variable in various parts of an application. It's often common that such variables are static.
This question seems to pop up in forums rather regularly and often the advice given is that this isn't possible or to include the "global" variable as part of the model being used as the DataContext of the page. Such duplication of functionality in the model is a bad idea and totally unnecessary.

It's not possible to bind to a static class as binding requires an object instance.
You can, however, bind to static properties of a class.

So we can bind to the static properties of the following.

namespace StaticBinding
{
  public class MyStaticClass
  {
    private static string myStaticProperty = "my static text";

    public static string MyStaticProperty
    {
      get { return myStaticProperty; }
      set { myStaticProperty = value; }
    }
  }
}

We can then create an application level resource which we can actually bind to:

.. xmlns:myns="clr-namespace:StaticBinding"


  

(Sorry, don't know why the syntax highlighter has forced upper case - I'm sure you're smart enough to work out what should and shouldn't be upper case though. ;)

With the above configured we can then bind to our global property in any page we wish. We just need to set the `Source` and `Path` of the binding.

..


.. 

A nice upside of this is that you even get intellisense on the `Path`. (Assuming you've set the `Source` first.)



X-Ref: http://stackoverflow.com/questions/5323052/data-binding-a-string-variable-of-static-class-to-textblock-in-phone-7/5325257#5325257

Thursday, March 10, 2011

Gotchas when forcing the theme colour in a Windows Phone 7 app

Windows Phone 7 support two background themes: light and dark.

When combined with the accent colour, this allow the user a level of customization and personalization of their device and the applications they use.

As a general rule it's good to allow your application to reflect the theme and accent colout the user has selected. Sometimes, however, you may want to "force" the theme of the app. This means that regardless of the them the user selects the application always looks the same.

Look at these two versions of the same app:
The image on the left was taken with the dark them selected and the one on the right with the light theme.
It looks like all is fine.

However, if we want to support the inclusion of the `SystemTray`, so that the user can see the time, battery level, network conection status, etc. then the system theme colour will show through and there's nothing you can do about it. Apart from not include the SystemTray, of course.

If you want to use a MessageBox in your application then you'l have a similar issue. This is what the default MessageBox looks like when a light theme is selected but a dark theme is forced.

The solution is to make your own version of a MessageBox.

Creating your own version of a message box is relatively simple. Creating your own SIP/Keyboard is a lot more complicated if you want to recreate all the functionality of the built in one.
My advice, don't force the theme unless you have a REALLY good reason and have the time and patience to deal with all the consequences.

Wednesday, March 09, 2011

#WP7Dev app feedback #6

Here's the feedback I recently gave to the creator of an app.

This is part of my series of app reviews.

In summary, I said it was "a nice app which is well executed".

Here's the feedback:

  • It would be nice if the main screen would remember the selected panorama item after being tombstoned.
  • When viewing items and swiping from side to side, there's no indicator of when the end of the list of items has been reached.
  • When viewing an item, tapping it to return to the main menu was, initially, unexpected and caused me to accidentally navigate backwards several times. Especially/even when scrolling down.
  • If viewing the item summaries for a single category, it's not clear what I'm navigating between when I swipe from side to side.
  • If viewing an item and the app is tombstoned, I would expect the app to display that item again when I navigate back to it.
  • If only one category is configured, on the first panorama item, is it necessary to have the "all items" option as well as the category.
  • In trial mode, it's possible to view articles of featured items, but not other items. This inconsistency was surprising.
  • When adding a new feed it would be good to also add this to a new category, not just select from existing ones.
  • When adding/editing a feed, is a cancel option really necessary? Can you not just rely on the back button to perform a cancel action?
  • When adding a category the entered text is required to be at least 2 characters long. This includes spaces. This means that it's possible to create categories made just of spaces.
  • The detecting of duplicate category names also doesn't include spaces at the start or end of the entered text which means that duplicates can, seemingly, appear to be created.
  • When a featured item is selected but the main progress bar is still being displayed, this appears over the top of the popup.
  • When a featured item is marked as read from the popup all featured items are reanimated. This takes time and makes the app seem unresponsive and means it's hard to quickly view multiple featured items and mark them read at the same time.
  • In the email created from the about screen, you may want to include the version number of the application. This will likely be helpful to you when investigating any reported error or problem. (Especially if someone is reporting a bug you think is fixed.)

Tuesday, March 08, 2011

#WP7Dev app feedback #5

Here's the feedback I recently gave to the creator of an app.

This is part of my series of app reviews.

In summary, I said it was "a simple, well executed app".

Here's the feedback:

  • On the main/menu page I would disable scrolling of the options/list as everything fits on the screen without needing to scroll.
  • When searching the word list it would be good to indicate when no words match the entered text. This is generally preferable to just leaving a blank screen as it makes it clear that there are no results to display.
  • Add tombstoning support to the search function so that on returning to the application it looks as it did when the user navigated away.
  • When using the next and previous buttons to navigate, I would recommend either making the list wrap around (so that selecting previous from the first item goes to the last item-and vice versa) or disable the previous button when on the first word and the next button when on the last word.
  • In the list, there is uneven capitalization of the first words in sentences.
  • In the list, most (but not all) of the sentences that span multiple lines appear to have a space before the first word. This creates an inconsistent left margin.
  • In the "XXXXX" display, the list is very long and may benefit from using a "long list selector" as in other places in the app.
  • In the "Test Yourself" mode, the page title says "test #N of 20" but it's really it's "question" number N, not "test" number N. I'd recommend changing the text to just be "N of 20".
  • In the "Test Yourself" mode, restrict the clickable space between options to prevent the chances of accidentally selecting an option other than the one intended. With this change it would be possible to remove the need to confirm (apply) the selected option. I find the confirmation step a bit frustrating.
  • If I back out of a test I am prompted to confirm that I wish to make this action as my progress will be lost but if I go back into this option my position in the test is remembered.
  • When the results of the test are displayed there is no clear indication of what the user should do next. How about adding options to try another test or returning to the main menu? I know that the back button can be used to return to the main menu and it's normally a bad idea to duplicate the number of ways you can perform the same navigation but there is currently a dead end. Adding instructions to the page to use the back button to navigate back to the main menu would take up more space and take longer to read than tappable text to do the navigation directly.
  • On the about screen, I would recommend increasing the tappable area around the URL for your website so that it is easier to tap.

Monday, March 07, 2011

#WP7Dev app feedback #4

Here's the feedback I recently gave to the creator of an app.

This is part of my series of app reviews.

In summary, I said it was "a lovely simple app which is well executed. It has impressive performance in terms of the speed of loading remote data."

Here's the feedback:
  • In the Marketplace description, some names are not capitalized correctly.
  • The highlight effect you have applied to the application icon is similar to the effect automatically applied to most iPhone apps. I would recommend removing this highlighting from the icon image so the app looks like it belongs on the platform.
  • I like the splash screen image but the logo it displays doesn't seem to match the branding of the rest of the app (apart from the color).
  • While I like the color you have used in the app I wonder if it's everyone's favourite. Have you considered using the phone accent color for this? It may help the user gain a greater sense of ownership of, affinity for and connection with the app.
  • Add tombstoning support to remember the selected pivot item and scroll position in that item.
  • There is no need to include the same options in both the application bar and the application menu.
  • I would recommend only including the "reload" option on the application bar. I would expect that this would be a frequently used option and having it always available will be helpful. Having it in the application menu makes it harder to access as it requires an extra tap and therefore takes slightly longer.
  • I would expect that the settings would be rarely accessed and so access to this functionality should be moved to the application menu so it doesn't distract or get pressed accidentally.
  • The convention for pivot item headers is for them to be entirely lower case. You should adjust "About" and "Settings" accordingly.
  • Add tombstoning support to remember which of the "About" or "Settings" pivot items were displayed when returning to the app. Remembering scroll position would also be good too.
  • The Settings screen has application bar items which are duplicated in the application bar menu. There is no need for this duplication.
  • On the setting screen there should be no need to have a cancel button which just closes the current page/navigates backwards. The back button on the phone does this already.
  • On the setting screen there is no need to have a Save button as the selected options are automatically remembered applied.
  • The entire application bar can therefore be entirely removed from the settings screen.
  • The about screen also has an application bar with save and cancel options but these don't relate to anything on screen.
  • On the about screen I would recommend making the email address stand out more to make it more obvious that it can be tapped to trigger sending an email. Colouring the email address with the phone accent color and increasing it's size would be my recommendation.
  • In the email created from the about screen, you may want to include the version number of the application. This will likely be helpful to you when investigating any reported error or problem.

Thursday, March 03, 2011

Still not got the pre-update? Fake it!

<justforfun>
You've sat quietly by as the rest of the world seems to be going on about the first Windows Phone 7 update (the pre-update) but have yet to have your device let you know that the update is available to you.



Well, if you want to get a feel for what it'll be like when that moment does finally come, you just need a simple bit of code:

Guide.BeginShowMessageBox("An update is available.",
                          "Updates can make your phone work better and add new features. They can make your phone more secure too.\r\n\r\nTo learn more and install this update, connect your phone to your computer.",
                          new []{"close"},
                          0,
                          MessageBoxIcon.None,
                          null,
                          null);

</justforfun>

Wednesday, March 02, 2011

WP7Clipboard - A clipboard API for #wp7dev

Background
  • Windows Phone 7 doesn't have an API for a Clipboard. (Actually, in the current version it doesn't even include a clipboard. - But, the ability to cut, copy and paste text will be added in the update coming later this month.)
  • I wrote an app, back in December 2010 (see video and please comment at http://www.wp7comp.com/scratch-pad/trackback/), that enables the cutting, copying and pasting of text and even sharing it between multiple applications. (Some people have the idea that you can't share data between apps on the device but I proved this isn't the case. Check the video or get it from the Marketplace to see/confirm that it doesn't use any unrestricted APIs or use a web service for storing/sharing the data.)
Short version
Head over to http://wp7clipboard.codeplex.com/ and get the code to see how I did this and use the library in your own applications.

Longer version
Constraints are good. They focus the mind and can provide structure where chaos can sometimes reign.
By their nature, mobile devices are very constrained. Many of these constraints are passed to (forced upon?) the applications that run on the devices.

Windows Phone 7 development has some potentially limiting constraints in this area:
  • No cut and paste support (currently)
  • No clipboard
  • No shared file system

There are 2 ways we can react to constraints:

  1. We can complain about them.
or
  1. We can work with them.

I opt for the later.
I knew there had to be a way to do this! Just because it seemed that everyone and their dog was complaining about a "lack of copy and paste" wasn't going to stop me.

"Cut and paste" is really only about copying and manipulating objects (strings in this case) in memory. Just because there isn't a UI for this doesn't mean we can't do it. We just need to build a UI.

Just because the platform doesn't provide a clipboard (functionality to store objects in persistent memory and make them available to all apps) doesn't mean we can't create the functionality ourselves. But this is where the fun begins...

All Silverlight based apps run inside a sandbox and can only create files inside "IsolatedStorage". There's no shared storage facility.

Rather than focus on what we don't have, let's think about what we can do.
Well, even in a Silverlight app we can use some of the XNA libraries.
Through the XNA APIs we can create and read images in the Pictures hub. (We can't delete them but we'll just have to live with that.)
After a little experimentation I discovered that the API will only allow us to save a valid JPEG file in to the pictures hub.
Never mind, there are ways of hiding information within pictures.
I had another idea in mind though. Due to something I worked on a long time ago, I know that the JPEG file format includes an end of file marker. I also know that almost all implementations of code to read JPEG format files ignores everything after the end of file marker. A quick check later and I verified that this is the case on WP7 too.

Yes, that's the secret, I include the data I wish to store in the "clipboard" inside a JPEG image file (the clipboard images littered through this post) after the end of file marker. Then, when I want to read from the "clipboard" I just get the most recent file from the users MediaLibrary and retrieve the extra data from the end of the file.

AFAIK only one person managed to correctly guess what I'd done.



Now you can do this in your apps too. I've encapsulated the functionality from ScratchPad into a separate library and made it open source at http://wp7clipboard.codeplex.com/
Originally this only supported text but I've started to add some functionality for processing (cutting and pasting) images too. It's still a beta but hopefuly some of you will find it useful, helpful or interesting.




A word of warning. Using this method creates files on the users phone which you can't programmtically delete. After sustained use, this will clutter up the users "saved pictures" folder and they will have to manually delete the files there. If you use this library/technique you may want to warn your users about this and give them the option to disable the functionality.

If possible I'd recommend sharing data between apps by synchronising it to a web based system. Connectivity issues aside that will probably make working with large amounts of data easier and provide backup/redundancy options.



I'd love any feedback you have on this.

Tuesday, March 01, 2011

How ScratchPad does copy and paste ... [#wp7dev]

In response to public demand I'm going to explain how I got Scratch Pad (my Windows Phone 7 app which supports cut 'n' paste and a shared clipboard API) to work.

This is the first of 2 posts on the subject. In this post I'm going to explain how I manipulate the text to create cut and paste within the app. In the next I'll show how I created a shared clipboard. And how you can add the functionality to your own apps too!

The cutting, copying and pasting of text within an app is simple really. It basically involves storing a copy of the text in question in a string variable within the code.

private string localClipboard;

To be able to select more than a single word, the code supports a "shift" mode:

private bool shiftSelected;

private int shiftSelectPositionStart;

private int shiftSelectPositionLength;

private void ShiftClick(object sender, EventArgs e)
{
    shiftSelected = !shiftSelected;

    shiftSelectPositionStart = tb.SelectionStart;
    shiftSelectPositionLength = tb.SelectionLength;
}

Which can be combined with a SelectionChanged event on the text to capture the larger string. (Being sure to consider if the new selection point is before or after the original/previous selection.)

private void SelectionChanged(object sender, RoutedEventArgs e)
{
    var currentStart = tb.SelectionStart;
    var currentLength = tb.SelectionLength;

    if (shiftSelected)
    {
        if (shiftSelectPositionStart < currentStart)
        {
            tb.SelectionStart = shiftSelectPositionStart;
            tb.SelectionLength = currentStart - shiftSelectPositionStart + currentLength;
        }
        else
        {
            tb.SelectionStart = currentStart;
            tb.SelectionLength = shiftSelectPositionStart - currentStart + shiftSelectPositionLength;
        }
    }

    shiftSelected = false;
}
Copying text is easy:
private void CopyClick(object sender, EventArgs e)
{
    this.localClipboard = tb.SelectedText;
}
But cutting text is slightly more complicated as we need to replace the original string with the text before and after the selection.
private void CutClick(object sender, EventArgs e)
{
    this.localClipboard = tb.SelectedText;

    var removeAt = tb.SelectionStart;

    var afterCut = tb.Text.Substring(removeAt + tb.SelectionLength);

    var beforeCut = tb.Text.Substring(0, removeAt);

    tb.Text = beforeCut + afterCut;

    tb.SelectionStart = beforeCut.Length;
}
Then that just leaves pasting the text back in at a newly selected location.
private void PasteClick(object sender, EventArgs e)
{
    var insertAt = tb.SelectionStart;

    tb.Text = tb.Text.Substring(0, insertAt) +
              this.localClipboard +
              tb.Text.Substring(insertAt + tb.SelectionLength);

    tb.SelectionStart = insertAt + this.localClipboard.Length;
    tb.SelectionLength = 0;
}
The above also selects the newly pasted string. Simples! Now, while you digest all that, please head on over to http://www.wp7comp.com/scratch-pad/ and leave some lovely comments - Thanks.

What hackers can teach us about what might be coming in future versions of Windows Phone

Ever wondered why so many of the "hacked" Windows Phone 7 apps show loading additional ringtones or accessing the camera directly?

Well I've had a little look at what some of the hackers have been doing and have found a few managed assemblies that aren't publicly available and it seems to be these that most of the people exploring in this area have been looking at.

So, for your amusement, interest and to satisfy your curiosity, here, in no particular order are some of those methods:

public abstract class Camera : IDisposable
{
  // ...
}

public sealed class PhotoCamera : Camera
{
  // ...
}

public sealed class VideoCamera : Camera
{
  // ...
}

public sealed class RingtoneLibrary
{
  // ...
  public void AddRingtone(Stream ringtoneSource, string ringtoneName)
  {
    // ...

    StreamHelper helper = new StreamHelper(ringtoneSource);
    try
    {
        NativeMethods.MediaApi_AddRingtoneFile(helper.GetTempFile(), ringtoneName);
    }
    finally
    {
        helper.Cleanup();
    }

    // ...
  }

  // ...
}

[DllImport("netcfmail3_7.dll")]
internal static extern byte GetMessageData(IntPtr pMessageNode, byte[] dataBuffer, int cbDataBuffer, byte[] idBuffer, int cbIdBuffer);
 
[DllImport("netcfmail3_7.dll")]
internal static extern int SendAsAttachment(string to, string subject, string messageClass, byte[] data, int cbData, string attachmentFileName);

[DllImport("netcfmail3_7.dll")]
internal static extern int SendInBody(string to, string subject, string messageClass, string body, int cchBody);

public CivicAddress ResolveAddress(GeoCoordinate coordinate)
{
  // ...
}

public static extern int HostGetAvailableFreeSpace(IntPtr pRuntimeHost, out long pAvailableSpace);

The things that jump out at me, apart from the camera access are the methods relating to emails!

My theory is that if there is managed functionality in the framework already (and its use doesn't pose a threat to the security of the users data or device) it's not unreasonable to assume that this could be made public in the future.

Just in case it bears repeating, this is all speculation and I have no special insight into what might be coming in future versions.