Sudoku Forever

I’ve taken the Sudoku JavaScript game I created and ported it to an app for Android. Sudoku Forever is based on the same Sudoku solver described in my JavaScript article but with a few more improvements and optimizations. It is very fast consistently generating a new board between 200 and 500 milliseconds.


Here’s a screenshot: Sudoku Forever Screenshot

Sudoku Forever also features the ability to save the current game state whenever you close the app as well as Save Game slots so you can save the current game and come back to it later.


Here’s the Home Page for Sudoku Forever.
And of course the link to it on Google Play.

Let me know what you think and be sure to leave a rating and feedback on Google Play!

Poor-man's promo check for Android apps.

When I first created Baby’s First Game for Android I gave away a free promotional version. This promotional version was basically to get feedback from people before the real release. I wanted the app to only work for a limited time after which it would disable itself. I suppose I could have just released the full version without any limitations but I didn’t know how well (or poorly as it turns out) my app would do or how a free version floating around would affect it. Plus I wanted to see how one might create a time limited app anyway.


I created a single method called doPromoCheck() that stores the current install date in the app settings and checks them on every start up. I also added a check to alert the user once a day that the application was a promotional version and would expire in x number of days. This message I wanted shown only once a day as to not annoy the users. Here’s the method with some static class variables for configuration:

...
private static final String PROMO_DATE = "promoDate";
private static final String PROMO_DISPLAYED = "promoDisplayed";
private static final long DAYS_MILLIS = 24 * 60 * 60 * 1000;
private static final long PROMO_DURATION = DAYS_MILLIS * 30; // 30 days

private void doPromoCheck() {
  SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = prefs.edit();
  long now = System.currentTimeMillis();
  long exp = prefs.getLong(PROMO_DATE, now + PROMO_DURATION);
  editor.putLong(PROMO_DATE, exp);

  // check if the promo period has ended
  if(now > exp) {
    AlertDialog alertDialog;
    String ok = getResources().getString(R.string.label_ok);
    alertDialog = new AlertDialog.Builder(this)
        .setCancelable(false)
        .setPositiveButton(ok, new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int id) {
            finish(); // stops the app as soon as the dialog is dismissed.
          }
        }).create();
    String title = "Promo Version";
    alertDialog.setTitle(title);
    String msg = "This promotional version has expired. Please purchase the official version from Google Play.";
    alertDialog.setMessage(msg);
    alertDialog.show();
  } else {
    long disp = prefs.getLong(PROMO_DISPLAYED, now);

    // only display the dialog if it's been one day since the last time it was displayed
    if(now >= disp) {
      // save the next display time for one day from now.
      editor.putLong(PROMO_DISPLAYED, now + DAYS_MILLIS);
      AlertDialog alertDialog;
      String ok = getResources().getString(R.string.label_ok);
      alertDialog = new AlertDialog.Builder(this)
          .setCancelable(false)
          .setPositiveButton(ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              // do nothing
            }
      }).create();

      String title = "Promo Version";
      alertDialog.setTitle(title);
      long days = (exp - now) / DAYS_MILLIS;
      String msg = "This promotional version will expire in " + days + " days. Please consider purchasing the official version from Google Play.";
      alertDialog.setMessage(msg);
      alertDialog.show();
    }
  }

  editor.commit();
}


The first time this is run it calculates the expiration date and stores it in the private app settings. Each time it is run after, it pulls the expiration out of the app settings. To use this method in your app, put the call as the first thing in your main Activity onCreate() method:

   protected void onCreate(Bundle savedInstanceState) {
      doPromoCheck();
      ...
   }


That’s it. Your application will now only last for 30 days and will simply show the promotional period ended dialog after. Of course, the app can be uninstalled and reinstalled to reset the expiration but it’s annoying and probably not worth the hassle to most people.

Baby’s First Game

I’ve just launched Baby’s First Game for Android on Google Play. This is a game designed specifically for infants, toddlers and preschool age children. They will have fun learning about colors, shapes, numbers and letters. The skill levels are very customizable and can grow with your child.

This game was inspired by Baby Smash by Scott Hanselman and watching the games my own kids were interested in. Three mini-games provide a fun way to get familiar with and learn to identify colors, shapes, numbers and letters.

Just for Baby is targeted specifically at infants and young toddlers. It teaches action/reaction while familiarizing baby with colors and shapes. When baby touches the screen, a happy shape appears.

Find It! tests your child’s ability to identify colors, shapes, letters and numbers by picking them out of a group.

Pop It! is a fun way to work on your child’s hand/eye coordination while “popping” shapes as they fly across the screen. Baby’s First Game is and always will be Ad free. Baby’s First Game for Android is available now on Google Play:

Get it on Google Play 

java XML parsing: line 1, character 38, unable to switch the encoding

While working on a Java web application I was trying to import an XML file into a Microsoft SQL Server database table with an XML type column. Everything seemed to be OK except I was running into the following error:

java XML parsing: line 1, character 38, unable to switch the encoding

After much googling the consensus was that this error is raised because SQL Server stores XML in the XML type column using UTF-16 character encoding while the file I was trying to insert was UTF-8 encoded. So, I had to convert my input data from UTF-8 to UTF-16. My original code was doing this:

String str = new String(data);

The String class defaults to UTF-16 unless specified otherwise. However, to be sure I changed the above to:

String str = new String(data, "UTF-16");

Nope, didn’t work… Well, the documentation for the String constructor isn’t the greatest so maybe the encoding parameter is just used as a hint at what the input data is supposed to be. The behavior of this constructor when the given bytes are not valid in the given charset is unspecified. Not entirely clear… Just to be sure, I changed it to this:

String str = new String(data);
str = new String(str.getBytes("UTF-16"), "UTF-16");

Still no luck. Ok, how about using CharsetEncoder/Decoder

Charset utf8= Charset.forName("UTF-8");
Charset utf16= Charset.forName("UTF-16");
CharBuffer cb = utf8.decode(new ByteBuffer.wrap(data));
ByteBuffer outputBuffer = utf16.encode(cb);
String str = new String(outputBuffer.array(), "UTF-16");

Still no. Well, looking at the XML document itself I see the XML declaration is specifying the encoding attribute as encoding="UTF-8". I delete it and finally it works. So, even though I changed the input to the correct encoding, the fact that this attribute was specified in the XML document itself caused SQL Server to complain. Ok fine… However, I ended up removing all the encoding conversion code that I had been playing with and reverted back to the original code:

String str = new String(data);

Tried the import again but without the encoding attribute and it still works. SQL server will do the conversion for you if the encoding attribute isn’t specified. It won’t touch it however if it is. So, options now are, 1) either remove the encoding attribute altogether, or 2) make sure the file is UTF-16 encoded with the encoding attribute set accordingly.

Error creating JAXB bindings

While creating some JAXB bindings from some XSD files I have I ran into an error like the following:

$ xjc -p com.foo.data.import foo.xsd -d out
[ERROR] The package name 'com.foo.data.import' used for this schema is not a valid package name.

What is the cause of this error? That would be the keyword “import” in the package name. You just can’t use a reserved word in a package name no matter how much you really want to!

Broken JDK 7 Installer

Ok, how broken is this? I recently rebuilt my development machine and ran into this goodie while reloading my software development tools. I needed the Java JDK so, like any normal person, I went to Oracle’s website and downloaded the shiny new JDK 7 and Java EE 6 bundle. After running the downloaded installer I am confronted by this gem:

Error: Could not find the required version of the Java(TM) 2 Runtime Environment in'(null)'.

Huh? So doing some googling I see one suggestion that the download might have been incomplete so I download it again. No good. I found a post on Stack Overflow from someone trying to uninstall Java EE 6. The “fix” for that problem is that the uninstaller is written in Java so it needs a Java VM to run. Seriously? Yeah, so I try it. I install the basic Java 6 Runtime and hey! All fixed! Um, Oracle… You know that the JDK comes with its own runtime right? Now I have 2 runtimes installed… Your bundle installer couldn’t install its required runtime before launching the JDK installer? Even if you couldn’t be bothered to do something like that, how about a more descriptive message instead of your buggy “couldn’t find it in ‘(null)'” crap? I mean, I’m expecting the runtime to be included in the bundle so this tells me nothing about needing it to be already installed. It just looks like I got a corrupted download or just crap software.

Update 10/20/12

Ok, so it’s been a year since this original post and Oracle still hasn’t fixed anything. Not only that, I discovered a new issue, probably what one commenter below had run into but I didn’t see it at the time. I got a shiny new laptop the other day. 64-bit with Windows 7 Professional. So, setting up my tools I initially tried to install the JDK deliberately without first installing the runtime just to see if this issue has actually been fixed. It hasn’t. What I did discover is just as WTF worthy as the above problem. Since I got a hot new 64-bit computer, let’s install the 64-bit JDK. Ok cool. I run the installer and it didn’t work as I expected. So, I download the Java 7 runtime. Still doesn’t work. Ok, I used the Java 6 runtime before so I try that. Nope. WTF? Ok, I’m trying the 64-bit runtimes, surely they should work. I download the 32-bit Java 7 runtime. And it works! Seriously? WTF? So, you can’t install the 64-bit JDK with the 64-bit Java runtime? The 64-bit JDK installer only works with the 32-bit runtime. Not only is this not documented anywhere on Oracle’s website the error message presented is still the same worthless uninformative message.

]]>