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