init commit

Change-Id: Ib96d43f22db2bdf360d1d1e0693f6aa5e3aa50ab
This commit is contained in:
2012-02-03 10:51:05 -05:00
commit 202fa24d8d
25 changed files with 1919 additions and 0 deletions

7
DroidFinder/.classpath Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

33
DroidFinder/.project Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DroidFinder</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.TwentyCodes.android.DroidFinderFull"
xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.0.4" android:versionCode="6">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar">
<uses-library android:name="com.google.android.maps"/>
<activity android:label="@string/app_name" android:name="DroidFinder">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:process=":remote" android:name="SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<!-- activities for tab activity -->
<activity android:name=".MyMapActivity"/>
<activity android:name=".SettingsActivity"/>
</application>
<uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

View File

@@ -0,0 +1,2 @@
# Project target.
target=android-15

3
DroidFinder/lint.xml Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

@@ -0,0 +1,11 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=Google Inc.:Google APIs:15

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
DroidFinder/res/drawable/user.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#505050">
<!-- first we attach this table to the top of the screen
this table layout is used to display the current distance from car and the current GPS accuracy
by setting the TableLayout background is black and the table rows are grey. and then adding a margin between the 2 rows,
we get a devider line drawn -->
<TableLayout
android:id="@+id/table"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0"
android:background="#000000">
<!-- distance display -->
<TableRow
android:background="#505050"
android:layout_marginBottom="2dip">
<TextView
android:layout_column="0"
android:id="@+id/tvDistance"
android:text="Distance"
android:enabled="false"
android:textSize="22sp"
android:gravity="left"
android:textColor="#FFFFFF"
android:textStyle="bold"
/>
<TextView android:layout_column="1"
android:id="@+id/tvDistance2"
android:gravity="right"
android:text="0"
android:enabled="false"
android:textColor="#FFFFFF"
android:textSize="26sp"
/>
</TableRow>
<!-- accuracy display -->
<TableRow android:background="#505050">
<TextView android:layout_column="0"
android:id="@+id/tvAccuracy"
android:text="Accuracy"
android:enabled="false"
android:textSize="22sp"
android:gravity="left"
android:textColor="#FFFFFF"
android:textStyle="bold"/>
<TextView android:layout_column="1"
android:id="@+id/tvAccuracy2"
android:gravity="right"
android:text="0"
android:enabled="false"
android:textColor="#FFFFFF"
android:textSize="26sp"/>
</TableRow>
</TableLayout>
<!-- after the table we draw the mapview
warren debug key
0fQa27WZuSpscM1yDbnjrDOPs3rgB78Sc8vWsaA
ricky debug api key
0rKmsWMM0D-Ii4Y4GcF-0jomwFM4YYOyLVnH0vw
twenty codes api key
0rKmsWMM0D-K15bEM_kwabPbNhsn4dp4rcq2q5Q
-->
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="0rKmsWMM0D-Ii4Y4GcF-0jomwFM4YYOyLVnH0vw"
android:layout_below="@id/table"
android:layout_alignParentBottom="true"/>
</RelativeLayout>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp" />
</LinearLayout>
</TabHost>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="layers">
<item>Satellite View</item>
<item>Map View</item>
</string-array>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="unit">
<item>Standard</item>
<item>Metric</item>
</string-array>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, DroidFinder!</string>
<string name="app_name">Droid Finder</string>
</resources>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Locating Options">
<CheckBoxPreference
android:title="Enable"
android:summary="Enable Transmitting phone's location though SMS messages"
android:defaultValue="false"
android:key="locate_enabled"
/>
<EditTextPreference
android:summary="locate"
android:defaultValue="locate"
android:title="Pass Phrase"
android:key="locate_pass"
android:dependency="locate_enabled" />
</PreferenceCategory>
<PreferenceCategory
android:title="Locking Options">
<CheckBoxPreference
android:title="Enable"
android:summary="Enable Locking the phone remotely though SMS messages"
android:defaultValue="false"
android:key="lock_pattern_enabled" />
<EditTextPreference
android:summary="lock"
android:defaultValue="lock"
android:title="Pass Phrase"
android:key="lock_pattern_pass"
android:dependency="lock_pattern_enabled"/>
</PreferenceCategory>
<PreferenceCategory
android:title="Map Settings">
<CheckBoxPreference
android:title="Stay Awake"
android:summary="Prevent the phone from sleeping"
android:defaultValue="false"
android:key="stay_awake" />
<ListPreference
android:title="Measurement Unit"
android:summary="Standard"
android:key="measurement_unit"
android:entries="@array/unit"
android:entryValues="@array/unit"/>
<ListPreference android:dialogTitle="Layers"
android:entryValues="@array/layers"
android:entries="@array/layers"
android:key="layers"
android:title="Layers"></ListPreference>
</PreferenceCategory>
<PreferenceCategory
android:title="System Settings">
<Preference
android:title="Back Up"
android:summary="Backs up current system settings that could be modified"
android:key="backup"
/>
<Preference
android:title="Restore"
android:summary="Restores system settings that were changed, from the backup"
android:key="restore"
/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,53 @@
package com.TwentyCodes.android.DroidFinderFull;
import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TabHost;
/**
* this is the main class for the application, it is responsible for displaying the main tab layout that will display the map and the settings
* pages.
*
* this application will lock the phone, transmit the phones location though SMS messages, set the ringtone stream to max,
* dim the phones display to minimum, and/or ring for a preset period of time based on a designated string received by SMS
* @author ricky barrette
*/
public class DroidFinder extends TabActivity{
private PostMortemReportExceptionHandler mExceptionReport = new PostMortemReportExceptionHandler(this);;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
mExceptionReport.run();
Thread.setDefaultUncaughtExceptionHandler(mExceptionReport);
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
TabHost tabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Resusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, MyMapActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("map").setIndicator("Map").setContent(intent);
// res.getDrawable(R.drawable.ic_tab_artists))
tabHost.addTab(spec);
intent = new Intent().setClass(this, SettingsActivity.class);
spec = tabHost.newTabSpec("settings").setIndicator("Settings").setContent(intent);
tabHost.addTab(spec);
}
@Override
public void onPause(){
MyMapActivity.mMyLocationOverlay.disableCompass();
MyMapActivity.mMyLocationOverlay.disableMyLocation();
super.onPause();
}
}

View File

@@ -0,0 +1,219 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Twenty Codes
* @author ricky barrette
* @author Google Inc.
*/
package com.TwentyCodes.android.DroidFinderFull;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Point;
import com.google.android.maps.GeoPoint;
/**
* This class contains common tools for computing common geological problems
* @author ricky barrette
* @author Google Inc.
*/
public class GeoUtils {
private static int EARTH_RADIUS_KM = 6371;
public static double MILLION = 1000000;
public static int minLatitude;
public static int maxLatitude;
public static int minLongitude;
public static int maxLongitude;
/**
* computes the bearing of lat2/lon2 in relationship from lat1/lon1 in degrees East
* @param lat1 source lat
* @param lon1 source lon
* @param lat2 destination lat
* @param lon2 destination lon
* @return the bearing of lat2/lon2 in relationship from lat1/lon1 in degrees East
* @author Google Inc.
*/
public static double bearing(double lat1, double lon1, double lat2, double lon2) {
double lat1Rad = Math.toRadians(lat1);
double lat2Rad = Math.toRadians(lat2);
double deltaLonRad = Math.toRadians(lon2 - lon1);
double y = Math.sin(deltaLonRad) * Math.cos(lat2Rad);
double x = Math.cos(lat1Rad) * Math.sin(lat2Rad) - Math.sin(lat1Rad) * Math.cos(lat2Rad)
* Math.cos(deltaLonRad);
return radToBearing(Math.atan2(y, x));
}
/**
* computes the bearing of lat2/lon2 in relationship from lat1/lon1 in degrees East
* @param p1 source geopoint
* @param p2 destination geopoint
* @return the bearing of p2 in relationship from p1 in degrees East
* @author Google Inc.
*/
public static double bearing(GeoPoint p1, GeoPoint p2) {
double lat1 = p1.getLatitudeE6() / MILLION;
double lon1 = p1.getLongitudeE6() / MILLION;
double lat2 = p2.getLatitudeE6() / MILLION;
double lon2 = p2.getLongitudeE6() / MILLION;
return bearing(lat1, lon1, lat2, lon2);
}
/**
* Calculates a geopoint x meters away of the geopoint supplied. The new geopoint
* shares the same latitude as geopoint point, this way they are on the same latitude arc.
*
* @param point central geopoint
* @param distance in meters from the geopoint
* @return geopoint that is x meters away from the geopoint supplied
* @author ricky barrette
*/
public static GeoPoint distanceFrom(GeoPoint point, double distance){
//convert meters into kilometers
distance = distance / 1000;
// convert lat and lon of geopoint to radians
double lat1Rad = Math.toRadians((point.getLatitudeE6() / 1e6));
double lon1Rad = Math.toRadians((point.getLongitudeE6() / 1e6));
// double lat2Rad = lat1Rad;
/*
* kilometers = acos(sin(lat1Rad)sin(lat2Rad)+cos(lat1Rad)cos(lat2Rad)cos(lon2Rad-lon1Rad)6371
*
* we are solving this equation for lon2Rad
*
* lon2Rad = lon1Rad+acos(cos(meters/6371)sec(lat1Rad)sec(lat2Rad)-tan(lat1Rad)tan(lat2Rad))
*
* NOTE: sec(x) = 1/cos(x)
*
* NOTE: that lat2Rad is = lat1Rad because we want to keep the new geopoint on the same lat arc
* therefore i saw no need to create a new variable for lat2Rad,
* and simply inputed lat1Rad in place of lat2Rad in the equation
*
* NOTE: this equation has be tested in the field against another gps device, and the distanceKm() from google
* and has been proven to be damn close
*/
double lon2Rad = lon1Rad + Math.acos( Math.cos((distance/6371)) * (1 / Math.cos(lat1Rad))
* (1 / Math.cos(lat1Rad)) - Math.tan(lat1Rad) * Math.tan(lat1Rad));
/*
* test... this equation is curtisy of Raytheon
*
* KM / 6371*cos(lat1Rad - lat2Rad) + lon1Rad = lon2Rad
*
* NOTE: i ricky, don't think that is is very accurate at all
*/
// double lon2Rad = distance / ( 6371 * Math.cos( (lat1Rad - lat1Rad) ) + lon1Rad);
// Log.d(tag,"lon2Rad = "+ lon2Rad);
// Log.d(tag,"lon2Deg = "+ Math.toDegrees(lon2Rad));
//
// Log.d(tag,"distance between the 2 = "+
// distanceKm(point.getLatitudeE6() / 1e6, point.getLongitudeE6() / 1e6,
// point.getLatitudeE6() / 1e6, Math.toDegrees(lon2Rad)));
//return a geopoint that is x meters away from the geopoint supplied
return new GeoPoint(point.getLatitudeE6(), (int) (Math.toDegrees(lon2Rad) * 1e6));
}
/**
* computes the distance between to lat1/lon1 and lat2/lon2 based on the curve of the earth
* @param lat1 source lat
* @param lon1 source lon
* @param lat2 destination lat
* @param lon2 destination lon
* @return the distance between to lat1/lon1 and lat2/lon2
* @author Google Inc.
*/
public static double distanceKm(double lat1, double lon1, double lat2, double lon2) {
double lat1Rad = Math.toRadians(lat1);
double lat2Rad = Math.toRadians(lat2);
double deltaLonRad = Math.toRadians(lon2 - lon1);
return Math.acos(Math.sin(lat1Rad) * Math.sin(lat2Rad) + Math.cos(lat1Rad) * Math.cos(lat2Rad)
* Math.cos(deltaLonRad))
* EARTH_RADIUS_KM;
}
/**
* computes the distance between to p1 and p2 based on the curve of the earth
* @param p1
* @param p2
* @return the distance between to p1 and p2
* @author Google Inc.
*/
public static double distanceKm(GeoPoint p1, GeoPoint p2) {
double lat1 = p1.getLatitudeE6() / MILLION;
double lon1 = p1.getLongitudeE6() / MILLION;
double lat2 = p2.getLatitudeE6() / MILLION;
double lon2 = p2.getLongitudeE6() / MILLION;
return distanceKm(lat1, lon1, lat2, lon2);
}
/**
* computes a geopoint the is the central geopoint between p1 and p1
* @param p1 first geopoint
* @param p2 second geopoint
* @return the central geopoint
* @author ricky barrette
*/
public static GeoPoint midPoint(GeoPoint p1, GeoPoint p2) {
minLatitude = (int)(+81 * 1E6);
maxLatitude = (int)(-81 * 1E6);
minLongitude = (int)(+181 * 1E6);
maxLongitude = (int)(-181 * 1E6);
List<Point> mPoints = new ArrayList<Point>();
int latitude = p1.getLatitudeE6();
int longitude = p1.getLongitudeE6();
if (latitude != 0 && longitude !=0) {
minLatitude = (minLatitude > latitude) ? latitude : minLatitude;
maxLatitude = (maxLatitude < latitude) ? latitude : maxLatitude;
minLongitude = (minLongitude > longitude) ? longitude : minLongitude;
maxLongitude = (maxLongitude < longitude) ? longitude : maxLongitude;
mPoints.add(new Point(latitude, longitude));
}
latitude = p2.getLatitudeE6();
longitude = p2.getLongitudeE6();
if (latitude != 0 && longitude !=0) {
minLatitude = (minLatitude > latitude) ? latitude : minLatitude;
maxLatitude = (maxLatitude < latitude) ? latitude : maxLatitude;
minLongitude = (minLongitude > longitude) ? longitude : minLongitude;
maxLongitude = (maxLongitude < longitude) ? longitude : maxLongitude;
mPoints.add(new Point(latitude, longitude));
}
System.gc();
return new GeoPoint((maxLatitude + minLatitude)/2, (maxLongitude + minLongitude)/2 );
}
/**
* converts radians to bearing
* @param rad
* @return bearing
* @author Google Inc.
*/
public static double radToBearing(double rad) {
return (Math.toDegrees(rad) + 360) % 360;
}
}

View File

@@ -0,0 +1,333 @@
/**
* @author Twenty Codes
* @author ricky barrette
*/
/**
*
*/
package com.TwentyCodes.android.DroidFinderFull;
import java.text.DecimalFormat;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Paint.Style;
import android.location.Location;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Projection;
/**
* @author ricky barrette
*/
public class MyCustomLocationOverlay extends com.google.android.maps.MyLocationOverlay {
protected static boolean blUnit;
protected static GeoPoint gpCar, gpUser;
private static Context mContext;
protected static TextView tvDistance;
private MapView mMapView;
private TextView tvAccuracy;
private SharedPreferences settings;
private ProgressDialog mGPSprogress;
protected static final String STAY_AWAKE = "stay_awake";
protected static final String MEASUREMENT_UNIT = "measurement_unit";
protected static final String LAYERS = "layers";
/**
* an overlay class that displays the compass of what you want really badly
* AKA your car and a user arrow that points north on the map that automatically updates
* also initializes the textviews used to update user about the location status
* @param context - context to work in
* @param mapView - mapView to post overlay to
* @author ricky barrette
*/
protected MyCustomLocationOverlay(Context context, MapView mapView) {
super(context, mapView);
mContext = context;
tvDistance = (TextView) ((Activity) context).findViewById(R.id.tvDistance2);
tvAccuracy = (TextView) ((Activity) context).findViewById(R.id.tvAccuracy2);
settings = context.getSharedPreferences(SettingsActivity.SETTINGS, 0);
blUnit = settings.getBoolean(MEASUREMENT_UNIT, false);
}
/**
* setter method for car values. sets geopoint, and location of user respective to car values
* @param car - lat and lon of car
* @author ricky
*/
protected static void setCar(GeoPoint car) {
gpCar = car;
}
/**
* sets the measurement unit of the distance text field at the top of the activity
* @param unit - true is metric, false is standard
*/
protected static void setUnit(boolean unit) {
blUnit = unit;
Log.i(mContext.getClass().getName(),"unit = "+unit);
}
/**
* returns a string distance that is based on the users measurement unit preference
* @param distance in kilometers
* @return string distance
* @author ricky barrette
*/
private String distance(double distance) {
DecimalFormat threeDForm = new DecimalFormat("#.###");
DecimalFormat twoDForm = new DecimalFormat("#.##");
/*
* if blnUnit is true, the distance computed will be in metric units,
* else, standard units are used
* meters are used until 1 kilometer is reached, then kilometers are used
* feet are used until 1 mile is reached, then miles are used
*/
if(blUnit){
if (distance < 1){
distance = distance * 1000;
return twoDForm.format(distance) +" m";
}
return threeDForm.format(distance) +" Km";
}
distance = distance / 1.609344;
if (distance < 1){
distance = distance * 5280;
return twoDForm.format(distance) +" ft";
}
return twoDForm.format(distance) +" mi";
}
/**
* computes bearing to geopoint based on device oriantaion and draws the compass of what you want really really badly on screen
* @param - canvas - the canvas to draw on
* @param - bearing - bearing of user based on magnetic compass
* @author ricky barrette
*/
@Override
protected void drawCompass(Canvas canvas, float bearing){
/*
* we moved drawUser() call from drawMyLocation() to here to so draw user
* is updated more often to smooth out the rotation of the arrow in relationship with compass
* @author ricky barrette
*
* we found that the user arrow would only be re-drawn if the map was animating, or if the user was scrolling it,
* so we call mMapView.invalidate() to force the map to be re-dawn, including it's overlays
* @author ricky barrette
*
* if the MapView is not null, then draw the user arrow
*/
if (mMapView != null) {
drawUser(canvas, mMapView, bearing);
mMapView.invalidate();
}
/*
* if the car and user geopoint are not null, then draw the compass point to the car geopoint
*
* else draw the compass to point north
*/
if (gpCar != null && gpUser != null){
Double d = GeoUtils.bearing(gpUser, gpCar);
bearing = bearing - d.floatValue();
} else if (bearing != 0){
bearing = 360 - bearing;
}
super.drawCompass(canvas, bearing);
}
/**
* updates location stats, and the accuracy circle. also saves data needed to draw the user arrow
* @author ricky barrette
* @param - canvas - the canvas to draw on
* @param - mapView - the map which to draw the layout
* @param - lastFix - location object of last fix of gps location
* @param - myLocation - current location of user
* @param - when - Ricky is unsure of this value. please kick him in the balls
*/
@Override
protected void drawMyLocation(Canvas canvas, MapView mapView, Location lastFix, GeoPoint myLocation, long when) {
gpUser = myLocation;
mMapView = mapView;
tvAccuracy.setText( distance( (lastFix.getAccuracy() / 1000) ) );
drawAccuracyCircle(myLocation, lastFix, canvas, mapView);
if (gpCar != null && gpUser != null){
double distance = GeoUtils.distanceKm(gpUser, gpCar);
//value is set in KM. if user has gone 30 feet from car app is set to check for arrival
if (distance > 0.009144){
// blnHasLeftCar = true;
}
// //if user has gone back into 30 foot radius and has not found the car and has left the car then notify user of finding of car
// if (distance <= 0.009144 && blnIsCarFound == false && blnHasLeftCar == true){
// blnIsCarFound = true;
// Vibrator vib = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
// AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
// builder.setTitle(mContext.getText(R.string.yay));
// builder.setMessage(mContext.getText(R.string.found_car)).setCancelable(false)
// .setPositiveButton(mContext.getText(R.string.ok), new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int id) {
//
// }
// });
// vib.vibrate(100);
// builder.show();
// }
tvDistance.setText(distance(distance));
} else {
tvDistance.setText("0");
}
}
/**
* draws an accuracy circle based on current location and lastFix onto the canvas supplied
* @param myLocation - current location of user
* @param lastFix - last gps fix of user
* @param canvas - canvas to draw on
* @param mapView the mapview to draw an overlay for
* @author ricky barrette
*/
private void drawAccuracyCircle(GeoPoint myLocation, Location lastFix, Canvas canvas, MapView mapView) {
Paint paint = new Paint();
Point center = new Point();
Point left = new Point();
Projection projection = mapView.getProjection();
/*
* Calculate a geopoint that is "radius" meters away from geopoint point
*/
GeoPoint leftGeo = GeoUtils.distanceFrom(myLocation, lastFix.getAccuracy());
/*
* Original method
*
double latitude = lastFix.getLatitude();
double longitude = lastFix.getLongitude();
float accuracy = lastFix.getAccuracy();
float[] result = new float[1];
Location.distanceBetween(latitude, longitude, latitude, longitude + 1, result);
float longitudeLineDistance = result[0];
GeoPoint leftGeo = new GeoPoint((int)(latitude * 1e6), (int)((longitude - accuracy / longitudeLineDistance) * 1e6));
*/
/*
* Convert the given GeoPoint and leftGeo to onscreen pixel coordinates,
* relative to the top-left of the MapView that provided this Projection.
*/
projection.toPixels(leftGeo, left);
projection.toPixels(myLocation, center);
/*
* get radius of the circle being drawn by
*/
int circleRadius = center.x - left.x;
if(circleRadius <= 0){
circleRadius = left.x - center.x;
}
/*
* paint a blue circle on the map
*/
paint.setAntiAlias(true);
paint.setStrokeWidth(2.0f);
paint.setColor(Color.BLUE);
paint.setStyle(Style.STROKE);
canvas.drawCircle(center.x, center.y, circleRadius, paint);
/*
* draw a dot over the geopoint
* not really need with this as the user arrow will be the center of the circle
*/
// RectF oval = new RectF(center.x - 1, center.y - 1, center.x + 1, center.y + 1);
// canvas.drawOval(oval, paint);
/*
* fill the radius with a alpha blue
*/
paint.setAlpha(30);
paint.setStyle(Style.FILL);
canvas.drawCircle(center.x, center.y, circleRadius, paint);
}
/**
* draws user arrow that points north based on device oriantataion onto the supplied canvas
* @param Canvas - canvas to draw on
* @param mapView the mapview to draw an overlay for
* @param bearing of then compass in degrees East
* @author ricky barrette
*/
private void drawUser(Canvas canvas, MapView mapView, float bearing){
Point screenPts = mapView.getProjection().toPixels(gpUser, null);
Bitmap arrowBitmap = BitmapFactory.decodeResource( mContext.getResources(), R.drawable.user);
Matrix matrix = new Matrix();
matrix.postRotate(bearing);
Bitmap rotatedBmp = Bitmap.createBitmap(
arrowBitmap,
0, 0,
arrowBitmap.getWidth(),
arrowBitmap.getHeight(),
matrix,
true
);
canvas.drawBitmap(
rotatedBmp,
screenPts.x - (rotatedBmp.getWidth() / 2),
screenPts.y - (rotatedBmp.getHeight() / 2),
null
);
}
/**
* Called when location provider status is changed.
* this method will be used to display a GPS progress dialog
* when the provider is unavailable, and dismisses the progress dialog is available
* @param provider name of the provider who's status has changed
* @param status of the provider
* @param extras
* @author ricky barrette
*/
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch(status){
case LocationProvider.AVAILABLE:
mGPSprogress.dismiss();
break;
case LocationProvider.OUT_OF_SERVICE:
mGPSprogress = ProgressDialog.show(mContext, "", "Acquiring GPS Fix", true);
mGPSprogress.setCancelable(true);
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
mGPSprogress = ProgressDialog.show(mContext, "", "Acquiring GPS Fix", true);
mGPSprogress.setCancelable(true);
break;
}
}
}

View File

@@ -0,0 +1,240 @@
/**
* @author Twenty Codes
* @author ricky barrette
*/
package com.TwentyCodes.android.DroidFinderFull;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
/**
* this class handles the map and map functions
* @author ricky barrette
*/
public class MyMapActivity extends MapActivity {
private MapController mMapController;
public static MyCustomLocationOverlay mMyLocationOverlay;
private MapView mMapView;
// protected PowerManager.WakeLock mWakeLock;
// private List<Overlay> mMapOverlays;
private final String tag = "DroidFinder - MyMapActivity";
/**
* displays a dialog to inform that the gps is disabled and provides them with a shortcut to the settings page
* if they select no, then finish() is called.
* @author ricky barrette
*/
private void enableGPSdialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("GPS is disbaled, Do You Want To Enable it?").setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent callGPSSettingIntent = new Intent( android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(callGPSSettingIntent);
dialog.cancel();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
dialog.cancel();
}
});
builder.show();
}
/**
* initializes the mapview, it's controller, zoom controls
* @author ricky barrette 3-31-2010
*/
private void initMap() {
mMapView = (MapView) findViewById(R.id.mapview);
mMapView.setBuiltInZoomControls(true);
mMapController = mMapView.getController();
// mMapOverlays = mMapView.getOverlays();
/*
* add MyCustomLocationOverlay to the map and enable the user icon and the compass
*/
mMyLocationOverlay = new MyCustomLocationOverlay(this, mMapView);
mMapView.getOverlays().add(mMyLocationOverlay);
/*
* on first fix
* remove the GPS progress dialog, animate map the the users location,
* and then zoom in to zoom level 20
*/
// mMyLocationOverlay.runOnFirstFix(new Runnable() {
// public void run() {
//// mGPSprogress.dismiss();
// GeoPoint gpUser = null;
// //try to pan to initial user location, if you fail try, try, try again
// do{
// gpUser = mMyLocationOverlay.getMyLocation();
// } while(! panToGeoPoint(gpUser, true));
// }
// });
}
/**
* loads saved settings from files
* @author ricky barrette
*/
private void loadSettings(){
//TODO load setting from shared_prefs
}
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
initMap();
// if the location manager services are not available, then ask user if they want to enable it
if ((LocationManager) getSystemService(Context.LOCATION_SERVICE) == null)
enableGPSdialog();
}
@Override
protected void onDestroy() {
mMapController = null;
mMyLocationOverlay = null;
mMapView = null;
System.gc();
super.onDestroy();
}
/**
* pans maps to where the a geopoint is, and if zoomIn is true, zooms in to level 20
* @param GeoPoint point - lat and lon of point to pan to
* @param boolean zoomIn - true if map needs to be zoomed in
* @return boolean true if panning was successful
* @author ricky barrette
*/
private boolean panToGeoPoint(GeoPoint point, boolean zoomIn) {
if (point != null) {
Log.e(tag,"panToGeoPoint() point was null");
return false;
}
if (mMapController != null){
Log.e(tag,"panToGeoPoint() mapControler was null");
return false;
}
try {
/**
* We have found that if the map is animating and is then told to animate again it will crash.
* the stopAnimation call should prevent this
*/
mMapController.stopAnimation(false);
mMapController.animateTo(point);
if(zoomIn){
mMapController.setZoom(20);
}
} catch (NullPointerException e) {
Log.e(tag,"panToGeoPoint() Nullpointer exceptoin");
e.printStackTrace();
return false;
}
return true;
}
/**
* displays a quit dialog
* @since 0.0.2
* @author ricky barrette 3-30-2010
*/
public void quitDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to quit").setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.show();
}
/**
* computes a geopoint the is the central geopoint between the user and the car.
* also it zooms so both marks are visible on the map
* @author ricky barrette
*/
private void showBoth(){
panToGeoPoint(GeoUtils.midPoint(MyCustomLocationOverlay.gpCar, MyCustomLocationOverlay.gpUser), false);
mMapController.stopAnimation(true);
mMapController.zoomToSpan((GeoUtils.maxLatitude - GeoUtils.minLatitude), (GeoUtils.maxLongitude - GeoUtils.minLongitude));
}
/**
* displays toast message with a long duration
* @param msg
* @author ricky barrette
*/
public void toastLong(CharSequence msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
toast.show();
}
/**
* displays toast message with a short duration
* @since 0.0.3
* @param msg
* @author ricky barrette 3-31-2010
*/
public void toastShort(CharSequence msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.show();
}
/**
* when called this will prevent the screen from sleeping (turning off)
* call this.mWakeLock.release(); to allow screen to sleep again
* @author ricky barrette
* @since 0.0.9
*/
// private void wakeLock(){
// if(!mWakeLock.isHeld()){
// mWakeLock.acquire();
// }
@Override
protected boolean isRouteDisplayed() {
return false;
}
@Override
protected void onPause(){
mMyLocationOverlay.disableCompass();
mMyLocationOverlay.disableMyLocation();
super.onPause();
}
@Override
protected void onResume(){
mMyLocationOverlay.enableCompass();
mMyLocationOverlay.enableMyLocation();
super.onResume();
}
}

View File

@@ -0,0 +1,211 @@
package com.TwentyCodes.android.DroidFinderFull;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
/**
* dont forget the manifest tag
* <uses-permission android:name="android.permission.READ_LOGS" />
* @author ricky
*/
public class PostMortemReportExceptionHandler implements UncaughtExceptionHandler, Runnable {
public static final String ExceptionReportFilename = "postmortem.trace";
private static final String MSG_SUBJECT_TAG = "Exception Report"; //"app title + this tag" = email subject
private static final String MSG_SENDTO = "twentycodes@gmail.com"; //email will be sent to this account
//the following may be something you wish to consider localizing
private static final String MSG_BODY = "Just click send to help make this application better. "+
"No personal information is being sent (you can check by reading the rest of the email).";
private Thread.UncaughtExceptionHandler mDefaultUEH;
private Activity mApp = null;
public PostMortemReportExceptionHandler(Activity aApp) {
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
mApp = aApp;
}
public String getDebugReport(Throwable aException) {
// NumberFormat theFormatter = new DecimalFormat("#0.");
//stack trace
StackTraceElement[] theStackTrace = aException.getStackTrace();
StringBuffer report = new StringBuffer();
report.append("--------- Application ---------\n\n");
report.append(mApp.getPackageName()+" generated the following exception:\n\n");
report.append(aException.toString() + "\n\n");
report.append("-------------------------------\n\n");
report.append("--------- Stack trace ---------\n\n");
for (int i = 0; i < theStackTrace.length; i++) {
report.append(" " + theStackTrace[i].toString() + "\n");
}
report.append("-------------------------------\n\n");
//app environment
PackageManager pm = mApp.getPackageManager();
PackageInfo pi;
try {
pi = pm.getPackageInfo(mApp.getPackageName(), 0);
} catch (NameNotFoundException eNnf) {
//doubt this will ever run since we want info about our own package
pi = new PackageInfo();
pi.versionName = "unknown";
pi.versionCode = 69;
}
Date theDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss_zzz");
report.append("-------- Environment --------\n");
report.append("Time\t="+sdf.format(theDate)+"\n");
report.append("Device\t="+Build.FINGERPRINT+"\n");
try {
Field theMfrField = Build.class.getField("MANUFACTURER");
report.append("Make\t="+theMfrField.get(null)+"\n");
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
report.append("Device: " + Build.DEVICE + "\n");
report.append("Brand: " + Build.BRAND + "\n");
report.append("Model: "+Build.MODEL+"\n");
report.append("Product: "+Build.PRODUCT+"\n");
report.append("App:\t "+mApp.getPackageName()+", version "+pi.versionName+" (build "+pi.versionCode+")\n");
report.append("Locale: "+mApp.getResources().getConfiguration().locale.getDisplayName()+"\n");
report.append("-----------------------------\n\n");
report.append("--------- Firmware ---------\n\n");
report.append("SDK: " + Build.VERSION.SDK + "\n");
report.append("Release: " + Build.VERSION.RELEASE + "\n");
report.append("Incremental: " + Build.VERSION.INCREMENTAL + "\n");
report.append("Build Id: " + Build.ID + "\n");
report.append("-------------------------------\n\n");
// If the exception was thrown in a background thread inside
// AsyncTask, then the actual exception can be found with getCause
report.append("--------- Cause ---------\n\n");
Throwable cause = aException.getCause();
if (cause != null) {
report.append(cause.toString() + "\n\n");
theStackTrace = cause.getStackTrace();
for (int i = 0; i < theStackTrace.length; i++) {
report.append(" " + theStackTrace[i].toString() + "\n");
}
}
report.append("-------------------------------\n\n");
report.append("--------- Complete Logcat ---------\n\n");
report.append(getLog().toString());
report.append("-------------------------------\n\n");
report.append("END REPORT");
return report.toString();
}
protected StringBuilder getLog(){
final StringBuilder log = new StringBuilder();
try{
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null){
log.append(line);
log.append("\n");
}
}
catch (IOException e){
}
return log;
}
public void run() {
sendDebugReportToAuthor();
}
protected void saveDebugReport(String aReport) {
//save report to file
try {
FileOutputStream theFile = mApp.openFileOutput(ExceptionReportFilename, Context.MODE_PRIVATE);
theFile.write(aReport.getBytes());
theFile.close();
} catch(IOException ioe) {
//error during error report needs to be ignored, do not wish to start infinite loop
}
}
public void sendDebugReportToAuthor() {
String theLine = "";
StringBuffer theTrace = new StringBuffer();
try {
BufferedReader theReader = new BufferedReader(
new InputStreamReader(mApp.openFileInput(ExceptionReportFilename)));
while ((theLine = theReader.readLine())!=null) {
theTrace.append(theLine+"\n");
}
if (sendDebugReportToAuthor(theTrace.toString())) {
mApp.deleteFile(ExceptionReportFilename);
}
} catch (FileNotFoundException eFnf) {
// nothing to do
} catch(IOException eIo) {
// not going to report
}
}
public Boolean sendDebugReportToAuthor(String aReport) {
if (aReport!=null) {
Intent theIntent = new Intent(Intent.ACTION_SEND);
String theSubject = mApp.getTitle()+" "+MSG_SUBJECT_TAG;
String theBody = "\n"+MSG_BODY+"\n\n"+aReport+"\n\n";
theIntent.putExtra(Intent.EXTRA_EMAIL,new String[] {MSG_SENDTO});
theIntent.putExtra(Intent.EXTRA_TEXT, theBody);
theIntent.putExtra(Intent.EXTRA_SUBJECT, theSubject);
theIntent.setType("message/rfc822");
Boolean hasSendRecipients = (mApp.getPackageManager().queryIntentActivities(theIntent,0).size()>0);
if (hasSendRecipients) {
mApp.startActivity(theIntent);
return true;
} else {
return false;
}
} else {
return true;
}
}
public void submit(Throwable e) {
String theErrReport = getDebugReport(e);
saveDebugReport(theErrReport);
//try to send file contents via email (need to do so via the UI thread)
mApp.runOnUiThread(this);
}
public void uncaughtException(Thread t, Throwable e) {
submit(e);
//do not forget to pass this exception through up the chain
mDefaultUEH.uncaughtException(t,e);
}
}

View File

@@ -0,0 +1,208 @@
/**
* @author Twenty Codes
* @author ricky barrette
*/
package com.TwentyCodes.android.DroidFinderFull;
import java.util.InputMismatchException;
import java.util.Scanner;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
/**
* this class will handle all receiving and sending of SMS messages
* @author ricky barrette
*/
public class SMS extends BroadcastReceiver{
protected static final String DELETE_CONFIRMATION = "delete_comfirmation";
protected static final String RETURN_ADDRESS = "return_address";
protected static final String NUMBERS = "numbers";
protected static final String LAT = "lat";
protected static final String LON = "lon";
protected static final String ACCURACY = "accuracy";
private SharedPreferences numbers;
private SharedPreferences settings;
private String tag = "SmsReceiver";
/**
* checks the md5 hash code of a string msg to the saved md5 hash code of a password
* @param msg
* @param key
* @return true if the md5 hash code matches the saved md5 hash code saved in the passwords.xml
* @author ricky barrette
*/
// private boolean checkmd5sum(String msg, String key){
// String correctMd5 = passwords.getString(key,null);
// if (correctMd5 != null) {
// String md5hash = DroidFinder.getMd5Hash(msg);
// if (md5hash.equals(correctMd5)) {
// return true;
// }
// }
// return false;
// }
@Override
public void onReceive(Context context, Intent intent) {
Log.i(tag,"onRecive()");
settings = context.getSharedPreferences(SettingsActivity.SETTINGS, 0);
numbers = context.getSharedPreferences(NUMBERS, 0);
//get the SMS message
Bundle bundle = intent.getExtras();
if (bundle != null)
{
SmsMessage[] msgs = null;
StringBuilder smsMsg = new StringBuilder();
StringBuilder phoneNumber = new StringBuilder();
//read the SMS message received
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
smsMsg.append(msgs[i].getMessageBody().toString());
phoneNumber.append(msgs[i].getOriginatingAddress());
}
String msg = smsMsg.toString();
/*
* locate
* if the SMS message matches a specified string (ignoring case)
* then do something
*/
if (msg.equalsIgnoreCase(settings.getString(SettingsActivity.LOCATE_PASS, null)) &&
settings.getBoolean(SettingsActivity.LOCATE_ENABLED, false)){
if (phoneNumber.toString().length() > 0 && storeNumber(phoneNumber.toString())){
Log.i(tag, "saved number successfuly!");
Log.i(tag,"sending phone location to sender");
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
String number = numbers.getString(RETURN_ADDRESS, null);
if (number != null){
sendSMS(number,
"DroidFinder: " +
location.getLatitude() + ", " + location.getLongitude()
+ "\n Accuracy (meters)= " + location.getAccuracy());
// + "\n Speed (meters/second) = "
// + location.getSpeed());
}
} else {
Log.w(tag, "did not save number successfuly");
}
}
/*
* if the sms msg contains the char sequence "DroidFinder: " then save the 3 floats
* for lat, lon, and accuracy.
*/
if (msg.startsWith("DroidFinder")){
Log.i(tag,"recived a droidfinder message");
Scanner scan = new Scanner(msg);
int index = 0;
Editor editor = settings.edit();
/*
* loops though a human readable message than contains a lat, lon, and accuracy in a specific order.
*
* while the is a other token in the string, try to save it as lat, lon, or accuracy (based on what has been already saved)
* if we cant save due to an InputMismatchException, then log it and skip over the token.
*/
do {
try {
switch (index){
case 0:
Log.i(tag,"tring to save token as lat");
editor.putInt(LAT, (int) (scan.nextDouble() * 1e6));
index++;
Log.i(tag,"save success");
break;
case 1:
Log.i(tag,"tring to save token as lon");
editor.putInt(LON, (int) (scan.nextDouble() * 1e6));
index++;
Log.i(tag,"save success");
break;
case 2:
Log.i(tag,"tring to save token as accuracy");
editor.putFloat(ACCURACY, scan.nextFloat());
index++;
Log.i(tag,"save success");
break;
}
} catch (InputMismatchException e) {
Log.e(tag,"save failed");
e.printStackTrace();
scan.next();
}
} while(scan.hasNext());
editor.commit();
}
/*
* lockPattern
* if the SMS message matches a specified string (ignoring case)
* then do something
*/
if (msg.equalsIgnoreCase(settings.getString(SettingsActivity.LOCK_PATTERN_PASS, null))&&
settings.getBoolean(SettingsActivity.LOCK_PATTERN_ENABLED, false)){
Log.i(tag,"locking phone and dimming screen to save battery");
SettingsManager sm = new SettingsManager(context);
//dim the screen to minimum
sm.setScreenBrightness(0);
//set screen timeout to 1 second
sm.setScreenTimeOff(1);
//lock the screen
sm.setLockPatternEnabled(true);
//disable wifi
sm.setWifiEnabled(false);
}
}
}
/**
* sends a SMS message
* @param phoneNumber
* @param message
* @author ricky barrette
*/
public void sendSMS(String phoneNumber, String message){
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
/**
* stores the senders number to shared_prefs numbers.xml
* @param number
* @return true if save was successful
* @author ricky barrette
*/
private boolean storeNumber(String number){
Editor editor = numbers.edit();
editor.putString(RETURN_ADDRESS, number);
return editor.commit();
}
}

View File

@@ -0,0 +1,127 @@
/**
* @author Twenty Codes
* @author ricky barrette
*/
package com.TwentyCodes.android.DroidFinderFull;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
public class SettingsActivity extends PreferenceActivity implements OnPreferenceClickListener, OnPreferenceChangeListener{
/*
* the following strings are for the shared_prefs passwords.xml
*/
public static final String SETTINGS = "settings";
public static final String LOCATE_PASS = "locate_pass";
public static final String LOCK_PATTERN_PASS = "lock_pattern_pass";
public static final String LOCATE_ENABLED = "locate_enabled";
public static final String LOCK_PATTERN_ENABLED = "lock_pattern_enabled";
public static final String RING_PASS = "ring_pass";
public static final String BACKUP_PASS = "backup_pass";
public static final String DELETE_PASS = "delete_pass";
public static final String BACKUP = "backup";
public static final String RESTORE = "restore";
private Preference locate_pass;
private Preference lock_pattern_pass;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set shared_prefs name
getPreferenceManager().setSharedPreferencesName(SETTINGS);
//load preferences xml
this.addPreferencesFromResource(R.xml.settings);
//set onclick listeners
findPreference(BACKUP).setOnPreferenceClickListener(this);
findPreference(RESTORE).setOnPreferenceClickListener(this);
//set onchange listeners
locate_pass = findPreference(LOCATE_PASS);
lock_pattern_pass = findPreference(LOCK_PATTERN_PASS);
locate_pass.setOnPreferenceChangeListener(this);
lock_pattern_pass.setOnPreferenceChangeListener(this);
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences shared_prefs = getPreferenceManager().getSharedPreferences();
// Setup the initial values
locate_pass.setSummary(shared_prefs.getString(LOCATE_PASS, ""));
lock_pattern_pass.setSummary(shared_prefs.getString(LOCK_PATTERN_PASS, ""));
}
// @Override
// protected void onPause() {
// super.onPause();
// // Unregister the listener whenever a key changes
// getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener((OnSharedPreferenceChangeListener) this);
// }
/**
* handles onclick events of preferences
* @author ricky barrette
*/
@Override
public boolean onPreferenceClick(Preference preference) {
if(preference.getKey().equals(BACKUP)){
new SettingsManager(this).backupSystemSettings();
return true;
}
if(preference.getKey().equals(RESTORE)){
new SettingsManager(this).restoreSystemSettings();
return true;
}
return false;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(preference.getKey().equals(LOCATE_PASS)){
preference.setSummary(newValue.toString());
return true;
}
if(preference.getKey().equals(LOCK_PATTERN_PASS)){
preference.setSummary(newValue.toString());
return true;
}
return false;
}
/**
* returns the md5 hash code for a String
* @param input
* @return md5 hash code
* @author ricky barrette
*/
// public static String getMd5Hash(String input) {
// try{
// MessageDigest md = MessageDigest.getInstance("MD5");
// byte[] messageDigest = md.digest(input.getBytes());
// BigInteger number = new BigInteger(1,messageDigest);
// String md5 = number.toString(16);
//
// while (md5.length() < 32)
// md5 = "0" + md5;
//
// return md5;
// } catch(NoSuchAlgorithmException e) {
// Log.e("MD5", e.getMessage());
// return null;
// }
// }
}

View File

@@ -0,0 +1,227 @@
/**
* @author Twenty Codes
* @author ricky barrette
*/
package com.TwentyCodes.android.DroidFinderFull;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.wifi.WifiManager;
import android.provider.Settings.SettingNotFoundException;
/**
* this class will handle all backups and changes to the system settings of the phone
* these settings include screen brightness, screen time off, lock screen, wifi, bluetooth
* @author ricky barrette
*/
public class SettingsManager {
private final String SYSTEM_SETTINGS = "system_settings";
private final String SCREEN_TIME_OFF = "screen_timer_off";
private final String SCREEN_BRIGHTNESS = "screen_brightness";
private final String LOCK_SCREEN_ENABLED = "lock_screen_enabled";
private final String WIFI_ENABLED = "wifi_enabled";
private final String BLUETOOTH_ON = "bluetooth_on";
private final String NETWORK_PREFERENCE = "network_prefrence";
private Context mContext;
private SharedPreferences system_settings;
private WifiManager mWifiManager;
/**
* creates a system settings manager that can modify the following settings:
* screen brightness, screen time off, lock screen, wifi, bluetooth
* @param context
* @author ricky barrette
*/
SettingsManager(Context context){
mContext = context;
system_settings = context.getSharedPreferences(SYSTEM_SETTINGS, 0);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
/**
* saves modified system settings so they can be restored once the phone is recovered
* @return true is save is successful
* @author ricky barrette
*/
public boolean backupSystemSettings(){
Editor editor = system_settings.edit();
//save screen brightness (0 - 225)
try {
editor.putInt(SCREEN_BRIGHTNESS, getScreenBrightness());
} catch (SettingNotFoundException e) {
e.printStackTrace();
}
//save screen time off (milliseconds)
try {
editor.putInt(SCREEN_TIME_OFF, getScreenTimeOff());
} catch (SettingNotFoundException e) {
e.printStackTrace();
}
//save lock screen preference
try {
editor.putBoolean(LOCK_SCREEN_ENABLED, getLockPatternEnabled());
} catch (SettingNotFoundException e) {
e.printStackTrace();
}
//save bluetooth preference
try {
editor.putBoolean(BLUETOOTH_ON, getBluetoothEnabled());
} catch (SettingNotFoundException e) {
e.printStackTrace();
}
//save network preference
try {
editor.putInt(NETWORK_PREFERENCE, getNetworkPreference());
} catch (SettingNotFoundException e) {
e.printStackTrace();
}
//save wifi preference
if (mWifiManager != null) {
editor.putBoolean(WIFI_ENABLED, getWifiEnabled());
}
return editor.commit();
}
/**
* returns the current state of the bluethooth radio
* @return true if enabled
* @throws SettingNotFoundException
* @author ricky barrette
*/
public boolean getBluetoothEnabled() throws SettingNotFoundException{
if (android.provider.Settings.System.getInt(mContext.getContentResolver(),
android.provider.Settings.Secure.BLUETOOTH_ON) == 1)
return true;
return false;
}
/**
* gets current network preference (this method is not tested)
* @return current network preference
* @throws SettingNotFoundException
* @author ricky barrette
*/
protected int getNetworkPreference() throws SettingNotFoundException{
return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
android.provider.Settings.Secure.NETWORK_PREFERENCE);
}
/**
* returns thecurrent screen brightness on a scale of 0-255
* @return screen brightness value
* @throws SettingNotFoundException
* @author ricky barrette
*/
protected int getScreenBrightness() throws SettingNotFoundException{
return android.provider.Settings.System.getInt(mContext.getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS);
}
/**
* returns the current state of the lock pattern screen
* @return true if enabled
* @throws SettingNotFoundException
* @author ricky barrette
*/
protected boolean getLockPatternEnabled() throws SettingNotFoundException {
if (android.provider.Settings.System.getInt(mContext.getContentResolver(),
android.provider.Settings.System.LOCK_PATTERN_ENABLED) == 1)
return true;
return false;
}
/**
* returns the current screen time out value in milliseconds
* @return the current screen time out in milliseconds
* @throws SettingNotFoundException
* @author ricky barrette
*/
protected int getScreenTimeOff() throws SettingNotFoundException{
return android.provider.Settings.System.getInt(mContext.getContentResolver(),
android.provider.Settings.System.SCREEN_OFF_TIMEOUT);
}
/**
* returns the current state of the wifi
* @return true if enabled
* @author ricky barrette
*/
protected boolean getWifiEnabled(){
return mWifiManager.isWifiEnabled();
}
/**
* enables or disabled bluetooth
* @param enabled
* @author ricky barrette
*/
public void setBluetoothEnabled(boolean enabled){
android.provider.Settings.Secure.putInt(mContext.getContentResolver(),android.provider.Settings.Secure.BLUETOOTH_ON,
enabled ? 1 : 0);
}
/**
* set the screen brightness
* @param brightness setting 0-225
* @author ricky barrette
*/
public void setScreenBrightness(int brightness){
android.provider.Settings.System.putInt(mContext.getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS, brightness);
}
/**
* enables or disables the lock pattern screen
* @param enabled
* @author ricky barrette
*/
public void setLockPatternEnabled(boolean enabled) {
android.provider.Settings.System.putInt(mContext.getContentResolver(),android.provider.Settings.System.LOCK_PATTERN_ENABLED,
enabled ? 1 : 0);
}
/**
* sets the screen time off value
* @param milliseconds
* @author ricky barrette
*/
public void setScreenTimeOff(int milliseconds){
android.provider.Settings.System.putInt(mContext.getContentResolver(),
android.provider.Settings.System.SCREEN_OFF_TIMEOUT, milliseconds);
}
/**
* enables of disabled wifi
* @param enabled
* @author ricky barrette
*/
public void setWifiEnabled(boolean enabled){
if (mWifiManager != null){
mWifiManager.setWifiEnabled(enabled);
}
}
/**
* restores system settings to backed up values
* @author ricky barrette
*/
public void restoreSystemSettings(){
setScreenBrightness(system_settings.getInt(SCREEN_BRIGHTNESS, 0));
setScreenTimeOff(system_settings.getInt(SCREEN_TIME_OFF, 0));
setLockPatternEnabled(system_settings.getBoolean(LOCK_SCREEN_ENABLED, false));
setWifiEnabled(system_settings.getBoolean(WIFI_ENABLED, false));
setBluetoothEnabled(system_settings.getBoolean(BLUETOOTH_ON, false));
}
}