Archive for February 2012

Android Beer timer Widget

A friend of mine said he wanted a beer app for the Android, really what’s that ? It goes something like this, a beer glass on your Android desktop. The beer glass fills up from 9am to 5pm, once it’s full, well then it’s time to stop working and go out for a beer. On the weekends the glass is always full of course. This would have to be a widget on the desktop so the image / icon can be changed on a timer through the day. Since I hadn’t written an Android widget before, I told my friend, no problem I will write it for you.

Lets declare the widget in the manifest, the service and the alarm receiver as well.

<receiver android:name=“.FxBeerWidget” android:label=“Beer time widget”>
  <intent-filter>
    <action android:name=“android.appwidget.action.APPWIDGET_UPDATE” />
  </intent-filter>
  <meta-data android:name=“android.appwidget.provider” android:resource=“@xml/beerwidgetlayout” />
</receiver>
<service android:name=“.CxUpdateWidgetService” />
<receiver android:name=“.CxBeerAlarmReceiver” />

Then in the AppWidgetProvider we use AlarmManager to update our receiver

// Setup receiver that will call the widgetService     
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent2 =  PendingIntent.getBroadcast(context, 0,
      new Intent(context, CxBeerAlarmReceiver.class),  PendingIntent.FLAG_CANCEL_CURRENT);
// Use inexact repeating which is easier on battery (system can phase events and not wake at exact times)
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 500, (60*1000), pendingIntent2);

Note that you have to be mindful of the resources you are using and use a long interval. If the person using the phone is playing a game for example when the timer goes off. You do not want to take much resources in order for his game to keep playing smoothly. In our case it’s a simple check and a quick update of a icon if needed.

The CxBeerAlarmReceiver is a BroadcastReceiver which when woken up will start the CxUpdateWidgetService which is a IntentService. The CxUpdateWidgetService will take care of updating the widgets.

public static void updateAllWidgets(Context context)
{
  //
  final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
  final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, FxBeerWidget.class));

  // Remote view for the widget
  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.beerwidget );
       
  // Setup the beer main Activity as Intent
  Intent beerIntent = new Intent();
  beerIntent.setClass( context, FxMain.class);
  beerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  // Setup pending intent, when widget clicked show main screen
  PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, beerIntent, 0);
  views.setOnClickPendingIntent(R.id.Widget, pendingIntent);
        
  // Time status
  int iCurrentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
  // Format it in clock like format, leading zero
  views.setTextViewText( R.id.lbStatus, CxUtil.getTimeString() );
       
  // Update image only if needed
  int plusNum = whichIcon( iCurrentHour);
  CxLog.d( CxLog.TOKEN, “updating beer image, currhour=” + iCurrentHour + “, plusNum=” + plusNum   );
       
  // Set the current image
  views.setImageViewResource( R.id.widgetImage, R.drawable.beer72_0  + plusNum );
       
  // Associate the update views – Loop all id’s
  for(int i=0; i<appWidgetIds.length; ++i)
     AppWidgetManager.getInstance(context).updateAppWidget( appWidgetIds[i], views );
}

Note that the user can have more than more widget running, there could be one on each desktop, etc. The for loop will take care of that and update all of the widgets. Another cotcha is that you will have to set the click intent for the widget each time the update function is called. Otherwise it will get disconnected from the widget and clicking the widget will not open the FxMain screen.

Here is the Widget if you like to download and install on your Android – BeerTimeWidget

Here is how it looks in action.

Java log4J

I had the need to log from a java project I just created. Never used log4J before but heard good things. Man do I love it when things are simple and that’s just what log4J is. Download and extract the jar, in my case log4j-1.2.16.jar add it to your classpath and your off to the races. When reading the install document, they have what you need to get up and running ASAP a small HelloWorld that will get you going.

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
   
public class Hello
{
      private static final Logger logger = Logger.getLogger(Hello.class);
      public static void main(String argv[])
      {
        BasicConfigurator.configure();
        logger.debug(“Hello world.”);
        logger.info(“What a beatiful day.”);
      }
}

Create the file from the sample and compile
> javac Hello.java
and run it
> java Hello

It will give the following output
0 [main] DEBUG Hello – Hello world.
6 [main] INFO Hello – What a beatiful day.

Yes, super simple, of course it has all the bells and whistles you might need. Like logging just for a specific class or just at a certain level, log to file etc, etc,

UPDATE
Then you can create xml file and configure the appenders from there, below is a sample of console appender and then a file appender. To set it in code, you can use the following.

PropertyConfigurator.configureAndWatch( “log4j_config.xml” );

That will instruct log4J to monitor your configuration file. If you want to change the configuration on the fly all you need to do is to change your configuration file, log4J checks for changes every 60 seconds. You can also call with additional parameter setting your own frequency.

# Set root logger level and appenders
log4j.rootLogger=INFO, console, rollingFile

# Console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss,SS} %-4r [%t] %-5p %c %x – %m%n

# Rolling file appender
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=mylog.log
log4j.appender.rollingFile.MaxFileSize=5MB
log4j.appender.rollingFile.MaxBackupIndex=20
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss,SS} %-4r [%t] %-5p %c %x – %m%n

PostgreSQL geo locations with PostGIS

I been playing with some geo location data. Naturally when working with the data one needs to save it to a database for later retrieval and selection. If you happen to be using Postgres your in luck. You can add the PostGIS extension that will make your database OpenGIS compatible.
The most important thing is to have geo location aware database when dealing with geo data. That means that you can select objects using proximity right out of the database. It makes easy to figure out how far away different locations are, what are the nearest locations etc. If you don’t have geo location aware database you would have to figure out the proximity in code. Of course that would mean a lot of calculations and CPU cycles.

How I set it up on my Ubuntu / Mint linux box. First install PostGIS on the box then you want to add it to your database as below.

createlang plpgsql yourdatabase
cd /usr/share/postgresql/8.4/contrib/postgis-1.5
psql -d yourdatabase -f postgis.sql
psql -d yourdatabase -f spatial_ref_sys.sql

Then make sure PostGIS has been added to the database.

SELECT PostGIS_full_version()
1.5 USE_GEOS=1 USE_PROJ=1 USE_STATS=1

Couple examples of usage.

To see how far away from my place ( Boulder ) some locations in the database are.
SELECT Distance(geom, SetSRID(MakePoint( 40.0150, –105.2705 ),4326)) FROM location_geo;
Then get the five closest ones to my place
SELECT * FROM location_geo ORDER BY distance(geom, SetSRID(MakePoint( 40.0150, –105.2705 ),4326)) LIMIT 5;

You can even set boundaries, use polygons etc.