init commit
Change-Id: Ib96d43f22db2bdf360d1d1e0693f6aa5e3aa50ab
This commit is contained in:
7
DroidFinder/.classpath
Normal file
7
DroidFinder/.classpath
Normal 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
33
DroidFinder/.project
Normal 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>
|
||||
43
DroidFinder/AndroidManifest.xml
Normal file
43
DroidFinder/AndroidManifest.xml
Normal 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>
|
||||
2
DroidFinder/default.properties
Normal file
2
DroidFinder/default.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
# Project target.
|
||||
target=android-15
|
||||
3
DroidFinder/lint.xml
Normal file
3
DroidFinder/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
</lint>
|
||||
11
DroidFinder/project.properties
Normal file
11
DroidFinder/project.properties
Normal 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
|
||||
BIN
DroidFinder/res/drawable/icon.png
Normal file
BIN
DroidFinder/res/drawable/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
DroidFinder/res/drawable/my_location.png
Executable file
BIN
DroidFinder/res/drawable/my_location.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
DroidFinder/res/drawable/quit_menu.png
Executable file
BIN
DroidFinder/res/drawable/quit_menu.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
DroidFinder/res/drawable/show_both.png
Executable file
BIN
DroidFinder/res/drawable/show_both.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
DroidFinder/res/drawable/user.png
Executable file
BIN
DroidFinder/res/drawable/user.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
86
DroidFinder/res/layout/map.xml
Normal file
86
DroidFinder/res/layout/map.xml
Normal 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>
|
||||
21
DroidFinder/res/layout/tabs.xml
Normal file
21
DroidFinder/res/layout/tabs.xml
Normal 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>
|
||||
7
DroidFinder/res/values/layer.xml
Executable file
7
DroidFinder/res/values/layer.xml
Executable 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>
|
||||
10
DroidFinder/res/values/measurement_unit.xml
Executable file
10
DroidFinder/res/values/measurement_unit.xml
Executable 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>
|
||||
5
DroidFinder/res/values/strings.xml
Normal file
5
DroidFinder/res/values/strings.xml
Normal 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>
|
||||
73
DroidFinder/res/xml/settings.xml
Executable file
73
DroidFinder/res/xml/settings.xml
Executable 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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
208
DroidFinder/src/com/TwentyCodes/android/DroidFinderFull/SMS.java
Normal file
208
DroidFinder/src/com/TwentyCodes/android/DroidFinderFull/SMS.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user