Wednesday, November 4, 2009

Get Facebook user's permission

In using the Facebook developer toolkit it was necessary to ask the user for extended permission to publish to their wall server side.

The FbPermissions class is initialized with the required permissions. Calling the GetPermissionFromUser will display the facebook permissions dialog.

If all permissions were granted the dialog will not be invoked next time. This prevents a momentary flash of the permissions dialog if you're using AJAX to make server requests.


<script type="text/javascript">
function FbPermissions(options){
 this.requiredPermissions = options["RequiredPermissions"]; 
}

FbPermissions.prototype.callback = function(e, successCallback, failureCallback){
 if(e === false){
  if(failureCallback != null)
   failureCallback();
 }
 else if(e == null || e === ""){
  if(failureCallback != null)
   failureCallback();
 }
 else{
  if(successCallback != null)
   successCallback();
  
  //Simple length check should be sufficient 
  if(this.requiredPermissions.split(',').length == e.split(',').length)
   this.requiredPermissions = "";
 }  
}

FbPermissions.prototype.GetPermissionFromUser = function(successCallback, failureCallback)
{
 var me = this;
 if(this.requiredPermissions != null && this.requiredPermissions.length != 0)
  FB.Connect.showPermissionDialog(this.requiredPermissions, function(e){me.callback(e, successCallback, failureCallback);});
 else
  successCallback();    
}


Usage


Using the class is simple. Just initialize the FbPermissions with the required permissions using a server side script block. Then invoke the GetPermissionFromUser function with a success and failure callback method.

var permissions = new FbPermissions({RequiredPermissions : '<%= Model.RequiredFacebookPermissions %>'});

function PostToWall(message) {
   permissions.GetPermissionFromUser(
   function(){/*Call your facebook application here*/},
   function(){alert('You must grant permission');})  
  }
</script>

<a href="#" onclick="PostToWall('hi'); return false;">click me</a>

Tuesday, September 15, 2009

Selenium RC timing issues

Even the best Selenium test will fall victim to timing issues which will cause tests to fail some what randomly.

This class attempts to isolate the test from timing issues by performing an automatic retry.

public static class SeleniumRetry
 {
  public static void Invoke<TArg>(Action<TArg> action, TArg arg)
  {
   Invoke(() => action.Invoke(arg));
  }
  
  public static void Invoke<TArg1, TArg2>(Action<TArg1, TArg2> action2, TArg1 arg1, TArg2 arg2)
  {
   Invoke(() => action2.Invoke(arg1, arg2));    
  }
  
  public static void Invoke(Action action)
  {
   var attempt = 0;
   const int maxAttempts = 5;
   while (true)
   {
    try
    {
     action.Invoke();
     break;
    }
    catch (Exception e)
    {
     Console.WriteLine(e.Message);

     if (++attempt > maxAttempts)
      throw;

     Thread.Sleep(500);
    }
   }
  }
 }


Using the class is simple:
This scenario shows how to automate a dynamically loaded login form that is created when the PopupLogon link is clicked.

SeleniumRetry.Invoke(Browser.Click, "PopupLogon");

SeleniumRetry.Invoke(Browser.Type, "input_email", "fake@email.com");
SeleniumRetry.Invoke(Browser.Type, "password", "12345");

//First click selects the button, second performs action.
SeleniumRetry.Invoke(Browser.Click, "submitBtn");
SeleniumRetry.Invoke(Browser.Click, "submitBtn");

Thursday, September 10, 2009

Automatically start and stop SeleniumRC with NUnit

You can use NUnit and SeleniumRC to run automated functional tests of your website. This is a simple class that starts selenium at the beginning of a unit test suite and shuts it down when done.


using System.Diagnostics;
using System.Net;
using NUnit.Framework;

[SetUpFixture]
public class SeleniumRcSetup
{
private readonly Process SeleniumRC = new Process();
[SetUp]
public void StartSelniumRc()
{
const string pathRelativeToProjBinDebug = @"path to your selenium installation";
SeleniumRC.StartInfo.FileName = "java";
SeleniumRC.StartInfo.Arguments = string.Format("-jar {0}selenium-server.jar", pathRelativeToProjBinDebug);
SeleniumRC.Start();
}
[TearDown]
public void StopSeleniumRc()
{
var r = WebRequest.Create("http://localhost:4444/selenium-server/driver/?cmd=shutDown");
r.GetResponse();
SeleniumRC.WaitForExit(5000);
SeleniumRC.Close();
}
}

Wednesday, September 9, 2009

Using XmlSerializer without rendering document declaration or namespace

Using xmlSerializer to serialize an object will by default add the xml namespace and document declaration. <strong>Example</strong>:

<?xml version="1.0" encoding="Windows-1252"?>
<node xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uID="12345">
...
</node>

But if all you want is to write out the xml fragment like:
<node uid="12345">
...
</node>

You need to configure the serializer before you use it. The following code will not render the document declaration or namespace.

public void SerializeWithNoDeclarationNoNamespace<T>(TextWriter writer, T theObject)
{
var settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
NewLineHandling = NewLineHandling.Replace,
NewLineChars = Environment.NewLine,
OmitXmlDeclaration = true
};

using (var xmlWriter = XmlWriter.Create(writer, settings))
{
var xmlnsEmpty = new XmlSerializerNamespaces();
xmlnsEmpty.Add("", "");

new XmlSerializer(typeof(T)).Serialize(xmlWriter, theObject, xmlnsEmpty);
}

writer.WriteLine("");
}

Friday, July 31, 2009

iTunesConnect crash reports

One nice feature of iTunesConnect is that you get crash reports from real users. You can use the symbolicatecrash script to map the crash report to line numbers in your code.

symbolicatecrash attempts to be very clever at finding the symbol files based on the applicaton GUID found in the crash report. Unfortunately even if you use a revision control system, get the exact revision of the code you released to the iTunes store and re-build, symbolicatecrash wont find the debug symbols because the applications GUIDs don't match.

In a pinch you can break open the symbolicatecrash script file, brush up on your Perl skills and force it to use the symbol file created by the re-build.

But for all future releases you can just have Hudson archive the debug symbol files for you and life will be much easier.

zip -r -T -y "myApp_ProdSymbols.zip" "myApp.app.dSYM"

Friday, July 17, 2009

iPhone app distribution made easy - Part 4

Introducing Subversion
One of the most important items for any kind of software development is a version/revision control system. There are many flavors of version control systems and many arguments for and against each one. Ultimately they all provide the ability to track changes in code over time and provide the ability to manage development paths. For the purpose of this post I'll be referencing SubVersion (http://subversion.tigris.org/).

Introducing Hudson
Hudson is a continuous integration build system that enables easy tracking and running of builds. Hudson can be downloaded from https://hudson.dev.java.net/ and is very easy to get started and can be run on the Mac with the following command "java -jar hudson.war".

Hudson is integrated with subversion so builds can be triggered by subversion code commits. Builds can also be launched manually. One of the great strengths of Hudson is that it manages all the build numbers and build artifacts for you so you don't have to think about it.

Basic steps
The steps to get Hudson building your iPhone applications are quite simple and follows the format:


  1. Create a new hudson job

  2. Point Hudson to your subversion repository

  3. Create a build step to run the build scripts developed earlier in Part 2 and Part 3.

  4. Instruct Hudson to save the build output.


Example Build step
The following build step starts by creating some variables for build folders etc using some of Hudson's built in environment variables. It then builds the AppStore and AdHoc distributions.

PROJDIR=${WORKSPACE}/myApp
ADHOC_BUILDDIR="${PROJDIR}/build/myAppAdHoc/DistributionAdHoc-iphoneos"
APPSTORE_BUILDDIR="${PROJDIR}/build/myAppAppStore/DistributionAppStore-iphoneos"
BASEFILENAME="${JOB_NAME}_${BUILD_NUMBER}(rev-${SVN_REVISION})"

echo Building AppStore release
cd "${PROJDIR}"
xcodebuild -target "myAppAppStore" -configuration "DistributionAppStore" -sdk iphoneos2.1
cd "${APPSTORE_BUILDDIR}"
zip -r -T -y "${BASEFILENAME}_AppStoreApp.zip" "myApp.app"

echo Building AdHoc release
cd "${PROJDIR}"
xcodebuild -target "myAppAdHoc" -configuration "DistributionAdHoc" -sdk iphoneos2.1
cd "${ADHOC_BUILDDIR}"
zip -r -T -y "${BASEFILENAME}_AdHocApp.zip" "myApp.app"


The output zip file name will include the build number & subversion revision number for easy reference.

Example: myApp_13(rev-99619)_ProdApp.zip

Example artifacts archive
Hudson has the ability to perform wild card searches when looking for build artifacts. The following will search both the AdHoc and AppStore build folders for their output files.

myApp/build/**/*.zip

Conclusion
So hopefully you are now inspired or atleast aware of how you can make your own iPhone development easier.

iPhone app distribution made easy - Part 3

Now that we've built the distributions with xcodebuild it seems a shame to use Finder to compress the app bundle for submission to the App Store.

So lets use the "zip" command line utility to compress the app bundle:

zip -r -T -y "myApp_AppStoreDistribution.zip" "myApp.app"

The important option to note here is the "-y" option that stores symbolic links as the link. This is important because the app bundle contains symbolic links to the code signature folder.

If the symbolic links don't exist the application will not be accepted and iTunesConnect will complain with an error like:

The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate...

Now all that is left for us to do is formalize the build process and we're good to go. Next time I'll introduce the continuous integration engine called Hudson.

iPhone app distribution made easy - Part 2

Being able to build various distributions in the XCode IDE is great but you have to think about what you're doing very carefully. Thankfully the 3.0 version of the SDK comes with an improved command line build utility called "xcodebuild".

Here's an example of how to build the AppStore distribution:

xcodebuild -target "myAppAppStore" -configuration "DistributionAppStore" -sdk iphoneos2.1

As you'll notice the target, configuration and the sdk to use are being specified. Note: The sdk option is new for the 3.0 sdk and can take either the name or path of the sdk to use.

You can view all of the installed sdks by running the following command:

xcodebuild -showsdks

So now we have the ability to build the distributions without thinking about it. We could put this in a script and call it a day but lets not stop there. Next time we'll zip up the app bundle for submission to the AppStore or AdHoc users.

iPhone app distribution made easy - Part 1

This is the first in a multi part series that will explore one approach to making iPhone app distribution a single click operation. The purpose is to take the thought out of generating a distribution and leave you free to concentrate on the real work. There are some prerequisites that I'll assume you have completed:
  1. Registered for the iPhone developer program.
  2. Created you unique AppID.
  3. Requested your code signing certificate.
  4. Created your distribution profiles for iTunes store and AdHoc.
  5. Installed these items on your development machine.

Armed with these items we'll begin by setting up the project.

Creating distribution configurations

Using the "project info" window's "configurations" tab duplicate the Release configuration twice. I named the two configurations "DistributionAdHoc" and "DistributionAppStore" but you're free to come up with your own convention.

The next step is to assign the "code signing identity" to the corresponding distribution profile. Do this in the "build" tab.

Creating the AdHoc target

The only difference with the AdHoc target is that it has the iTunesArtwork file so that iTunes will display the application icon. The application icon for the iTunes for the AppStore distribution will actually come from the iTunes store.

Create a new target by selecting the projects current target and duplicate it. Rename the target to something that indicates that its the AdHoc target. Add the iTunesArtwork file to the "Copy Bundle Resources" step of the target.

Note: The iTunesArtWork file is a 512x512 png file with no extension in the root of the app bundle.

One step closer

So now you should be able to select the Target, Configuration and SDK and build your specific distribution.

Next time we'll use the command line build utility xcodebuild to take the thought out of building.

Thursday, July 16, 2009

Giving back

Apart from some rather niche forums (XP Embedded for example, don't know what XPE is? I did say niche) I'll admit to taking a lot of knowledge but rarely giving anything back.

I hope to rectify this by sharing tips and tricks that I've learned along the way.