Using layout include tag with Location proof of concept
I’ve been prototyping some code using the location api and not only have I learned some new things about this but also worked in the layout ‘include’ tag to minimize the amount of redundency in the layout file, and the Android Java code. Include allows you to include one layout file in another, there’s an article about it on the Android dev site. One minor speed bump I ran into was that I didn’t see an immediate way to access the resuseable portion of the layout file via a findById call. After a little hacking around, the answer was pretty easy.
I created a subclass in my main Android Activity which accepts a View as one of the arguments to it’s constructor. This View instance points to the “included” layout, for example the code in onCreate of the Activity could look like the following where there subclass is LayoutWidget.
LayoutWidget widget = new LayoutWidget( this.findViewById( R.layout.included_widget ) );
This assumes that the layout file for the Activity contains something like the following entry
<include android:id='@+id/included_widget' layout='@layout/widget_layout_file'/>
And that there is another Android layout resource called widget_layout_file.xml. If the widget_layout_file.xml layout contained the following element
<TextView android:id="@+id/title_txvw style="@style/BaseTxvw"/> <TextView android:id="@+id/fld1_txvw style="@style/BaseTxvw"/>
Then the constructor of LayoutWidget could look like
public LayoutWidget( View vw )
{
TextView titleTxvw = vw.findById( R.id.title_txvw );
TextView fld1Txvw = vw.findById( R.id.fld1_txvw );
}
I’ve included my prototype below…it’s a little rough (sorry about the indenting) but I think it rounds out the story a little more. I didn’t include the entire layout files since they’re a pain to format correctly ( I need to see if there is a WordPress xml paste widget thingy ). Don’t forget to add the permissions to your AndroidManifest.xml file for COURSE and FINE locations.
public class LocSandbox extends Activity
{
private Handler handler = new Handler(); private LocationManager _locMgr;
private LocationWidget _gpsWidget;
private LocationWidget _netWidget;
private LocationListener _gpsLocLstr;
private LocationListener _netLocLstr;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_locMgr = (LocationManager)getSystemService(LOCATION_SERVICE);
// assign the views used to show the location information
_gpsWidget = new LocationWidget( findViewById( R.id.gps_form ), handler );
_gpsWidget.setTitle( "GPS Widget" );
_netWidget = new LocationWidget( findViewById( R.id.net_form ), handler );
_netWidget.setTitle( "Network Widget" );
_gpsLocLstr = new WidgetLocationListener( _gpsWidget );
_netLocLstr = new WidgetLocationListener( _netWidget );
// get the last known location from the location providers
Location loc;
loc = _locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if ( loc != null )
{
_netWidget.updateLocation(loc);
}
loc = _locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if ( loc != null )
{
_gpsWidget.updateLocation(loc);
}
}
// helper method to geocode location
private List<address> geocode( Location loc )
{
List<address> addresses = null;
Geocoder gc = new Geocoder( this, Locale.getDefault() );
try {
addresses = gc.getFromLocation( loc.getLatitude(), loc.getLongitude(), 10 );
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
@Override
protected void onResume() {
super.onResume();
// start listening for new locations
registerListeners();
}
@Override
protected void onPause() {
super.onPause();
// make sure to unregister!
_locMgr.removeUpdates( _gpsLocLstr );
_locMgr.removeUpdates( _netLocLstr );
}
private void registerListeners()
{
_locMgr.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 2000, 10, _netLocLstr );
_locMgr.requestLocationUpdates( LocationManager.GPS_PROVIDER, 2000, 10, _gpsLocLstr );
}
// class to manage the ui views/widgets
class LocationWidget
{
private Handler _handler;
private TextView _titleTxvw;
private TextView _timeTxvw;
private TextView _latTxvw;
private TextView _lngTxvw;
private TextView _accuracyTxvw;
private TextView _speedTxvw;
private TextView _localeTxvw;
private TextView _statusTxvw;
private Location _lastLoc;
public LocationWidget( View vw, Handler handler )
{
_handler = handler;
_titleTxvw = (TextView)vw.findViewById( R.id.title );
_timeTxvw = (TextView)vw.findViewById( R.id.time );
_latTxvw = (TextView)vw.findViewById( R.id.lat );
_lngTxvw = (TextView)vw.findViewById( R.id.lng );
_accuracyTxvw = (TextView)vw.findViewById( R.id.accuracy );
_speedTxvw = (TextView)vw.findViewById( R.id.speed );
_localeTxvw = (TextView)vw.findViewById( R.id.locale );
_statusTxvw = (TextView)vw.findViewById( R.id.status );
_lastLoc = null;
}
public void setTitle( final String txt )
{
_handler.post( new Runnable() {
@Override
public void run() {
_titleTxvw.setText( txt );
}
});
}
public void updateStatus( final String status )
{
_handler.post( new Runnable() {
@Override
public void run() {
_statusTxvw.setText( status );
}
});
}
public void updateLocation( final Location location )
{
handler.post( new Runnable() {
@Override
public void run()
{
if ( _lastLoc != null )
{
double time = ( location.getTime() - _lastLoc.getTime() ) / 1000;
_timeTxvw.setText( "Updated: " + Double.toString( time ) + " sec" );
}
else
{
_timeTxvw.setText( "Updated: ---- " );
}
_latTxvw.setText( "Lat: " + location.getLatitude() );
_lngTxvw.setText( "Lng: " + location.getLongitude() );
_accuracyTxvw.setText( "Accuracy: " + location.getAccuracy() );
_speedTxvw.setText( "Speed: " + location.getSpeed() );
List<address>addresses = geocode(location);
if ( addresses != null && addresses.size() >= 1 )
{
_localeTxvw.setText( addresses.get(0).getLocality() );
}
_lastLoc = location;
}
});
}
}
// implementation of location listener to interface with LocationWidget
// assigned to specific location provider
class WidgetLocationListener implements LocationListener
{
private LocationWidget _widget;
public WidgetLocationListener( LocationWidget widget )
{
_widget = widget;
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
_widget.updateStatus( "Status: " + status );
}
@Override
public void onProviderDisabled(String provider)
{
_widget.updateStatus( "Status: disabled provider" );
}
@Override
public void onProviderEnabled(String provider)
{
_widget.updateStatus( "provider enabled" );
}
@Override
public void onLocationChanged(Location location)
{
_widget.updateLocation( location );
}
}
}
The layout file for the activity main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include android:id="@+id/gps_form" layout="@layout/location_widget"/>
<include android:id="@+id/net_form" layout="@layout/location_widget"/>
</LinearLayout>
location_widget.xml file
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView style="@style/LocText" android:id="@+id/title" android:background="@color/translucent_white" android:paddingBottom="2px"/> <TextView android:id="@+id/lat" style="@style/LocText"/> <TextView android:id="@+id/lng" style="@style/LocText" android:paddingBottom="5px"/> <TextView android:id="@+id/time" style="@style/LocText"/> <TextView android:id="@+id/accuracy" style="@style/LocText"/> <TextView android:id="@+id/speed" style="@style/LocText"/> <TextView android:id="@+id/locale" style="@style/LocText"/> <TextView android:id="@+id/status" style="@style/LocText"/> </LinearLayout>

July 1st, 2010 at 4:14 pm
[…] (more…) All, Programming […]