Friday 28 December 2012

The Hobbit

Due to the poor press reviews for the Hobbit I've decided to post my own review and besides 'tis Christmas. Peter Jackson's latest film the Hobbit in my opinion a most excellent and worthy addition to the Lord of the Rings Trilogy.

First of all the 2 hours and 50 mins were packed with action, plot and comedy, even though only one third of the book was covered. Saruman, the head wizard, makes an electric appearance and it is clear he has a dark malevolence about him which gives a new dimension and deeper scope to the plot. Driving the plot forward is an evil battle-scarred Orc who is chasing down the Dwarves with a pack of vicious Wargs.

[FREE][ANDROID] Crossword Solver

The special effects are breath taking, I saw the 3D high frame rate version and was dazzled with the visuals. The 3-D effects were as amazing as the first time I entered a Cinema 180 back in the 1980's. Plenty of objects flying in your face but tempered with the gorgeous New Zealand mountain scenery. The fight scenes are well executed with goblins and foes dispatched messily and quickly. I Look forward to the director's cert 18 cut!

There are plenty of jokes to keep you amused, I particularly liked when the dwarves piled into Bilbo's house and scraped their muddy boots on the fine furniture and then ate all his food. The scene with the trolls, based on London cockney taxi drivers was laugh out loud especially if know some of the vernacular.

The book chapters are closely followed such as Riddles in the Dark where Gollum and Bilbo try to outwit one another by posing riddles is an edge of seat tense experience. There is a nice touch when we first see the ring as it falls from Gollum's knickers. Andy Serkis reprises his role as Gollum and gives another fine performance, you can see why Bilbo stayed his hand as pity sank in.

There is a new main character, Radaghast the Brown (the Bird Tamer) as mentioned briefly in the LOTR, it would seem that him, Saruman  and a mysterious necromancer will be providing the extra plot and intrigue for the other two films of the trilogy. Maybe also Shelob, the spider.

Bilbo is played by Martin Freeman from the BBC comedy show the Office, and he pulls all of the same faces which suits the bewildered Bilbo Baggins of Bagend. I doubted this actor when I first heard but after watching I cannot imagine anyone else, even Ian Holm, nasty Bagginsesy!

To go back to my original point never trust the so called 'critics'. In fact always do the opposite of what they recommend as I bought the WestWing and New Battlestar Galactica box set based on excellent critics reviews, the horror the horror.

[FREE][ANDROID][DIET] Weight Tracker App, 

Oh Gandalf is in it too, smoking some fine weed!


Wishing You a Merry Christmas and Happy New Year
Pig Dog Bay






Thursday 13 December 2012

CleverDic Release 1.10

CleverDic on Google Market

The latest version of CleverDic has been released, the most versatile crossword solver and anagram finder for Android. Fantastic new features have been added such as  two-word anagram searches.


Two Word Anagrams

Better to explain this great new feature with an example:
Type in manchester united

CleverDic will find the following two word anagrams:


mechanised nutter
inducement haters
enchanters tedium
+20 other results

The order of the letters is unimportant, it is the position of the space that matters. So for
manchester united, the space splits the letters into a 10 letter word and a 6 letter word.
For george bush, the space splits the letters into 6 and 4 letter words. CleverDic will then use all the letters in georgebush to find all the possible 6-4 letter word combos.

If you do cryptic crosswords like me, two word anagrams are quite common so this feature is an essential aid in the crossword toolbox.

By the way george bush returns:

gouges herb
bugger hoes

Apologies for any offence.


Shortcuts

It can be quite difficult sometimes to enter say 9 missing letters as you have to type 9 dots, ......... , which can be a strain on the eyes. I've made entering missing letters much simpler by using a number 1-9 to represent a group of missing letters. For example enter z9 to find all the 10 letter words starting with z, some of the examples found:

zigzagging
zimbabwean
zookeepers
zombielike

Clearer Bigger Display

The text field where you enter the letters and the search button are now bigger, some people were telling me that it was not obvious where to enter the text. The background now uses a much lighter shade of sky blue which has improved the appearance of the app in general.

Finally, I've replaced the Android icon from the about screen with an email icon, so that people can easily contact me.


Hope you like the new two word anagram feature.

Happy Crosswording

Pig Dog Bay





Links

Saturday 8 December 2012

Android App Marketing

One big surprise with Android App development is how much time is required to market an app, in fact more effort has been spent marketing my app than actual development. Its a crowded market place out there, but I've found a few ways to  make headway.


Social Media

Most Android forums and blogs suggest using social media to promote your app without actually saying how. I'm not a big fan of Twitter or Facebook, pretty clueless to be honest, but this is what I have done.


  1. Create Twitter, Facebook business page, Facebook user page, Google+ and Blogger pages
  2. Posts links on your pages so that they are all cross referenced
  3. On your Facebook user page, pester your friends to like your business page
  4. Put links to your app on your pages
  5. Tweet links to your app
  6. Google for Android Forums or Android Blogs. On each blog or forum, follow (twitter), like (facebook), +1 (google+) all of them
  7. Post any news about your app, such as new releases on all your sites
  8. Promote the sites within your app, I use an About activity.
Early days yet for me, but I've gained 6 new followers on Twitter who represent major android websites. My Facebook business page still only has 8 likes, these are all from my friends. More importantly these pages show up on Google searches.

When tweeting about your app remember to hash-tag relevant keywords in the tweet, for example #crossword, hash-tags are are similar to keywords for search engines. Only use 1 or 2 hash tags per tweet.

My next step is to create a youtube video of  the app in action.


Forums

Forums are a great way to share ideas with fellow developers and to announce your app to the world for free. One forum that I really like is AndroidPit, there is a thread about promoting Android Apps. A few of us have asked each other to download and review each others app.



App Store Optimization

CleverDic ranked a lowly 28th on the list of apps when I searched for Crossword Solver. So I changed the title of my app to CleverDic Crossword Solver, my ranking jumped to 8th place. I then added a keywords section at the end of the description and my ranking moved up to 6th place. I've read that google does not condone using keywords, alas it seems most folk do use them.

Downloads have jumped 4 fold from around 10 per day to 40 per day. Still small fry in the Android world, but I'm hoping for more improvements to come.

I've also added a feature banner, promo image and text. These items appear on the desktop view of the google market place app page. Not sure what effect they have but the page looks more attractive and all the more successful apps employ these features. I've also posted these images on all my social media sites.

Finally

If all else fails badger your friends and family to download your app. If you see any one with an Android phone in the pub or at work, ask them politely if they mind downloading your app. More seriously though take a look at this very informative blog for further info on marketing android apps and making money:

http://droid-blog.net


Good luck marketing your app, let me know how you get on or any ideas you have
Pig Dog Bay





Links




Monday 3 December 2012

CleverDic Release 1.09

CleverDic on Google Market


The latest version of CleverDic has been released, the versatile crossword and anagram solver for Android.


Hints and Tips

The biggest change has been to the user interface, a hints and tips box is now displayed on start up. I'm hoping this will improve the retention rate of the app, currently its 54% (Active installs divided by Total User installs). The early versions of CleverDic did show examples how to use the app, but were dropped when I changed the UI to use a list.

To implement the new hints and tips box I rewrote the UI to use fragments. Fragments allow you to break the UI into modules (or fragments!). When the user searches for a clue, the hints and tips box fragments is replaced by a list showing the results. I've spent a week testing the changes before releasing since I considered this to be a major change to the app. With fragments up and running it will be easier to add other features to the main screen.


App Rate Prompt

To help increase the number of ratings for CleverDic (currently standing at 6) I've included AppRate by TimotheeJeannin.

https://github.com/TimotheeJeannin/AppRate

After at least 7 days and 10 uses a dialog box will pop up and ask the user to rate the app. The user can choose to rate, rate later or not to rate the app. Lots of good ratings are essential for a decent ranking in the App Store and persuading users to try the app over the many competitors.

Facebook and Twitter

I've put the facebook, twitter and blogger icons back on the about screen. I need to provide ways to allow users to partake in discussions, send feedback and share CleverDic with their friends. If nothing else, the icons look cool.


Name Change

CleverDic is now called CleverDic Crossword Solver. When searching for crossword solver apps, CleverDic ranked 28th, with the new name it now ranks 8th. I have being doing a little research on App Store  Optimization and this guy has great advice:

http://droid-blog.net/category/aso-2/


Happy Crosswording
PDB


CleverDic on Google Market

Thursday 22 November 2012

CleverDic Release 1.08

The main addition to the code for this release is a settings screen which allows the user to configure the search settings. The maximum number of results displayed from a crossword style query can now be set to 50, 100 or 200. The user can now check box to show sub-anagrams or not. There are only two settings so far but as time goes on I'll be adding more settings so the user can better configure the app.

The other major change, I have removed all of the social media icons from the about screen. Instead there is just one button to rate the app. Clicking on the button opens up CleverDic on the Google market place. As yet this is the only way to submit a rating is through the market place.

I decided to stop promoting my Facebook and Twitter pages within CleverDic, as I am not convinced they generate any traffic for the app. The hope was that people would 'like' the PigDogBay Facebook page and so their friends would see the page. Maybe its just early days yet, but I'm going to focus on writing code for now.

One feature that didn't make it in this release is an AppRate prompt. After a certain amount of time and uses, a dialog is displayed asking the user to rate the app. There was a problem in that the market place only displayed for a few seconds and then disappeared. This feature will be added when I have ironed out the problem and it has had a bit more testing under its belt.

For the next release I'll be adding a hints and tips box. I've been trying out the Android Fragments API and support packages. Fragments are like custom controls and  you can swap them in and out. Hopefully using fragments I'll be able to make better use of the screen space for tablet devices.


Never a crossword!
PDB

Friday 16 November 2012

Android Preferences Tutorial

Introduction

Recently I have added a preference screen to one of my Android apps and now is a good time to put all what I have learnt down on paper, more for future reference. I'll present a quick tutorial and then discuss more advanced topics and pitfalls. Note that I will not be discussing the new Preference Fragments API, for now my Nexus 7 is more than happy running the deprecated preference APIs.

[FREE][ANDROID] Crossword Solver

Creating the Preference XML

The preference screen is defined in an XML file, Android can take this XML file and create an activity (user interface) and deal with the data binding and storage. Very nice indeed.

In the res folder create a new folder called xml. The new xml folder is where we will place our preferences.xml file. Eclipse can create the file for us
  1. Right click on the xml folder
  2. Click on New on the pop-up menu
  3. Click on Android XML File
  4. The New Android XML File dialog will be displayed
  5. Select Preference in the Resource Type drop down list
  6. Enter file name, preferences.xml
  7. Select PreferenceScreen in the root element list
  8. Press Finish


Creating the Preference User Interface

Below is the code from my preference.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" 
    android:title="@string/pref_title">
    <PreferenceCategory 
        android:title="@string/pref_search_cat"
        android:key="search_category">
  <CheckBoxPreference 
      android:key="show_subanagrams_pref"
      android:summary="@string/pref_findsubanag_summary"
      android:title="@string/pref_findsubanag_title"
      android:defaultValue="True"
      />    
  <ListPreference 
      android:key="result_limit_pref"
      android:title="@string/pref_resultlimit_title"
      android:summary="@string/pref_resultlimit_summary"
      android:defaultValue="200"
      android:entries="@array/resultLimits"
      android:entryValues="@array/resultLimitsValues"
      />
    </PreferenceCategory>
</PreferenceScreen>

I have a CheckBoxPreference to toggle a boolean value and a ListPreference to select a string value. I've put the display strings in the strings.xml file in my values folder. You'll notice that the list preference references an array resource. You can create the array resources by creating a resource file (another Android XML file) in the values folder and call it arrays.xml. Below is my arrays.xml file:


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="resultLimits" >
        <item name="50">50 Results</item>
        <item name="100">100 Results</item>
        <item name="200">200 Results</item>
    </string-array>
    <string-array name="resultLimitsValues">
        <item name="50">50</item>
        <item name="100">100</item>
        <item name="200">200</item>
    </string-array>
</resources>

Next we need to create an activity class for the preference screen and  inflate the XML in preferences.xml. Create a new class under your src folder called SettingsActivity.java:


package com.mpdbailey.cleverdicandroid;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class SettingsActivity extends PreferenceActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        // Note that none of the preferences are actually defined here.
        // They're all in the XML file res/xml/preferences.xml.
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }
}

This class extends from PreferenceActivity instead of Activity and calls addPreferencesFromResource(R.xml.preferences) to create the user interface from the XML in preferences.xml.

Thats it! There is no need to worry how Android binds the data to the preference UI controls, its all done under the bonnet. Android also takes care of storing the data for you.


Using Preferences From Your App

In my MainActivity class, I have the following code that fires up the Preference Activity:

 @Override
 public boolean onOptionsItemSelected(MenuItem item)
 {
  Intent intent;
  switch (item.getItemId())
  {
  case (R.id.menu_settings):
   intent = new Intent(this, SettingsActivity.class);
   startActivity(intent);
   break;
  default:
   return false;
  }
  return true;
 }
 

I've put a menu item called Settings on my menu and the code above will start the preference activity when the user clicks on the settings menu button.

The code below is also from the MainActivity class and details with the interaction with the preference data.



 @Override
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  prefs.registerOnSharedPreferenceChangeListener(this);
  LoadPreferences(prefs);
 }

 public void onSharedPreferenceChanged(SharedPreferences prefs, String key)
 {
  LoadPreferences(prefs);
 }

 private void LoadPreferences(SharedPreferences prefs)
 {
   this.presenter.SetFindSubAngrams(prefs.getBoolean("show_subanagrams_pref", true));
   int limit = Integer.parseInt(prefs.getString("result_limit_pref","200"));
   this.presenter.SetResultLimit(limit);
 }

 @Override
 protected void onDestroy()
 {
  super.onDestroy();
  PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
 }
 
 
 

I get the SharedPreferences object using PreferenceManager.getDefaultSharedPreferences(this), which allows the various activities of my app access to the preference data.

The Preference User Interface will fire SharedPreferenceChanged events which I listen to in my MainActivity class to keep the app up to date with the latest preferences. These events fire as soon as you change a preference, toggle a check box on the preference form and the event will fire.


 Note that when the app first starts that I call LoadPreferences() this is important as it sets up my app with the current preference information.

Application Life-Cycle Pitfalls

Be careful if you use anonymous inner classes to implement the OnSharedPreferenceChangeListener. You'll notice that in the code above I register  the MainActivity class in  OnCreate()  and unregister in OnDestroy(). This is fine if the MainActivity object is the listener. If you use anonymous classes then these can be collected by the garbage collector when the app is paused, this means that your app will then stop responding to SharedPreferenceChanged events. For more details see this StackOverflow Question about the issue.

[FREE][ANDROID][DIET] Weight Tracker App, 

Wrapping Up

The Android Preference Framework pretty much does all the work for you, its just a matter of hooking your code up to it. For an example project see the SipDemo in the Android SDK samples.




Thursday 15 November 2012

CleverDic 1.07 Released


CleverDic on Google Market


The latest version of CleverDic, the crossword solver app, has been released. Two changes have been made that increase the apps usefulness and ease of use.





The first change is a new feature that shows you the missing letter for the sub-anagrams in the list. The above screenshot shows the various 6 letter anagrams of the word hearts first then the sub-anagrams. There are over 20 five letter anagrams that can be made from the various letters in hearts. The word earth can be made from hearts and is now shown in the list as 'earth (s)', the letter s being unused.




The second change is an improvement to the Clear option in the menu (or action bar for later Android versions). When you press clear now the keyboard is displayed which saves you from having to touch the edit box to enter  your anagram.



Happy Crosswording!


Links

CleverDic on Google Market

Thursday 1 November 2012

RoboQuipper 1.00

Download RoboQuipper from Google Market



RoboQuipper took just 2 hours to create. Half of that time was spent drawing the RoboCop face, which I drew using Inkscape. As you can see the face is just a few shapes with a gradient fill. Most of the android boiler plate  I just cut and pasted from CleverDic ('ll eventually get round to writing shared libraries and controls at some point).

RoboQuipper originally started as an Easter Egg in a piece of scientific software I wrote. In that version an image of the RoboCop ZX Spectrum loading screen is displayed. When the user clicks on the image a random quote from the film pops up.

There is this nagging horrible feeling at the back of my mind  that this app will be lawyer bait, anyone know if this infringes any copyrights?

I'd Buy that for a dollar!
Pig Dog Bay

Links

Download RoboQuipper from Google Market

Wednesday 31 October 2012

CleverDic 1.06 Released

CleverDic on Google Market

The latest version of CleverDic, the crossword solver app, has been released. The user interface has been revamped to give a smarter and cleaner appearance. The background now has a sky blue gradient and there is a status bar that indicates the number of matches or if the app is busy searching. The keyboard automatically disappears after you press search or enter.


The text field on the main screen has now been replace with a list. This meant I had to provide help and information in other ways. I've created a help screen and one time only  welcome dialog that shows a simple help message.




You can now look up the word definitions by touching the words. This works by opening up the web browser and performing a special search through Google. For example, to look up the word android, the app will now browse to this URL:

http://www.google.com/search?q=define:android


To help gather user feedback and to promote other apps, I've added an about screen. The screen shows icons for Facebook, Twitter, Blogger and Google Android Market.



Other refinements include switching off the auto-rotate feature, this was just annoying, the app remains in portrait mode now.

For the next release I'm considering adding a settings screen to allow the user to select the background colour, the maximum number of  words shown and turn on/off the sub-anagrams feature.

Happy Crosswording!


Links

CleverDic on Google Market

Sunday 28 October 2012

New Website

I've set up a new website for Pig Dog Bay:

http://www.pigdogbay.com

For now it contains the Pig Dog Bay logo and links to:

Android Market
http://play.google.com/store/search?q=pub:Pig+Dog+Bay

Facebook
http://www.facebook.com/PigDogBay

Twitter:
https://twitter.com/pigdogbay

Blogger
http://pigdogbay.blogspot.co.uk/

The idea is to promote my Android apps and more importantly to gather feedback from users so that I can make improvements. This blog will contain technical articles about software engineering and information about my Android apps, hopefully readers will be able to share their ideas and knowledge as well.

My goal is to see if I can make a living from writing Apps for Android, any tips or advice would be greatly appreciated. I won't be giving the day job up just yet though.

C# versus Java

Recently I bought a Google Nexus 7 tablet and so immediately entered the world of Android development. My old friend Java beckoned, and it seems that Java has not kept up with modern programming developments.


Functional Programming

This paradigm has completely passed Java by. C# supports Lamda expression, you can pass functions as parameters to functions, return functions from functions and proper closures (making local variables available to the lamda function). The best you can do with Java is anonymous inner classes, clumsy and lots more typing.

There is no LINQ or IEnumerable<> interface equivalent in Java, however Java does have its own version  of the foreach statement.


Clean up

I like C#'s IDisposable clean-up pattern, OK its not perfect especially when you need to share a resource.
The great thing about tidying up resources in C# is the using statement. The latest version of Java has implemented something similar using try{}, not available for Android Java though, hmm.


String or string

I'm forever typing string instead of String in Eclipse, gahhhh! I can see why now C# now uses boxing it makes things simpler if you also regard types such as int and floats as objects. I also hate having to use NumberFormat to format ints/longs/floats into strings, just have ToString(), oh they can't in Java because they are not objects.


Exceptions

When I first started writing C# I couldn't believe how lax it was as you didn't need to say what exceptions a function throws. Going back to Java, having to either catch exceptions or declare them is a real pain in the A. I can see this leading to bad practices such as programmers using try/catch around every piece of code, thus hiding problems.


Events

User clicks the button, so you need a click listener? That means implementing an interface or using an anonymous inner class in java. I consider C#'s built in event keyword a superior, simpler and more concise alternative to the Observer pattern. Also C#'s extension methods are a great alternative for the Visitor pattern, which you can't really achieve in Java (or in C# using OOP techniques) due to the lack of Multiple Inheritance.


Eclipse

I use Netbeans (or MPLAB X) for PIC development and it is great. VS2010 with CodeRush is just heavenly. What the heck is Eclipse? A throw back to the 1990's? Eclipse is not pleasant to use, I find it slower to type code, I hate having to hover over a red squiggle to see the bug info, intellisense is slow or non-existant and it has another bunch of key-strokes to learn. I do like Eclipse's auto fix feature though and it does seem to auto-generate boiler plate in an intelligent fashion. Eventually I'll grow to like it, maybe!


Final Thoughts

C# has developed into a multi-paradigm language where as Java seems to have stayed stuck. I guess Sun's demise has not helped Java's cause, it would of been better for Google to have bought Sun instead of Oracle. I once loved Java, my first OOP language,  I scorned C# as a rip off of Java, but now it is clear C# has features that fix many of Java's flaws. Pity C# is a Microsoft technology though.




Thursday 25 October 2012

Embedded C Timing Functions

This post is about simple timing functions written in C for embedded processors or micro-controllers such as PICs. The timing functions here are a delay function and function that you poll to see if a set amount of time has elapsed.

The most basic timer feature I have seen is a global variable, or tick count, that is incremented every time a timer interrupt is fired. The problem here is if another piece of code interferes with this variable or if the timer interrupt fires during the read of the tick count value. The code below instead safely wraps the tick count and returns a structure. The code is written for the CCS  C compiler for PIC micros.

/*
  Timer.h
*/
#ifndef TIMING_H
#define TIMING_H

#include "defines.h"

typedef struct
{
 uint32 Duration;
 uint32 StartCount;
 uint32 EndCount;
} TimerInfo;

#inline
extern void OnTick(void);
extern uint32 GetTickCount(void);

extern void StartTimer(TimerInfo* timerInfo, uint16 duration);
extern bool HasTimerElapsed(TimerInfo* timerInfo);
extern void TimerWait(uint16 duration);


#ifdef _DEBUG
 void SetTickCount(unsigned int32 tickCount);
#endif

//Include guard
#endif



/*
        
 Timer.c

 Description:
 The aim of this code file is to implement a background timer in a safer manner by
 making the TickCount read-only.

 To perform a timed task:

 TimerInfo timerInfo; 
 StartTimer(&timerInfo, 42);
 while(!HasTimerElapsed(&timerInfo))
 {
   //perform some task
 }


*/
#include "Timing.h"

volatile static uint32 _TickCount = 0;

uint32 GetTickCount(void)
{
 uint32 nonVolatile;
 disable_interrupts(INT_TIMER0);
 nonVolatile = _TickCount;
 enable_interrupts(INT_TIMER0);
 return nonVolatile;
}


/*
 Call this method from the timer interrupt to increment the tick count.
*/
void OnTick(void)
{
 _TickCount++;
}


/*
 Call this method at the start of a timed task.
 Usage:
  TimerInfo timerInfo = StartTimer(42);
  while(!HasTimerElapsed(timerInfo)){//perform some task}

 Inputs:  duration - number of ticks to wait for
 Returns: TimerInfo - A structure holding the relevant timer information
*/
void StartTimer(TimerInfo* timerInfo, uint16 duration)
{
 timerInfo->Duration = duration;
 timerInfo->StartCount=GetTickCount();
 timerInfo->EndCount = timerInfo->Duration+timerInfo->StartCount;
}


/*
 Poll this method to determine if the timer has elapsed.
 Usage:
  TimerInfo timerInfo = StartTimer(42);
  while(!HasTimerElapsed(timerInfo)){//perform some task}

 Inputs:  TimerInfo - Timer information as returned by StartTimer()
 Returns: bool  - True timer has elapsed, false - timer has not elapsed

*/
bool HasTimerElapsed(TimerInfo* timerInfo)
{
 uint32 tickCount = GetTickCount();
 //Timer info uses uint32, but the logic still needs to be able to cope with overflow.
 if (timerInfo->EndCount >= timerInfo->StartCount)
 {
  return (tickCount>=timerInfo->StartCount && tickCountEndCount) ? false : true;
 }
 return (tickCount>=timerInfo->EndCount && tickCountStartCount) ? true : false;
}


/*
 Wait for the specified number of ticks
 Inputs: duration - number of ticks to wait
*/
void TimerWait(uint16 duration)
{
 TimerInfo timer;
 StartTimer(&timer, duration);
 while(!HasTimerElapsed(&timer)){}
}

#ifdef _DEBUG
 /*
  Allow unit tests to manipulate _TickCount
 */
 void SetTickCount(uint32 tickCount){ _TickCount=tickCount;}
#endif
The tick count is marked as volatile, this warns the compiler not to optimize the use of this variable and to always read from its memory location. You'll notice that I disable and then enable interrupts when reading the tick count. To increase the tick count you call OnTick() from your timer interrupt sub-routine, I've marked this function as inline to save doing the function call.

To use the code, you first need to get a TimerInfo which contains the start time, and then pass the TimerInfo to HasTimerElapsed() which returns true, the time has elasped, or false, the time has not elapsed. See my previous posts about C Type defines if you're wondering where the bool has come from.

You can easily port the code, but you will need to replace the #inline pre-processor and the disable/enable interrupt calls.

Embedded C, Defining Common Types

How do you write portable C code that you can use on any processor architecture or compiler and even unit test such code on a Windows PC? This is one problem I've been addressing over the last year or so as I've written firmware for several processor architectures  PICS, Renesas H8's and Infineon 166.

The first problem is that an int can be 1,2 or 4 bytes in size and it depends on the compiler, processor and OS. In this post I'll show how to use precisely defined types that you can use throughout your code so that you will not need to worry about the size of types.

Common types that you will use are signed and unsigned ints, so these will need to be defined and standardized:

Signed ints: sint8, sint16,sint32, sint64
Unsigned ints: uint8, uint16, uint32, uint64
For floating point I use, float32 and float64

The C language is missing the bool type, so I define this as well, which is great as I can now mix the embedded C code with the C++ unit test harness code running on my Windows PC. I also prefer returning a bool instead of error codes so as to keep things simple.

Here is an example of my defines.h that I use when writing C projects for PIC micro-controllers.


#ifndef DEFINES_H
#define DEFINES_H

#ifdef WIN32

typedef char   sint8;   // -128 T0 127
typedef unsigned char uint8;  // 0 TO 255
typedef signed short sint16;  // -32768 TO 32767 
typedef unsigned short uint16;  // 0 TO 65535
typedef long   sint32;  // -2147483648 TO 2147483647
typedef unsigned long uint32;  //0 TO 4294967295
typedef float   float32; //(1.4012984643248171e-45f) to(3.4028234663852886e+38f)
typedef double   double64; // 4.9406564584124655e-324 to 1.7976931348623158e+308

//A byte is a one byte unsigned integer
typedef unsigned char BYTE;
//A double word is a four byte unsigned integer
typedef unsigned long DWORD;
//A word is a two byte unsigned integer
typedef unsigned short WORD;

#else

typedef signed int   sint8;   // -128 T0 127
typedef unsigned int                    uint8;  // 0 TO 255
typedef signed long   sint16;  // -C32768 TO 32767
typedef unsigned long                   uint16;  // 0 TO 65535
typedef signed long long                sint32;  // -2147483648 TO 2147483647
typedef unsigned long long              uint32;  //0 TO 4294967295
typedef float    float32; //(1.4012984643248171e-45f) to(3.4028234663852886e+38f)

//A byte is a one byte unsigned integer - already defined in CCS compiler
//typedef unsigned int BYTE;
//A word is a two byte unsigned integer
typedef unsigned long WORD;
//A double word is a four byte unsigned integer
typedef unsigned long long DWORD;

typedef unsigned char   bool;
#define true    (bool)1
#define false    (bool)0


#endif

//C definition of null is (void *) 0, for C++ it is just 0
#ifndef NULL
 #ifdef __cplusplus
    #define NULL 0
 #else
    #define NULL ((void *) 0)
 #endif
#endif

//Include guard
#endif

In my future embedded C posts that I'll be using these types, eg sint16, in my example code.

Wednesday 24 October 2012

Android Scaled Images Tool

Android supports 4 screen types, extra high, high, medium and low density. Extra high density means that the screen has a higher number of pixels per inch than a lower density screen. If you have images in your app then you need to provide images for each screen type, so that the image size will remain consistent.

My approach to doing this is first create my extra high definition image and then resize it for the less dense screen types:

High Density - Reduce Image to 75% of the original size
Medium Density - Reduce Image to 50% of the original size
Low Density - Reduce Image to 37.5% of the original size




 I start with the top most image and then reduce it in size to create the other images. On your computer screen each image is becoming smaller, but on a Android phone with a low density display and a phone with a high density display will pick the right image so that to the user they appear the same physical size.

I've not found a tool yet on Eclipse to actually resize the images for me so I created my own. Its a .Net tool for Windows, you can download it from:

http://sites.google.com/site/pigdogbay/downloads

The tool is called AndroidScaledImages.msi

I've had a few issues with creating a shortcut in the users StartTo menu (a technical issue to do with advertised shortcuts being default in MS Setup). Anyhow you will need to create a short cut to the AndroidScaledImages.exe file in your Send To folder. To do this.


  1. Open the start menu
  2. Go to run / search
  3. Enter shell:sendto
  4. Now open a new explorer window
  5. Navigate to the program files\pig dog bay\Android Scaled Images
  6. Create a short cut to AndroidScaledImages.exe and drag it into your send to folder.
Once done, you can right click your extra high def image, send to, AndroidScaledImages.exe - shortcut
The high, medium and low density images will then be created in the same directory as the image you clicked. You then move each image into corresponding apps res/drawable folder, and then rename them all to the same name.

The tool is very simple and the source is below in case you want to role you own. If anyone has a better way of creating the lower density images,e.g. from Eclipse please let me know.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace AndroidScaledImages
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                return;
            }
            if (!File.Exists(args[0]))
            {
                return;
            }
            string filename = Path.GetFileNameWithoutExtension(args[0]);
            string path = Path.GetDirectoryName(args[0]);
            Bitmap bitmap = new Bitmap(args[0]);
            Bitmap high = ResizeImage(bitmap,0.75);
            Bitmap medium = ResizeImage(bitmap,0.50);
            Bitmap low = ResizeImage(bitmap,0.375);
            high.Save(Path.Combine(path,filename + "_h.png"),ImageFormat.Png);
            medium.Save(Path.Combine(path, filename + "_m.png"), ImageFormat.Png);
            low.Save(Path.Combine(path, filename + "_l.png"), ImageFormat.Png);

        }

        static Bitmap ResizeImage(Bitmap original, double ratio)
        {
            double w = (double)original.Width;
            double h = (double)original.Height;
            w = w * ratio;
            h = h * ratio;
            Bitmap resized = new Bitmap((int)w, (int)h);
            using (Graphics g = Graphics.FromImage((Image)resized))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(original, 0, 0, (int)w, (int)h);
            }
            return resized;    
        }


    }
}