AssemblyMate

Coming soon: AssemblyMate

0

I submitted a new Windows Phone app today called AssemblyMate. Building on the success of my app for Jehovah’s Witnesses to use in the ministry — MinistryMate — I am hoping to address another common need with the new app.  AssemblyMate will allow you to take notes at assemblies and conventions and have the notes stored right on your phone.  You can also record details about the assembly such as attendance and baptism numbers.

The assembly programs will be automatically downloaded to your phone as soon as they are available.  Then you can set the dates for when you will attend.  Within the program listing, you will be able to click on each talk and enter the name of the speaker as well as some points you want to remember.

But what good are all those notes if they only exist on your phone?  One of the nicest features is the ability to upload the notes for the entire assembly to your SkyDrive account.  From there, you can download them to your PC, print them, search them, anything you want!

And this is just the beginning!  When Windows 8 is released in 2012, look for a version of AssemblyMate that works on your Windows tablet device!

MinistryMate

MinistryMate 2.2

2

MinistryMateToday I submitted the latest update to the best ministry app on the Windows Phone platform, MinistryMate.  As more and more users have downloaded the app, the feedback I have received has proven invaluable in deciding what changes to make and what new features to add.  The latest release is another example of that.  The goal of this app is to help fellow Witnesses be more organized and productive in their ministry, and incorporating the most requested fixes and new features is helping that goal become a reality.  Here’s what’s new in 2.2:

  1. Improved navigation – A landing page now gives you 1-click access to anywhere in the app.  Also, the ‘recent’ section of the panorama lets you get back to the most current items without having to hunt them down.
  2. Schedule hours for future dates – Add time for a future date, and it is added to your report as “projected” time, helping you schedule your month’s activity and keep on track to reach your goals.
  3. Filter calls by street – Have several calls on the same street?  Select the street in the calls filter and see only those calls.
  4. See current location on map – Now you can see not only the location of your call(s) on a map, but see where you are too.
  5. Bug fixes – A bug with the sorting of calls was fixed.  Also, photos should now display correctly, regardless of the orientation they were taken in.

Also, new users may note that the price has been reduced to only $1.29.  Thanks to all for the continued support, and by all means please continue to give me your feedback, both positive and negative, so I can make this app everything you need it to be.

 

Phone Number Context Menu

WP7 App: MinistryMate v1.5

2

I just submitted the next update of MinistryMate for certification.  I’m really excited about this release because of some of the new features I was able to add that will greatly enhance the user’s experience.  Here’s a quick rundown of what’s included:

Phone Number Context Menu

Phone Number Context Menu

  1. Better backup and restore using Dropbox.com – I added backup/restore functionality back in version 1.3, but some users have reported issues with connectivity to the remote server which the backups are sent to.  In order to overcome that problem, as well as to give the user more flexibility and access to their data, the backups will now be sent to the user’s own Dropbox account.  This transition was made dramatically easier thanks to the DropNet API developed by Damian Karzon.  NOTE: To utilize this feature, you will need to create your own (free) account at Dropbox.com, if you don’t already have one.
  2. Easy error reporting – I’ve tried hard to create an app that is bug free and will provide the user with a reliable, stable experience.  But the realities of the mobile app world are unavoidable.  Sometimes the users will experience errors that neither I nor Microsoft have encountered in testing the app.  To address that situation, I added some error reporting code in this release.  It catches and logs any errors that cause the app to shutdown unexpectedly.  Then the next time you launch the app, it prompts you to email the error report to me.  The hope is that more information on more errors will help me make a better experience for the users.
  3. Edit RVs on the bulk edit screen – Version 1.4 saw the introduction of  bulk editing of placements as part of an improved time managment process.  I left out the editing of RVs because I assumed the automatic calculation that takes place would be sufficient.  But the voice of the users has been heard, and I have added RVs to the bulk edit screen in the new release.
  4. Service year totals for pioneers or traveling overseers – This was another commonly requested feature that I was able to add in this release.  The totals will automatically display at the top of the ‘reports’ screen if the publisher type is set to Regular Pioneer, Special Pioneer, or Traveling Servant.
  5. Turn a house-to-house entry into a call – Another user-requested feature that I was able to deliver with this release.
  6. Send a text message to a call – Instead of just clicking on the person’s phone number to call them, a user requested the ability to send a text message to the phone number.  To use this new feature, you just click and hold on the phone number.  A menu will popup allowing you to select whether you want to call or text the person.  Clicking on the phone number still works the way it always has.
  7. Spanish and French versions – Thanks to the efforts of a couple of our brothers, every line of text in the entire application has been translated to Spanish and French.  Hopefully their efforts will benefit more of our brothers who have been waiting to use this application in their native tongue.

This is easily the biggest update I’ve made to MinistryMate since the initial release back in January.  I hope you enjoy the new features, and, more importantly, I hope they make your ministry more productive as well.  Please continue to provide feedback — positive or negative — and I’ll keep working to make this app better.

Updating WP7 Trial Apps Not Working

0

I just published an update to my MinistryMate application, but when I try to download the update on my phone, the process fails.  I open up Marketplace, which shows one update available.  Then I click on MinistryMate, and press the Update button.  It then shows Queuing, pending, installing (very quickly), then back to a screen telling me ‘No downloads in progress’.  The update was not applied and still shows in Marketplace.  I did some quick Binging and found a thread on Microsoft’s AppHub forums describing this problem and acknowledging a bug.  The thread can be found here.

The most recent post in the forum is from a Microsoft employee and promises an upcoming client update to address the problem.  In the meantime, however, the only workaround is to uninstall the application, then install the new version through the Marketplace.  That’s a huge problem for applications like MinistryMate, which store data on the device, because the data is deleted when the application is uninstalled.  So before you uninstall, be sure to make a note of all the information you’ve saved so you can re-enter it after the update.

I’m sorry for the inconvenience this causes my users, but hopefully Microsoft will have this issue resolved soon.

wp7_English_320x50_blue

WP7 App: MinistryMate

1

MinistryMateMy second Windows Phone 7 app was approved today and is now available in the Marketplace. Its called MinistryMate, and its meant to be used by Jehovah’s Witnesses to organize and track their return visits and field service reports. I’m so happy to have version 1.0 out there, but I’m not close to finished with it.  There are still many, many features I plan to implement in future versions. If you’ve got a Windows Phone, and you’re a Witness, please give it a shot and let me know what you think!

MVVM Mini-Tutorial

0

Jesse Liberty has a great blog post describing the basics of the MVVM pattern and its value in Silverlight and/or WPF development. I’ve been using MVVM for all my new development in the past few months–and even converting old code to use this pattern–for many of the reasons that Jesse lays out, and I found this to be a great tutorial.

Zoom and PageChanged Events for FlowDocumentPageViewer

My app contains several screens that have content displayed in FlowDocuments, contained in the FlowDocumentPageViewer control. The problem that arose is that when the user changed the Zoom level on one screen, then navigated to another screen, the content on the new screen would be displayed at the default zoom level. And when navigating back to the original screen, the content would be reverted to the default zoom there too. My approach to solving this problem was to save the zoom level in a “preferences” class and set each viewers zoom to the saved value. However, a problem with this approach is that there was no way to know when the zoom level changed on the out-of-the-box FlowDocumentPageViewer control.

Some quick Bing-ing led me to an extended control downloadable from this page. The control overrides the FlowDocumentPageViewer’s OnIncreaseZoomCommand and OnDecreaseZoomCommand methods. This solution works great, but only when the user clicks the ‘+’ or ‘-’ to control the FlowDocument’s zoom. The commands are not executed when the user uses the slider control to adjust the zoom, and no overridable methods or events are specific to the slider. So how can I know when the user uses the slider to adjust the zoom instead of the buttons?

For that, I had add another override to the extended control, this time OnPropertyChanged.

protected override void OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
switch (e.Property.Name)
{
case "Zoom":
OnZoomChanged();
break;
}
}

Mozilla Weave

0

I’ve been a huge fan of the Firefox browser for several years, and the folks at Mozilla just keep making it better. The latest enhancement I’m taking advantage of is called Mozilla Weave. I just started using it a few days ago, but so far it’s amazing. The stated goal is to “broker rich experiences while increasing user control over their data and personal information.” I haven’t read much detail on what their vision entails, but the first component released for testing certainly lives up to that goal.

The first component is a service called Weave Sync, “a prototype that encrypts and securely synchronizes the Firefox experience across multiple browsers, so that your desktop, laptop, and
mobile phone can all work together. It currently supports continuous synchronization of your bookmarks, browsing history, saved passwords and tabs.”

This is extremely useful for me because I use Firefox on three different computers at various times and often find myself frustrated with the experience. For example, I might find and bookmark a useful site at work, then struggle to find the site when I’m at home and using a different laptop. I’ve been using the GMarks add-on to handle this for me, but Weave Sync makes the feature more integrated with the browser. The synching of saved passwords is also a time saver, because I will be less likely to use the “forgot my password” feature of sites that I visit on multiple computers.

Of course, all this additional convenience would be pretty much useless if it required a lot of configuration or constant user intervention. But so far, I haven’t noticed any of that. Initial configuration was amazingly simple. Once you install the service (similar to installing an add-on in Firefox), you simply set up an account with a username, password and passphrase. Then setting up another computer requires the same steps, but there is additional wait time for first-time synching. Once each computer is set up, the synching is automatic and unnoticed by the user.

As other browsers continue to try and play catch-up with Firefox, I’ve experimented with them to see if they’ve closed the gap. So far, none have come close. In fact, some of the latest versions, such as IE8 and Google Chrome, seem to be taking steps backwards. Meanwhile, Firefox marches forward with more and more intelligent and useful features.

FTPS over TLS/SSL using C#

1

One of the projects I’m working on has a requirement to send a document over a secure FTP connection. The .NET framework has a built-in class to handle FTP (FTPWebRequest) so that was a good starting point.

The documentation for FTPWebRequest does not provide a great deal of detail on securing the communications between the client and the server. There is simply a boolean property named EnableSSL to turn the encryption on or off. Sounded pretty simple, so here’s what I came up with for my upload method:

public bool UploadFile(Uri serverUri, string userName, string password, string fileName)
{
// the serverUri should start with the ftp:// scheme.
if (serverUri.Scheme != Uri.UriSchemeFtp)
return false;

try
{
// get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.EnableSsl = true;
request.Credentials = new NetworkCredential(userName, password);
request.Method = WebRequestMethods.Ftp.UploadFile;

// read file into byte array
StreamReader sourceStream = new StreamReader(fileName);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;

// send bytes to server
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();

FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Response status: {0}", response.StatusDescription);
}
catch (Exception exc)
{
throw exc;
}
return true;
}

When I ran my app with that method, things didn’t work quite like I wanted them to. Here’s the error I ended up with: “System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.”

The problem is there is no validation procedure. None of the MSDN articles I read said anything about certificate validation. So after much googling, I finally found the missing piece of code in a forum post. So I added a validation procedure and assigned it as the ServicePointManager.ServerCertificateValidationCallback.

public Program()
{
ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertificatePolicy;
}

public bool AcceptAllCertificatePolicy(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}

With that, my secure FTP was a success! Of course, in real-world applications you will want to do some actual validation of the server certificate, but I’ll leave that as an exercise for the reader.

Selecting the input tray when printing XPS documents

1

There are many examples on the web of how to print an XPS document, and for the most part they are relatively simple. But when my application needed to do something crazy (like…I don’t know…tell the document which tray to print to), the myriads of how-to’s proved pretty much worthless. In fact, the only useful information I found on the subject was from a post on MSDN forums. This post proved extremely helpful, even containing a c# code sample that I could use almost as-is.

But when I got to the point of implementing that code, I hit a snag. It seems that the document would always print to the last tray on the printer, even though I was telling it to print to a specific tray. It turns out, there was a little bit of detail missing from the sample code, namely a namespace attribute that needs to be added to the xml document that comprises the PrintTicket. The URI for that namespace is likely to be different for each printer your application prints to, so you need to discover it at runtime.

Here’s the updated sample, with my slight modifications:

public static class XpsPrinterUtils
{
private static string GetInputBinName(string printerName, int binIndex, out string nameSpaceURI)
{
string binName = string.Empty;
// get PrintQueue of Printer from the PrintServer
LocalPrintServer printServer = new LocalPrintServer();
PrintQueue printQueue = printServer.GetPrintQueue(printerName);
// get PrintCapabilities of the printer
MemoryStream printerCapXmlStream = printQueue.GetPrintCapabilitiesAsXml();
// read the JobInputBins out of the PrintCapabilities
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(printerCapXmlStream);
// create NamespaceManager and add PrintSchemaFrameWork-Namespace (should be on DocumentElement of the PrintTicket)
// Prefix: psf  NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI);
nameSpaceURI = xmlDoc.ChildNodes[1].GetNamespaceOfPrefix("ns0000");
// and select all nodes of the bins
XmlNodeList nodeList = xmlDoc.SelectNodes("//psf:Feature[@name='psk:JobInputBin']/psf:Option", manager);
// fill Dictionary with the bin-names and values
if (nodeList.Count > binIndex)
{
binName = nodeList[binIndex].Attributes["name"].Value;
}
return binName;
}
public static PrintTicket ModifyPrintTicket(PrintTicket ticket, string featureName, string newValue, string nameSpaceURI)
{
if (ticket == null)
{
throw new ArgumentNullException("ticket");
}
// read Xml of the PrintTicket
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ticket.GetXmlStream());
// create NamespaceManager and add PrintSchemaFrameWork-Namespace (should be on DocumentElement of the PrintTicket)
// Prefix: psf  NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI);
// search node with desired feature we're looking for and set newValue for it
string xpath = string.Format("//psf:Feature[@name='{0}']/psf:Option", featureName);
XmlNode node = xmlDoc.SelectSingleNode(xpath, manager);
if (node != null)
{
if (newValue.StartsWith("ns0000"))
{
// add namespace to xml doc
XmlAttribute namespaceAttribute = xmlDoc.CreateAttribute("xmlns:ns0000");
namespaceAttribute.Value = nsNameSpaceURI;
xmlDoc.DocumentElement.Attributes.Append(namespaceAttribute);
}
node.Attributes["name"].Value = newValue;
}
// create a new PrintTicket out of the XML
MemoryStream printTicketStream = new MemoryStream();
xmlDoc.Save(printTicketStream);
printTicketStream.Position = 0;
PrintTicket modifiedPrintTicket = new PrintTicket(printTicketStream);
// for testing purpose save the printticket to file
//FileStream stream = new FileStream("modPrintticket.xml", FileMode.CreateNew, FileAccess.ReadWrite);
//modifiedPrintTicket.GetXmlStream().WriteTo(stream);
return modifiedPrintTicket;
}
}
// example of calling above code
string nameSpaceURI = string.Empty;
string selectedBin = XpsPrinterUtils.GetInputBinName(PrinterName, PaperBin, out nameSpaceURI);
PrintTicket myPrintTicket = XpsPrinterUtils.ModifyPrintTicket(defaultPrintTicket, "psk:JobInputBin", selectedBin, nameSpaceURI);
Go to Top