Friday, August 13, 2010

Kids Alphabet, an Android-based application, released: story from the frontline


Foreword

My first Android-based application Kids Alphabet has been recently released on August 10, 2010. This article gives a short summary of activities required for successful implementation and publishing of Android product and might be helpful for those who are still planning to release the first application to the market.

Prehistory

Since first Android SDK was introduced to developers in the far 2008 I participated in 1-st Android Developers Challenge as a member of Intelliarts mobile solutions team, created a set of Android applications as a freelancer and finally got to the point when I decided to create an own product.

I had a few ideas of potentially asked-for application on Android Market but I selected the easiest one to be my first application which would pass the "Product Idea to Product Success" road. Such a decision was made because a short-term project gives almost the same experience in Android product creation process as a long-term one, besides it reveals all the potential problems that might occur during application implementation and publishing.

Application Idea proof

Before starting an implementation of your idea it worth to spend some time and take a closer look on alike applications that are already published on various Android Markets. There are so many Android developers around the globe that it might turn out that the same idea was already implemented. But that doesn't mean that you should immediately forget this idea and choose another one. Instead, investigate how popular are those applications, what might be done better, what unique features you might provide to the users of your application. Depending on investigation results you should decide whether it still worth to create the better and cost-effective application than those ones available on Market or maybe choose another idea.

User Interface design

This is probably one the most important activities as the fist impression of the end-user about your application comes from UI. Don't hesitate to invest some money and hire a designer who will help you to organize our thoughts about application UI, create few prototypes in order to chose the most pretty and usable one. Remember that potential buyers of your application won't even look on it if it have an ugly design no matter what unique and useful features does it provide.

Implementation and Testing

Implementation phase is the most interesting from the developer's point of view as it implies the actual development work on application. While every developer can spend as much time as needed to create a perfect application the stark reality says that we don't have too much time for that. The number of applications published on Android Market grows extremely fast, there are a hundreds of new products being posted on Market every day. So you should take that into account if you don't want to find out on the pre-release day that somebody has already implemented and published almost the same application. For example, it took me about three months to create a first release of Kids Alphabet application but during that time there appeared approximately 5 applications with the alike idea on Android Market, which means that potential buyers of my product might have already purchased another applications.

Of course, while developing the application really fast you shouldn't forget about testing - reasonable amount of time should be spent on application testing as if application crashes or works unexpectedly the end-user will probably remove it and place a low rating. It would be great if you perform a beta-testing of your application. In case you're planning to sell the product and you don't want to share fully functional application you might create a Lite version and let other Android developers give it a try. Thus you might get a really important feedback before releasing your application and fix critical issues if any were found during beta-testing.

Full vs. Lite version

A lot of developers use the practice of publishing both Full and Lite versions of the application to Android Market. There are several articles describing how to implement a Lite version of Android application, the most common approaches are:
  • Reduce the amount of features which user might use in a Lite version - it looks to me that this approach doesn't apply to big applications with a bunch of functionality as the user would likely want to see all those features before purchasing your product. Such approach applies best to the games development where you might limit the number of levels available in Lite version.
  • Allow fully-functional application usage for a trial period - this approach is easily circumvented by installing an application once again after the trial period has expired. I'd not recommend to use it.
  • Setup a server which will contain a database of phones that have already used their trial period - while this approach is quite secure it requires set up of web service.

I've created one more approach which I used for a while in my product: the fully functional application limited to 15 minutes usage per day. While this approach gives users ability to try all available features that application provides it still doesn't allow to use application in full strength. This method also doesn't have the weakness of trial period based approach as reinstalling the application won't grant full access to application features for another trial period. I have to say that I finally decided not to publish the Lite version of product on Android Market as all paid applications can be evaluated during 24 hours after purchase and canceled if the user didn't like them.

Publishing your application

This is probably the most exciting moment of the overall Android product development process - you've finished your application and is ready to show it to the whole world. Keep in mind that creating a publisher account on Android Market requires from 3 to 5 days. So if you're planning to make the release on particular day, for example before Christmas, and you didn't setup an Android Market account yet then you should take a time and perform this in about a week before release.

Maintenance

Huge part of work is done at this point but since the moment you've sell the first copy of your application you should think of customers maintenance. The good idea would be to create at least a simple application site which provides a possibility for customers to contact you in case of any questions/problems. Remember that providing good services for your customers is also a part of Android application developer's work.

Conclusion

The goal I set myself at the very beginning of the product development was reached. While of course some mistakes were made during creation of my first Android product this experience will be reused in further projects.

Hopefully this information would be helpful for other developers !
 

Tuesday, April 6, 2010

Passing parameters and retrieving results from inner/outer UAC processes in NSIS-based installer


Foreword

While creating NSIS-based installer for one of my projects I used UAC plugin in order to elevate the installation process to administrator privileges. Those who used UAC plugin know that it creates additional admin level process during initialization and installation continues to operate in it. But user level process is still available and might be used in order to perform some user-related operations like creation of shortcut on the Desktop, creating of user-related preferences, etc.

When executing some code segment from user level process via calling to UAC::ExecCodeSegment it's sometimes required to pass parameters and retrieve back results, so this article would give some insight into this problem and a ways of solving it.

Passing parameters to user level process during UAC::ExecCodeSegment call

It is quite simple to pass parameter from admin level process (also called 'inner') to the user level process (also called 'outer') - all we need to do is to call UAC::StackPush function which will place specified value into outer process's stack. In order to get passed parameter in user level process we might simply call Pop or Exch function which will retrieve passed value.

; Function which is executed from user level process
Function UserLevelFunction
    ; Getting passed parameter into $0 variable.
    ; By calling 'Exch' we might preserve value which already
    ; was stored in $0 (if not required a call to 'Pop' might be used).
    Exch $0

    ; Showing test message from user level process with retrieved parameter
    MessageBox MB_OK "Parameter: $0"

    ; Getting back previous value of $0 variable (if required)
    Pop $0
FunctionEnd

; Section which is executed from admin level process
Section "UACParameterPassingTest"
    ; Specifies for which install types this section would be used
    SectionIn 1 2

    ; Placing parameter into stack of user level process
    UAC::StackPush "testParameter"

    ; Executing function with user privileges
    GetFunctionAddress $1 UserLevelFunction
    UAC::ExecCodeSegment $1
SectionEnd

As you might have noticed there is nothing complex about passing parameters to the user level process so lets proceed to the next section as that one requires non-trivial solution.

Retrieving results from user level process after UAC::ExecCodeSegment call

Unfortunately there is no standard way of passing back results of execution from function called in outer process. There is also no possibility to create some global variable which would be shared between inner/outer processes and pass results via it. So during implementation of my installer I created one solution and am going to describe it in more details here.

The main idea of proposed solution is to write resulting data to some file in a system folder accessible from both user level and admin level processes. In case of my installer I used user's Application Data folder to store file in it. In order to retrieve path to this folder from both processes we need to define special item ID constant in installer's code (please refer to following article for more details: CSIDL Windows)

!define CSIDL_LOCAL_APPDATA "0x1C"

and call to UAC::GetShellFolderPath function

UAC::GetShellFolderPath ${CSIDL_LOCAL_APPDATA} $APPDATA

as this guarantees that we'll receive the same path for user and admin level processes. So, once we have strictly defined place for populating/reading results, the implementation of overall solution doesn't bring much trouble. The complete solution looks like following:

!define CSIDL_LOCAL_APPDATA "0x1C"

; Function which is executed from user level process
; and returns result to admin level process
Function UserLevelFunction
    ; $0 - contains path to user's local AppData folder
    ; $1 - contains temporary file handle

    ; Retrieving the path to user's Application Data folder.
    ; The result is automatically placed into $0 variable.
    UAC::GetShellFolderPath ${CSIDL_LOCAL_APPDATA} $APPDATA

    ; Writing result of execution to the file accessible
    ; by both user and admin processes.
    FileOpen $1 "$0\UACResultRetrievingTest.dat" w
    FileWrite $1 "functionResult"
    FileClose $1
FunctionEnd

; Function which is executed from admin level process
; and processes result retrieved from user level process
Function ProcessResult
    ; $0 - contains path to user's local AppData folder
    ; $1 - contains temporary file handle
    ; $2 - contains result of execution read from temporary file

    ; Retrieving the path to user's Application Data folder.
    ; The result is automatically placed into $0 variable.
    UAC::GetShellFolderPath ${CSIDL_LOCAL_APPDATA} $APPDATA

    ; Reading result of execution from the file accessible
    ; by both user and admin processes.
    FileOpen $1 "$0\UACResultRetrievingTest.dat" r
    FileRead $1 $2
    FileClose $1

    ; Removing temporary file (if required)
    Delete "$0\UACResultRetrievingTest.dat"

    MessageBox MB_OK "Result of execution: $2"
FunctionEnd

; Section which is executed from admin level process
Section "UACResultRetrievingTest"
    ; Specifies for which install types this section would be used
    SectionIn 1 2

    ; Executing function with user privileges
    GetFunctionAddress $0 UserLevelFunction
    UAC::ExecCodeSegment $0

    ; Executing function with admin privileges
    Call ProcessResult
SectionEnd

As you might see the solution is not complex one but it took a while to get to it. So hopefully it will help someone to save a bit of time for more interesting tasks.

Conclusion

Proposed techniques allow to pass required values between inner and outer processes in NSIS-based installer which uses UAC plugin for elevation to administrator privileges. As an example, I used this approach to pass user's registry SID retrieved in user level process but required in admin level process. There are few posts on NSIS Discussion forum proposing rare solutions for similar problem, but they are not well structured and not complete so as the result - hard to understand. This post intended to summaraze all those techniques and provide complete solution with code examples.