Thursday, July 1, 2010

Location-aware Twitter search app for Android


I just wrote and published a new free app for android. It is called Locobird and a chunk of the code is below. It uses your location to search twitter around you. What's new about this app is that it uses the Clearwire Location Platform to get your rough location when you are connected to the 4G network. Now you are wondering, how do I connect to that? Simple, you get an EVO.









This app uses the new static map API from Google and a java Twitter API from http://www.winterwell.com/software/jtwitter.php

Here's the code for using the Clearwire Location Platform (CLP)

package com.thehopemachine.locobird;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Date;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import org.json.JSONStringer;

import android.location.Location;
import android.util.Log;

public class WimaxLocationProvider {

private static String CLP_ADDRESS = "http://testlocation.clearwire-wmx.net:8000/json/";
private static Long STALE = 60000l; //one minutes worth of milliseconds
private static String HOST = "host";
private static String VERSION = "version";
private static String VERSION_VAL = "1.1.0";
private static String LATITUDE = "latitude";
private static String LONGITUDE = "longitude";
private static String ACCURACY = "accuracy";
private static String LOCATION = "location";
private static String ERROR = "error";
private static String QUERYARG = "/?app_id=";
private Location mLastFix = null;
public static String WIMAX = "the Clear 4G Network";
private String mHost = null;
private String mAppID = null;
private Date mLastCall = null;
public WimaxLocationProvider (String host, String appID)
{
mHost = host;
mAppID = appID;
}
public Location getLocation() throws Exception
{
//www.example.com/?app_id=freiu4898fhjrh4yshefheoiuhr
//do we have a last fix? is it still good?
String hostValue = mHost + QUERYARG + mAppID;
if (mLastFix != null && !isStale())
{
Log.d("locobird", "returning last fix");
return mLastFix;
}
//now test if called too quick
if (mLastCall != null && (new Date().getTime() - mLastCall.getTime() <= Locobird.SPURIOUS_FILTER))
{
//this implies we've been getting errors since we have no last fix but do have a last call
throw new CLPException("unable to provide location from CLP");
}
//else get a fix
Location l = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost post = new HttpPost(CLP_ADDRESS);
HttpResponse response = null;
HttpEntity entity = null;
InputStream input = null;
//create a json request (basic)
String request = null;
try
{
request = new JSONStringer().object().key(HOST).value(hostValue).key(VERSION).value(VERSION_VAL).endObject().toString();
post.setEntity(new StringEntity(request));
JSONObject locationData = null;
StringBuffer data = new StringBuffer(512);
//send the request (POST it)
response = httpclient.execute(post);
entity = response.getEntity();
//get IO stream from entity and turn into JSON object
input = entity.getContent();
//look at response code
if (response.getStatusLine().getStatusCode() >= HttpURLConnection.HTTP_BAD_REQUEST)
{
//400 bad request, 404 not found, 500 server error ,etc
//do not try to parse json- will cause error
l = null;
}
else if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK)
{
byte[] buffer = new byte[512];
int x = 0;
while ((x = input.read()) != -1)
{
data.append((char)x);
}
//create location from the response
Log.d("locobird", "CLP response= " + data.toString());
locationData = new JSONObject(data.toString());
//test for location object in the json (if you just query you will get an exception)
if (!locationData.has(LOCATION))
{
//get the error object and examine it for cause
//{"error":"server error"}
if (locationData.has(ERROR))
{
String errorCause = locationData.getString(ERROR);
//could return error message in a bundle or just throw an error
throw new CLPException(errorCause);
}
else
{
//neither location nor error so a clp problem
throw new CLPException("Missing location and error objects from CLP response");
}
}
else
{
JSONObject jsonLocation = locationData.getJSONObject(LOCATION);
//we have a good location object from the CLP
//load the location object with the locationData
l = new Location(WIMAX);
l.setLatitude(jsonLocation.getDouble(LATITUDE));
l.setLongitude(jsonLocation.getDouble(LONGITUDE));
l.setAccuracy((float) jsonLocation.getDouble(ACCURACY));
}
}
}
finally
{
//ensure call time is recorded
mLastCall = new Date();
try
{
if (entity != null)
{
entity.consumeContent();
input.close(); //may not be needed
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//can return null in case of error. if this happens, do not update the fix- keep old one.
if (l == null)
{
throw new CLPException("unable to provide location from CLP");
}
else
{
mLastFix = l;
mLastFix.setTime(new Date().getTime());
Log.d("locobird", "returning new fix");
return l;
}
}
//if time since last fix exceed STALE, the fix is stale so get a new one.
private boolean isStale()
{
return ((new Date().getTime() - mLastFix.getTime()) > STALE);
}
}


For checking if you are on 4G, here's the code.

public static boolean onWimax(ConnectivityManager cm)
{
NetworkInfo info = cm.getActiveNetworkInfo();
if (info == null)
{
//no active network=
return false;
}
int networkType = cm.getActiveNetworkInfo().getType();
//type = 6 means wimax

if((networkType == 6) && (cm.getActiveNetworkInfo().getDetailedState().compareTo(DetailedState.CONNECTED)) == 0)
{
return true;
}
else
{
return false;
}
}
You will need these imports:

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;


No comments:

Post a Comment

Thanks for your feedback!