Tuesday, October 13, 2009

Google Health Viewer

I am preparing to take on the task of writing a Google Health Viewer for Android phones. I have done a bit of background reading, but still not enough to launch into the project. What I'm wondering, by publishing this post, is whether there are like-minded collaborators out there, also interested in such a product.

Firstly, I should state that it's my wish to make this an open-source project, and, like the Google Health service itself, be a free app.

I know a lot of folk have concerns about Digital Medical Records, but surely the usefulness, and potentially life-saving benefits to come from it outweigh whatever overly sensitive, and largely unfounded anxieties we have about privacy?

So, if anyone's interested just bung a comment to this post. Would be interested in knowing if things like useful wrapper classes on the Google Data API's are available? Or even ready-made classes for Google Health data entities themselves?

Wednesday, September 2, 2009

Xml Handling in Android

In recent years I have mostly coded in C#, so on entering the wonderful world of Android and polishing up my Java skills, I find I sorely miss some of the niftier C# language elements like indexers and properties and their proliferation throughout various .NET frameworks classes.

When it came to querying/modifying XML in Android, I found it handy to write a handful of helper methods which achieve the equivalents of the below in C#:


XmlElement XmlNode[string name]; (get)
string XmlNode.InnerText; (get)
string XmlNode.InnerText; (set)
string XmlNode.OuterText; (get)


Also, note a solution to the very annoying org.w3c.dom.Node.setNodeValue(String) problem/workaround in setInnertext().

Enjoy:



import java.io.IOException;

import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlSerializer;

/**
* A class containing a collection of helper methods for common Xml node navigation/query
*
* @author Scott Powell
*/
public class XmlUtils
{
public static Element getChildByName(Element e, String name)
{
NodeList l = e.getChildNodes();
if (l == null || l.getLength() == 0)
return null; // not found

for (int i = 0; i < l.getLength(); i++)
{
Node n = l.item(i);
if ((n instanceof Element) && n.getNodeName().equals(name))
return (Element)n;
}
return null; // not found
}

public static String getInnerText(Element e)
{
NodeList l = e.getChildNodes();
if (l == null || l.getLength() == 0)
return ""; /// empty

int idx = 0;
while (idx < l.getLength())
{
if (l.item(idx).getNodeType() == Node.TEXT_NODE)
return l.item(idx).getNodeValue();
idx++;
}
return ""; // no #text node found, so return empty string
}

public static void setInnerText(Element e, String val)
{
NodeList l = e.getChildNodes();
if (l != null && l.getLength() > 0)
{
int idx = 0;
while (idx < l.getLength())
{
Node n = l.item(idx);
if (n.getNodeType() == Node.TEXT_NODE)
{
//n.setNodeValue(val); // this isn't changing value!!
Node text = e.getOwnerDocument().createTextNode(val);
e.replaceChild(text, n);
return;
}
idx++;
}
}
// no #text Node, so create one
Node text = e.getOwnerDocument().createTextNode(val);
e.appendChild(text);
}

public static void writeElementTo(Element e, XmlSerializer s) throws IOException
{
s.startTag("", e.getNodeName());
if (e.hasAttributes())
{
NamedNodeMap m = e.getAttributes();
for (int i = 0; i < m.getLength(); i++)
{
Node n = m.item(i);
s.attribute("", n.getNodeName(), n.getNodeValue());
}
}
if (e.hasChildNodes())
{
NodeList kids = e.getChildNodes();
for (int i = 0; i < kids.getLength(); i++)
{
Node n = kids.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE)
writeElementTo((Element)n, s); // recursively write child element
else if (n.getNodeType() == Node.TEXT_NODE)
{
s.text(n.getNodeValue());
}
}
}

s.endTag("", e.getNodeName());
}
}

Auto-repeat Buttons in Android

To my surprise there doesn't seem to be an attribute with the standard android.View.Button class to make it auto-repeat while the Button is pressed. I've seen this behaviour in the DatePicker dialog, so assumed the behaviour is standard. Well, unless I'm going blind and just missed it, I went and wrote my own AutoRepearButton class.

For the Android fans out there, here is the source:


package com.spleenware;

import java.util.TimerTask;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;

/**
* Surprisingly, an AutoRepeatButton doesn't seem to be in the standard Android View frameworks.
* So, simple implementation here. When Button is held down its onClickListener is called on a timer.
*
* @author Scott Powell
*/
public class AutoRepeatButton extends Button
{
public AutoRepeatButton(Context c)
{
super(c);
}

/**
* Constructor used when inflating from layout XML
*/
public AutoRepeatButton(Context c, AttributeSet attrs)
{
super(c, attrs);
}

/**
* TODO: These could be made variable, and/or set from the XML (ie. AttributeSet)
*/
private static final int INITIAL_DELAY = 900;
private static final int REPEAT_INTERVAL = 100;

private TimerTask mTask = new TimerTask()
{
@Override
public void run()
{
if (isPressed())
{
performClick(); // simulate a 'click'
postDelayed(this, REPEAT_INTERVAL); // rinse and repeat...
}
}
};

@Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
postDelayed(mTask, INITIAL_DELAY);
else if (event.getAction() == MotionEvent.ACTION_UP)
removeCallbacks(mTask); // don't want the pending TimerTask to run now that Button is released!

return super.onTouchEvent(event);
}

}