diff --git a/TravelPost/AndroidManifest.xml b/TravelPost/AndroidManifest.xml
index 1a3538c..1bc5440 100644
--- a/TravelPost/AndroidManifest.xml
+++ b/TravelPost/AndroidManifest.xml
@@ -1,12 +1,36 @@
-
+ package="com.TwentyCodes.android.TravelPost" android:versionCode="0" android:versionName="0.0.0">
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TravelPost/gen/com/TwentyCodes/android/TravelPost/R.java b/TravelPost/gen/com/TwentyCodes/android/TravelPost/R.java
index d1fac70..84f27f2 100644
--- a/TravelPost/gen/com/TwentyCodes/android/TravelPost/R.java
+++ b/TravelPost/gen/com/TwentyCodes/android/TravelPost/R.java
@@ -21,6 +21,7 @@ public final class R {
public static final int hello=0x7f050000;
}
public static final class xml {
- public static final int travelpostwidgetinfo=0x7f040000;
+ public static final int settings=0x7f040000;
+ public static final int travelpostwidgetinfo=0x7f040001;
}
}
diff --git a/TravelPost/res/xml/settings.xml b/TravelPost/res/xml/settings.xml
new file mode 100644
index 0000000..f32953d
--- /dev/null
+++ b/TravelPost/res/xml/settings.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationReceiver.java b/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationReceiver.java
new file mode 100644
index 0000000..f6ecc4b
--- /dev/null
+++ b/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationReceiver.java
@@ -0,0 +1,71 @@
+/**
+ * LocationReceiver.java
+ * @date Jan 21, 2011
+ * @author ricky barrette
+ * @author Twenty Codes, LLC
+ */
+package com.TwentyCodes.android.TravelPost;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+/**
+ * The broadcast receiver that works with LocationService.java
+ * @author ricky barrette
+ */
+public class LocationReceiver extends BroadcastReceiver {
+
+ public static final String ACTION_UPDATE = "TwentyCodes.TravelPost.intent.action.LocationUpdate";
+ public static final String LOCATION_PARCEL = "location_parcel";
+ private static final String TAG = "LocationReceiver";
+ private WakeLock mWakeLock;
+
+ /**
+ * acquires a wakelock to prevent the device's cpu from sleeping
+ * @param context
+ * @author ricky barrette
+ */
+ private void acquireWakeLock(Context context) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mWakeLock.acquire();
+ }
+
+ /**
+ * called when this receiver receives a location update
+ * @param location
+ * @author ricky barrette
+ */
+ private void onLocationUpdate(Location location) {
+ //TODO something with the location i.e. report location to social services like twitter, ect...
+ removeWakeLock();
+ }
+
+ /**
+ * Called when there is a location update from the location service.
+ * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
+ * @author ricky barrette
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ acquireWakeLock(context);
+ if(intent.getParcelableExtra(LOCATION_PARCEL) != null){
+ Location location = intent.getParcelableExtra(LOCATION_PARCEL);
+ onLocationUpdate(location);
+ }
+ }
+
+ /**
+ * removes the wake lock if there is one held
+ * @author ricky barrette
+ */
+ private void removeWakeLock() {
+ if(mWakeLock.isHeld())
+ mWakeLock.release();
+ }
+
+}
diff --git a/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationService.java b/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationService.java
new file mode 100644
index 0000000..9fd021f
--- /dev/null
+++ b/TravelPost/src/com/TwentyCodes/android/TravelPost/LocationService.java
@@ -0,0 +1,227 @@
+/**
+ * LocationService.java
+ * @date Jan 21, 2011
+ * @author ricky barrette
+ * @author Twenty Codes, LLC
+ */
+package com.TwentyCodes.android.TravelPost;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+
+/**
+ * A service that will gather the user's location in the background, and report it via Broadcast once the location gathered has reached the
+ * @author ricky barrette
+ */
+public class LocationService extends Service implements LocationListener {
+
+ /**
+ * The desired accuracy in meters
+ */
+ private static final float DESIRED_ACCURACY = 6.0f;
+
+ /**
+ * Maximum running time in milliseconds
+ */
+ private final long MAX_RUN_TIME = 180000L;
+ public static final String TAG = "LocationService";
+ private LocationManager mLocationManager;
+ private WakeLock mWakeLock;
+ private Location mLocation;
+ private int mStartId;
+
+ /**
+ * this runnable will be qued when the service is created. this will be used as a fail safe
+ * @author ricky barrette
+ */
+ private Runnable mFailSafe = new Runnable() {
+ @Override
+ public void run(){
+ broadcastLocation();
+ }
+ };
+
+ /**
+ * a convince method for starting the service
+ * @param context
+ * @return a runnable that will start the service
+ * @author ricky barrette
+ */
+ public static Runnable startService(final Context context){
+ return new Runnable(){
+ @Override
+ public void run(){
+ Intent service = new Intent(context, LocationService.class);
+ context.startService(service);
+ }
+ };
+ }
+
+ /**
+ * a convince method for stopping the service
+ * @param context
+ * @return a runnable that will stop the service
+ * @author ricky barrette
+ */
+ public static Runnable stopService(final Context context){
+ return new Runnable(){
+ @Override
+ public void run(){
+ context.stopService(new Intent(context, LocationService.class));
+ }
+ };
+ }
+
+ /**
+ * broadcasts location to anything listening for updates,
+ * since this is the last function of the service, we call finish()u
+ * @author ricky barrette
+ */
+ private void broadcastLocation() {
+ if (mLocation != null) {
+ Intent locationUpdate = new Intent();
+ locationUpdate.setAction(LocationReceiver.ACTION_UPDATE);
+ locationUpdate.putExtra(LocationReceiver.LOCATION_PARCEL, mLocation);
+ sendBroadcast(locationUpdate);
+ stopSelf(mStartId);
+ }
+ }
+
+ /**
+ * (non-Javadoc)
+ * @see android.app.Service#onBind(android.content.Intent)
+ * @param arg0
+ * @return
+ * @author ricky barrette
+ */
+ @Override
+ public IBinder onBind(Intent arg0) {
+ // UNUSED
+ return null;
+ }
+
+ /**
+ * called when the service is created. this will initialize the location manager, and acquire a wakelock
+ * (non-Javadoc)
+ * @see android.app.Service#onCreate()
+ * @author ricky barrette
+ */
+ @Override
+ public void onCreate(){
+ mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+ PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mWakeLock.acquire();
+
+ /*
+ * que the fail safe runnable to kill the report location and kill it self after the MAX_RUN_TIME has been meet
+ */
+ new Handler().postDelayed(mFailSafe, MAX_RUN_TIME);
+ }
+
+ /**
+ * called when the service is destroyed.
+ * this will remove any wakelock or location service running, and register to be waken back up
+ * (non-Javadoc)
+ * @see android.app.Service#onDestroy()
+ * @author ricky barrette
+ */
+ @Override
+ public void onDestroy(){
+ mLocationManager.removeUpdates(this);
+ if(mWakeLock.isHeld())
+ mWakeLock.release();
+ }
+
+ /**
+ * (non-Javadoc)
+ * @see android.location.LocationListener#onLocationChanged(android.location.Location)
+ * @param location
+ * @author ricky barrette
+ */
+ @Override
+ public void onLocationChanged(Location location) {
+// Log.d(TAG, "got location +- "+ location.getAccuracy() +"m");
+ mLocation = location;
+ if(location.getAccuracy() <= DESIRED_ACCURACY){
+ broadcastLocation();
+ }
+ }
+
+ /**
+ * (non-Javadoc)
+ * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
+ * @param arg0
+ * @author ricky barrette
+ */
+ @Override
+ public void onProviderDisabled(String arg0) {
+ // UNUSED
+ }
+
+ /**
+ * (non-Javadoc)
+ * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
+ * @param arg0
+ * @author ricky barrette
+ */
+ @Override
+ public void onProviderEnabled(String arg0) {
+ // UNUSED
+ }
+
+ /**
+ * To keep backwards compatibility we override onStart which is the equivalent of onStartCommand in pre android 2.x
+ * @author ricky barrette
+ */
+ @Override
+ public void onStart(Intent intent, int startId) {
+ Log.i(TAG, "onStart.Service started with start id of: " + startId);
+ mStartId = startId;
+ startLocationService();
+ }
+
+ /**
+ * This method is called when startService is called. only used in 2.x android.
+ * @author ricky barrette
+ */
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.i(TAG , "onStartCommand.Service started with start id of: " + startId);
+ mStartId = startId;
+ startLocationService();
+ return START_STICKY;
+ }
+
+
+ /**
+ * (non-Javadoc)
+ * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
+ * @author ricky barrette
+ */
+ @Override
+ public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
+ // UNUSED
+ }
+
+ /**
+ * request periodic location updates from androids location services
+ * @author ricky barrette
+ */
+ private void startLocationService() {
+ mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
+ mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+ mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this);
+ }
+
+}
diff --git a/TravelPost/src/com/TwentyCodes/android/TravelPost/PostMortemReportExceptionHandler.java b/TravelPost/src/com/TwentyCodes/android/TravelPost/PostMortemReportExceptionHandler.java
index e1b8335..be15c1d 100644
--- a/TravelPost/src/com/TwentyCodes/android/TravelPost/PostMortemReportExceptionHandler.java
+++ b/TravelPost/src/com/TwentyCodes/android/TravelPost/PostMortemReportExceptionHandler.java
@@ -24,9 +24,13 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
/**
- * dont forget the manifest tag
- *
- * @author ricky
+ * The Twenty Codes, LLC Exception handler.
+ * This exception handler will generate an email with the stacktrace, cause, device & eviroment, and complete logcat
+ * to use create a field variable, and add the following lines to your onCreate()
+ * mExceptionReport.run();
+ Thread.setDefaultUncaughtExceptionHandler(mExceptionReport);
+ * Don't forget the manifest tag android.permission.READ_LOGS
+ * @author ricky barette
*/
public class PostMortemReportExceptionHandler implements UncaughtExceptionHandler, Runnable {
public static final String ExceptionReportFilename = "postmortem.trace";
diff --git a/TravelPost/src/com/TwentyCodes/android/TravelPost/TravelPost.java b/TravelPost/src/com/TwentyCodes/android/TravelPost/TravelPost.java
index f674deb..3988959 100644
--- a/TravelPost/src/com/TwentyCodes/android/TravelPost/TravelPost.java
+++ b/TravelPost/src/com/TwentyCodes/android/TravelPost/TravelPost.java
@@ -1,5 +1,42 @@
+/**
+ * TravelPost.java
+ * @date Jan 21, 2011
+ * @author ricky barrette
+ * @author Twenty Codes, LLC
+ */
package com.TwentyCodes.android.TravelPost;
-public class TravelPost {
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
-}
+/**
+ * Main activity for the Travel Post widget.
+ * This activity will be used to gather and store the users settings for the widget using shared_prefs
+ * @author ricky barrette
+ */
+public class TravelPost extends PreferenceActivity {
+
+ private PostMortemReportExceptionHandler mExceptionReport = new PostMortemReportExceptionHandler(this);
+ private static final String SETTINGS = "settings";
+
+ /**
+ * called when the activity is first created
+ * (non-Javadoc)
+ * @see android.preference.PreferenceActivity#onCreate(android.os.Bundle)
+ * @author ricky barrette
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ //start the exception handler
+ mExceptionReport.run();
+ Thread.setDefaultUncaughtExceptionHandler(mExceptionReport);
+
+ // set shared_prefs name
+ getPreferenceManager().setSharedPreferencesName(SETTINGS);
+
+ // load preferences xml
+ this.addPreferencesFromResource(R.xml.settings);
+ }
+
+}
\ No newline at end of file