inital commit
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* LocationRinger.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.ui.RingerListActivity;
|
||||
import com.TwentyCodes.android.exception.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* This is the main Activity for Location Ringer
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class LocationRinger extends RingerListActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* LocatoinSelectedListener.java
|
||||
* @date May 9, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger;
|
||||
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
/**
|
||||
* This interface will be used to pass the selected location from the dialogs to the listening instance
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public interface LocationSelectedListener {
|
||||
|
||||
public void onLocationSelected(GeoPoint point);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* OnDatabaseUpgradeCompeteListener.java
|
||||
* @date Jul 2, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.db;
|
||||
|
||||
/**
|
||||
* This interface will be used to listen to see when the database events are complete
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public interface DatabaseListener {
|
||||
|
||||
public void onDatabaseUpgradeComplete();
|
||||
|
||||
public void onRingerDeletionComplete();
|
||||
|
||||
public void onRestoreComplete();
|
||||
|
||||
public void onDatabaseUpgrade();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,596 @@
|
||||
/**
|
||||
* RingerDatabase.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.db;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
|
||||
/**
|
||||
* This class will be the main interface between location ringer and it's database
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class RingerDatabase {
|
||||
|
||||
private static final String TAG = "RingerDatabase";
|
||||
private Context mContext;
|
||||
private SQLiteDatabase mDb;
|
||||
public boolean isUpgrading = false;
|
||||
private static final String RINGER_INFO_TABLE = "ringer_info";
|
||||
private DatabaseListener mListener;
|
||||
|
||||
/*
|
||||
* database information values
|
||||
*/
|
||||
private final int DATABASE_VERSION = 3;
|
||||
|
||||
/*
|
||||
* the following is for the table that holds the other table names
|
||||
*/
|
||||
private final String DATABASE_NAME = "ringers.db";
|
||||
private final String RINGER_TABLE = "ringers";
|
||||
|
||||
/*
|
||||
* Database keys
|
||||
*/
|
||||
public final static String KEY_RINGER_NAME = "ringer_name";
|
||||
public final static String KEY_RINGTONE = "home_ringtone";
|
||||
public final static String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
|
||||
public final static String KEY_RINGTONE_IS_SILENT = "ringtone_is_silent";
|
||||
public final static String KEY_NOTIFICATION_IS_SILENT = "notification_is_silent";
|
||||
public final static String KEY_IS_ENABLED = "is_enabled";
|
||||
public final static String KEY_RADIUS = "radius";
|
||||
public final static String KEY_LOCATION_LAT = "location_lat";
|
||||
public final static String KEY_LOCATION_LON = "location_lon";
|
||||
public final static String KEY_RINGTONE_URI = "ringtone_uri";
|
||||
public final static String KEY_NOTIFICATION_RINGTONE_URI = "away_notification_uri";
|
||||
public final static String KEY_RINGTONE_VOLUME = "ringtone_volume";
|
||||
public final static String KEY_NOTIFICATION_RINGTONE_VOLUME = "notification_ringtone_volume";
|
||||
public final static String KEY_WIFI = "wifi";
|
||||
public final static String KEY_BT = "bt";
|
||||
public final static String KEY_MUSIC_VOLUME = "music_volume";
|
||||
public final static String KEY_ALARM_VOLUME = "alarm_volume";
|
||||
public static final String KEY_VALUE = "value";
|
||||
public static final String KEY = "key";
|
||||
public static final String KEY_UPDATE_INTERVAL = "update_interval";
|
||||
public static final String KEY_PLUS_BUTTON_HINT = "plus_button_hint";
|
||||
|
||||
|
||||
/**
|
||||
* A helper class to manage database creation and version management.
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private class OpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
/**
|
||||
* Creates a new OpenHelper
|
||||
* @param context
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public OpenHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the database from version 2 to 3
|
||||
* @param db
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void convert2to3(SQLiteDatabase db){
|
||||
//get all the ringer information from the old table
|
||||
Cursor cursor = db.query("two", new String[] { KEY_RINGER_NAME, KEY_RINGTONE,
|
||||
KEY_NOTIFICATION_RINGTONE, KEY_RINGTONE_IS_SILENT,
|
||||
KEY_NOTIFICATION_IS_SILENT, KEY_IS_ENABLED,
|
||||
KEY_RADIUS, KEY_LOCATION_LAT, KEY_LOCATION_LON,
|
||||
KEY_RINGTONE_URI, KEY_NOTIFICATION_RINGTONE_URI,
|
||||
KEY_RINGTONE_VOLUME, KEY_NOTIFICATION_RINGTONE_VOLUME,
|
||||
KEY_WIFI, KEY_BT, KEY_MUSIC_VOLUME, KEY_ALARM_VOLUME
|
||||
}, null, null, null, null, null);
|
||||
|
||||
/*
|
||||
* iterate through the database moving data over to the version 3 tables
|
||||
*/
|
||||
int count = cursor.getColumnCount();
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
ContentValues ringer = new ContentValues();
|
||||
if(Debug.DEBUG)
|
||||
Log.v(TAG, "Converting: " + cursor.getString(0));
|
||||
for(int i = 0; i < count; i++){
|
||||
if(Debug.DEBUG)
|
||||
Log.v(TAG, i + " = "+ cursor.getColumnName(i) +" ~ " + cursor.getString(i));
|
||||
switch(i){
|
||||
case 0: //ringer name
|
||||
ringer.put(cursor.getColumnName(i), cursor.getString(0));
|
||||
break;
|
||||
case 5: //is enabled
|
||||
ringer.put(KEY_IS_ENABLED, cursor.getString(i));
|
||||
break;
|
||||
case 6: //radius
|
||||
ringer.put(KEY_RADIUS, cursor.getString(i));
|
||||
break;
|
||||
case 7: // lat
|
||||
ringer.put(KEY_LOCATION_LAT, cursor.getString(i));
|
||||
break;
|
||||
case 8: // lon
|
||||
ringer.put(KEY_LOCATION_LON, cursor.getString(i));
|
||||
break;
|
||||
default:
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(KEY_RINGER_NAME, cursor.getString(0));
|
||||
values.put(KEY, cursor.getColumnName(i));
|
||||
values.put(KEY_VALUE, cursor.getString(i));
|
||||
db.insert(RINGER_INFO_TABLE, null, values);
|
||||
}
|
||||
}
|
||||
db.insert(RINGER_TABLE, null, ringer);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the initial database structure
|
||||
* @param db
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void createDatabase(SQLiteDatabase db){
|
||||
db.execSQL("CREATE TABLE " + RINGER_TABLE +
|
||||
"(id INTEGER PRIMARY KEY, " +
|
||||
KEY_RINGER_NAME+" TEXT, " +
|
||||
KEY_IS_ENABLED+" TEXT, " +
|
||||
KEY_RADIUS+" INTEGER, " +
|
||||
KEY_LOCATION_LAT+" INTEGER, " +
|
||||
KEY_LOCATION_LON+" INTEGER)");
|
||||
db.execSQL("CREATE TABLE " + RINGER_INFO_TABLE +
|
||||
"(id INTEGER PRIMARY KEY, " +
|
||||
KEY_RINGER_NAME+" TEXT, " +
|
||||
KEY+" TEXT, " +
|
||||
KEY_VALUE+" TEXT)");
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the database is created for the first time. this will create our Ringer database
|
||||
* (non-Javadoc)
|
||||
* @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
if(Debug.DROP_TABLE_EVERY_TIME)
|
||||
db.execSQL("DROP TABLE IF EXISTS " + RINGER_TABLE);
|
||||
createDatabase(db);
|
||||
//insert the default ringer into this table
|
||||
db.execSQL("insert into " + RINGER_TABLE + "(" + KEY_RINGER_NAME + ") values ('"+RingerDatabase.this.mContext.getString(R.string.default_ringer)+"')");
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the database needs to be updated
|
||||
* (non-Javadoc)
|
||||
* @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version "+oldVersion+" to "+newVersion);
|
||||
|
||||
if(RingerDatabase.this.mListener != null)
|
||||
RingerDatabase.this.mListener.onDatabaseUpgrade();
|
||||
|
||||
RingerDatabase.this.isUpgrading = true;
|
||||
|
||||
final Handler handler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if(RingerDatabase.this.mListener != null)
|
||||
RingerDatabase.this.mListener.onDatabaseUpgradeComplete();
|
||||
}
|
||||
};
|
||||
|
||||
//upgrade thread
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
Looper.prepare();
|
||||
switch(oldVersion){
|
||||
case 1:
|
||||
db.execSQL("ALTER TABLE " + RINGER_TABLE + " ADD "+ KEY_MUSIC_VOLUME+" INTEGER");
|
||||
db.execSQL("ALTER TABLE " + RINGER_TABLE + " ADD "+ KEY_ALARM_VOLUME+" INTEGER");
|
||||
case 2:
|
||||
//rename the old ringer table
|
||||
db.execSQL("ALTER TABLE " + RINGER_TABLE + " RENAME TO two");
|
||||
//create a new ringer table
|
||||
createDatabase(db);
|
||||
//convert database to the new version
|
||||
convert2to3(db);
|
||||
//remove old tables
|
||||
db.execSQL("DROP TABLE IF EXISTS two");
|
||||
}
|
||||
handler.sendEmptyMessage(0);
|
||||
RingerDatabase.this.isUpgrading = false;
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string boolean from the database
|
||||
* @param bool
|
||||
* @return true or false
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public static boolean parseBoolean(String bool){
|
||||
try {
|
||||
return bool == null ? false : Integer.parseInt(bool) == 1 ? true : false;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new RingerDatabase
|
||||
* @param context
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public RingerDatabase(Context context){
|
||||
this.mContext = context;
|
||||
this.mDb = new OpenHelper(this.mContext).getWritableDatabase();
|
||||
}
|
||||
|
||||
public RingerDatabase(Context context, DatabaseListener listener){
|
||||
this.mListener = listener;
|
||||
this.mContext = context;
|
||||
this.mDb = new OpenHelper(this.mContext).getWritableDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Backs up the database
|
||||
* @return true if successful
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public boolean backup(){
|
||||
File dbFile = new File(Environment.getDataDirectory() + "/data/"+mContext.getPackageName()+"/databases/"+DATABASE_NAME);
|
||||
|
||||
File exportDir = new File(Environment.getExternalStorageDirectory(), "/"+this.mContext.getString(R.string.app_name));
|
||||
if (!exportDir.exists()) {
|
||||
exportDir.mkdirs();
|
||||
}
|
||||
File file = new File(exportDir, dbFile.getName());
|
||||
|
||||
try {
|
||||
file.createNewFile();
|
||||
this.copyFile(dbFile, file);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this ringer name is original, if not it renames it
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private String checkRingerName(String name){
|
||||
|
||||
List<String> names = this.getAllRingerTitles();
|
||||
String ringerName = name;
|
||||
int count = 1;
|
||||
|
||||
for(int index = 0; index < names.size(); index++ ){
|
||||
if(ringerName.equals(names.get(index))){
|
||||
ringerName = name + count+++"";
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
return ringerName;
|
||||
|
||||
// return checkRingerName(name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file
|
||||
* @param src file
|
||||
* @param dst file
|
||||
* @throws IOException
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void copyFile(File src, File dst) throws IOException {
|
||||
FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(dst).getChannel();
|
||||
try {
|
||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||
} finally {
|
||||
if (inChannel != null)
|
||||
inChannel.close();
|
||||
if (outChannel != null)
|
||||
outChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a note by its row id
|
||||
* @param id
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void deleteRinger(final long id) {
|
||||
|
||||
final ProgressDialog progress = ProgressDialog.show(RingerDatabase.this.mContext, "", RingerDatabase.this.mContext.getText(R.string.deleteing), true, true);
|
||||
|
||||
final Handler handler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if(RingerDatabase.this.mListener != null)
|
||||
RingerDatabase.this.mListener.onRingerDeletionComplete();
|
||||
}
|
||||
};
|
||||
|
||||
//ringer deleting thread
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
Looper.prepare();
|
||||
|
||||
/*
|
||||
* get the ringer name from the id, and then delete all its information from the ringer information table
|
||||
*/
|
||||
RingerDatabase.this.mDb.delete(RINGER_INFO_TABLE, KEY_RINGER_NAME +" = "+ DatabaseUtils.sqlEscapeString(RingerDatabase.this.getRingerName(id)), null);
|
||||
|
||||
/*
|
||||
* finally delete the ringer from the ringer table
|
||||
*/
|
||||
RingerDatabase.this.mDb.delete(RINGER_TABLE, "id = "+ id, null);
|
||||
updateRowIds(id +1);
|
||||
handler.sendEmptyMessage(0);
|
||||
progress.dismiss();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a cursor containing all ringers
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Cursor getAllRingers(){
|
||||
return this.mDb.query(RINGER_TABLE, new String[] { KEY_RINGER_NAME, KEY_IS_ENABLED, KEY_RADIUS, KEY_LOCATION_LAT, KEY_LOCATION_LON }, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all ringer names in the database, where or not if they are enabled
|
||||
* @return list of all strings in the database table
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public List<String> getAllRingerTitles() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
Cursor cursor = this.mDb.query(RINGER_TABLE, new String[] { KEY_RINGER_NAME }, null, null, null, null, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
list.add(cursor.getString(0));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a ringer from a row id;
|
||||
* @param id
|
||||
* @return cursor containing the note
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Cursor getRingerFromId(long id) {
|
||||
return this.mDb.query(RINGER_TABLE, new String[]{ KEY_RINGER_NAME, KEY_IS_ENABLED, KEY_RADIUS, KEY_LOCATION_LAT, KEY_LOCATION_LON }, "id = "+id, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a ringer's info from the supplied ringer name
|
||||
* @param ringerName
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Cursor getRingerInfo(String ringerName){
|
||||
return this.mDb.query(RINGER_INFO_TABLE,
|
||||
new String[]{ KEY, KEY_VALUE }, KEY_RINGER_NAME +" = "+ DatabaseUtils.sqlEscapeString(ringerName), null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ringer's name form the ringer table
|
||||
* @param id
|
||||
* @return ringer's name
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public String getRingerName(long id) {
|
||||
String name = null;
|
||||
Cursor cursor = this.mDb.query(RINGER_TABLE, new String[]{ KEY_RINGER_NAME }, "id = "+id, null, null, null, null);;
|
||||
if (cursor.moveToFirst()) {
|
||||
name = cursor.getString(0);
|
||||
}
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new ringer into the database
|
||||
* @param ringer values
|
||||
* @param ringerInfo values
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void insertRinger(ContentValues ringer, ContentValues ringerInfo){
|
||||
ringer.put(RingerDatabase.KEY_RINGER_NAME, checkRingerName(ringer.getAsString(RingerDatabase.KEY_RINGER_NAME)));
|
||||
mDb.insert(RINGER_TABLE, null, ringer);
|
||||
String ringerName = ringer.getAsString(RingerDatabase.KEY_RINGER_NAME);
|
||||
|
||||
//insert the information values
|
||||
for(Entry<String, Object> item : ringerInfo.valueSet()){
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(KEY_RINGER_NAME, ringerName);
|
||||
values.put(KEY, item.getKey());
|
||||
/*
|
||||
* Try get the value.
|
||||
* If there is a class cast exception, try casting to the next object type.
|
||||
*
|
||||
* The following types are tried:
|
||||
* String
|
||||
* Integer
|
||||
* Boolean
|
||||
*/
|
||||
try {
|
||||
values.put(KEY_VALUE, (String) item.getValue());
|
||||
} catch (ClassCastException e) {
|
||||
try {
|
||||
values.put(KEY_VALUE, (Boolean) item.getValue() ? 1 : 0);
|
||||
} catch (ClassCastException e1) {
|
||||
values.put(KEY_VALUE, (Integer) item.getValue());
|
||||
}
|
||||
}
|
||||
mDb.insert(RINGER_INFO_TABLE, null, values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a ringer is enabled
|
||||
* @param row id
|
||||
* @return true if the ringer is enabled
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public boolean isRingerEnabled(long id) {
|
||||
Cursor cursor = this.mDb.query(RINGER_TABLE, new String[] { KEY_IS_ENABLED }, "id = "+id, null, null, null, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "isRingerEnabled("+id+") = "+ cursor.getString(0));
|
||||
return parseBoolean(cursor.getString(0));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the database from the sdcard
|
||||
* @return true if successful
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void restore(){
|
||||
File dbFile = new File(Environment.getDataDirectory() + "/data/"+mContext.getPackageName()+"/databases/"+DATABASE_NAME);
|
||||
|
||||
File exportDir = new File(Environment.getExternalStorageDirectory(), "/"+this.mContext.getString(R.string.app_name));
|
||||
if (!exportDir.exists()) {
|
||||
exportDir.mkdirs();
|
||||
}
|
||||
File file = new File(exportDir, dbFile.getName());
|
||||
|
||||
try {
|
||||
file.createNewFile();
|
||||
this.copyFile(file, dbFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/*
|
||||
* close and reopen the database to upgrade it.
|
||||
*/
|
||||
this.mDb.close();
|
||||
this.mDb = new OpenHelper(this.mContext).getWritableDatabase();
|
||||
if(this.mDb.isOpen() && ! this.isUpgrading)
|
||||
if(this.mListener != null)
|
||||
this.mListener.onRestoreComplete();
|
||||
}
|
||||
|
||||
public int setRingerEnabled(long id, boolean enabled) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "setRingerEnabled("+id+") = "+ enabled);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(KEY_IS_ENABLED, enabled);
|
||||
return mDb.update(RINGER_TABLE, values, "id" + "= "+ id, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* updates a ringer by it's id
|
||||
* @param id
|
||||
* @param ringer values
|
||||
* @param info values
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void updateRinger(long id, ContentValues ringer, ContentValues info){
|
||||
String ringer_name = getRingerName(id);
|
||||
|
||||
if(!ringer_name.equals(ringer.getAsString(RingerDatabase.KEY_RINGER_NAME)))
|
||||
ringer.put(RingerDatabase.KEY_RINGER_NAME, checkRingerName(ringer.getAsString(RingerDatabase.KEY_RINGER_NAME)));
|
||||
|
||||
//update the information values in the info table
|
||||
for(Entry<String, Object> item : info.valueSet()){
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(KEY_RINGER_NAME, ringer.getAsString(KEY_RINGER_NAME));
|
||||
values.put(KEY, item.getKey());
|
||||
try {
|
||||
values.put(KEY_VALUE, (String) item.getValue());
|
||||
} catch (ClassCastException e) {
|
||||
try {
|
||||
values.put(KEY_VALUE, (Boolean) item.getValue() ? 1 : 0);
|
||||
} catch (ClassCastException e1) {
|
||||
values.put(KEY_VALUE, (Integer) item.getValue());
|
||||
}
|
||||
}
|
||||
//try to update, if update fails insert
|
||||
if(!(mDb.update(RINGER_INFO_TABLE, values, KEY_RINGER_NAME + "="+ DatabaseUtils.sqlEscapeString(ringer_name) +" AND " + KEY +"='"+ item.getKey()+"'", null) > 0))
|
||||
mDb.insert(RINGER_INFO_TABLE, null, values);
|
||||
}
|
||||
|
||||
//update the ringer table
|
||||
mDb.update(RINGER_TABLE, ringer, "id" + "= "+ id, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the row ids after a row is deleted
|
||||
* @param id of the row to start with
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void updateRowIds(long id) {
|
||||
long currentRow;
|
||||
ContentValues values = new ContentValues();
|
||||
Cursor cursor = this.mDb.query(RINGER_TABLE, new String[] { "id" },null, null, null, null, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
currentRow = cursor.getLong(0);
|
||||
if(currentRow == id){
|
||||
id++;
|
||||
values.clear();
|
||||
values.put("id", currentRow -1);
|
||||
mDb.update(RINGER_TABLE, values, "id" + "= "+ currentRow, null);
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Debug.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.debug;
|
||||
|
||||
/**
|
||||
* A convince class containing debugging variables
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class Debug {
|
||||
|
||||
/**
|
||||
* Sets the logging output of this application
|
||||
*/
|
||||
public static final boolean DEBUG = true;
|
||||
|
||||
/**
|
||||
* The amount of intersecting that is needed between a users accuracy radius and a ringers location radius
|
||||
*/
|
||||
public static final float FUDGE_FACTOR = .002f;
|
||||
|
||||
/**
|
||||
* Drops the ringer database table every time the database is created
|
||||
*/
|
||||
public static boolean DROP_TABLE_EVERY_TIME = false;
|
||||
|
||||
/**
|
||||
* Max radius that can be set by a ringer
|
||||
*/
|
||||
public static final int MAX_RADIUS_IN_METERS = 600;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* GetLocationWidget.java
|
||||
* @date Jun 27, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.receivers;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.LocationRinger.services.LocationService;
|
||||
import com.TwentyCodes.android.LocationRinger.ui.SettingsActivity;
|
||||
|
||||
/**
|
||||
* This widget will be used to force a Location update from the users home screen
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class GetLocationWidget extends AppWidgetProvider {
|
||||
|
||||
public final String TAG = "GetLocationWidget";
|
||||
|
||||
/**
|
||||
* Called in response to the ACTION_APPWIDGET_UPDATE broadcast when this AppWidget provider is being asked to provide RemoteViews for a set of AppWidgets.
|
||||
* Override this method to implement your own AppWidget functionality.
|
||||
* @see android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[])
|
||||
* @param context
|
||||
* @param appWidgetManager
|
||||
* @param appWidgetIds
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
if (Debug.DEBUG)
|
||||
Log.v(TAG, "onUpdate()");
|
||||
final int N = appWidgetIds.length;
|
||||
|
||||
// Perform this loop procedure for each App Widget that belongs to this provider
|
||||
for (int i=0; i<N; i++) {
|
||||
int appWidgetId = appWidgetIds[i];
|
||||
|
||||
Intent intent = new Intent(context, LocationService.class)
|
||||
.putExtra(LocationService.INTENT_EXTRA_REQUIRED_ACCURACY, Integer.parseInt(context.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_READABLE).getString(SettingsActivity.ACCURACY , "50")))
|
||||
.setAction(LocationReceiver.LR_ACTION_UPDATE);
|
||||
|
||||
//create a pending intent to start the post activity
|
||||
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||
|
||||
// Get the layout for the App Widget and attach an on-click listener to the button
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.get_location_widget);
|
||||
views.setOnClickPendingIntent(R.id.widget_get_location_button, pendingIntent);
|
||||
|
||||
// Tell the AppWidgetManager to perform an update on the current App Widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
|
||||
}
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements onReceive(Context, Intent) to dispatch calls to the various other methods on AppWidgetProvider.
|
||||
* (non-Javadoc)
|
||||
* @see android.appwidget.AppWidgetProvider#onReceive(android.content.Context, android.content.Intent)
|
||||
* @param context
|
||||
* @param intent received
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Debug.DEBUG)
|
||||
Log.v(TAG, "onReceive");
|
||||
// v1.5 fix that doesn't call onDelete Action
|
||||
final String action = intent.getAction();
|
||||
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
|
||||
final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
this.onDeleted(context, new int[] { appWidgetId });
|
||||
}
|
||||
} else {
|
||||
super.onReceive(context, intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in response to the ACTION_APPWIDGET_DELETED broadcast when one or more AppWidget instances have been deleted.
|
||||
* Override this method to implement your own AppWidget functionality.
|
||||
* (non-Javadoc)
|
||||
* @see android.appwidget.AppWidgetProvider#onDeleted(android.content.Context, int[])
|
||||
* @param context
|
||||
* @param appWidgetIds
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onDeleted(Context context, int[] appWidgetIds) {
|
||||
if (Debug.DEBUG)
|
||||
Log.v(TAG, "onDelete()");
|
||||
super.onDeleted(context, appWidgetIds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* LocationReceiver.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.receivers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.LocationRinger.services.RingerProcessingService;
|
||||
import com.TwentyCodes.android.LocationRinger.ui.SettingsActivity;
|
||||
|
||||
/**
|
||||
* This class will receive broadcast from the location service. it will wake the ringer processing service.
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class LocationReceiver extends com.TwentyCodes.android.location.LocationReceiver {
|
||||
|
||||
public static final String LR_ACTION_UPDATE = "com.TwentyCodes.android.LocationRinger.action.LocationUpdate";
|
||||
private static final String TAG = "LocationReceiver";
|
||||
|
||||
@Override
|
||||
public void onLocationUpdate(Location location) {
|
||||
if(location != null)
|
||||
if(location.getAccuracy()<= Integer.parseInt(mContext.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_PRIVATE).getString(SettingsActivity.IGNORE_LOCATION, "1000")))
|
||||
mContext.startService(new Intent(mContext, RingerProcessingService.class).putExtra(INTENT_EXTRA_LOCATION_PARCEL, location));
|
||||
else
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "location accuracy = "+ location.getAccuracy()+" ignoring");
|
||||
else
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "location was null");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* SystemReceiver.java
|
||||
* @date May 4, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.LocationRinger.services.LocationService;
|
||||
import com.TwentyCodes.android.LocationRinger.ui.SettingsActivity;
|
||||
|
||||
/**
|
||||
* This receiver will system events
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class SystemReceiver extends BroadcastReceiver {
|
||||
|
||||
/*
|
||||
* these constants are used for checking the shared_prefs
|
||||
*/
|
||||
private final String BATTERY_LOW = "battery_low";
|
||||
private final String TAG = "SystemEventReciever";
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
|
||||
* @param context
|
||||
* @param intent
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "onReceive() ~"+intent.getAction());
|
||||
SharedPreferences systemEventHistory = context.getSharedPreferences(TAG, 2);
|
||||
Intent i = new Intent(context, LocationService.class)
|
||||
// .putExtra(LocationService.INTENT_EXTRA_PERIOD_BETWEEN_UPDATES, (long) (60000 * Integer.parseInt(context.getSharedPreferences(SettingsActivity.SETTINGS, 2).getString(SettingsActivity.UPDATE_INTVERVAL , "10"))))
|
||||
.putExtra(LocationService.INTENT_EXTRA_REQUIRED_ACCURACY, Integer.parseInt(context.getSharedPreferences(SettingsActivity.SETTINGS, 2).getString(SettingsActivity.ACCURACY , "50")))
|
||||
.setAction(LocationReceiver.LR_ACTION_UPDATE);
|
||||
|
||||
/*
|
||||
* if the phone finishes booting, then start the service if the user enabled it
|
||||
*/
|
||||
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
|
||||
if(context.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_READABLE).getBoolean(SettingsActivity.START_ON_BOOT, false))
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* if the battery is reported to be low then
|
||||
* stop the service, and remove the pending alarm
|
||||
* and finally record that the phone's battery was low in the shared_prefs
|
||||
*/
|
||||
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW)){
|
||||
LocationService.stopService(context).run();
|
||||
new Handler().postDelayed(LocationService.stopService(context), 30000L);
|
||||
systemEventHistory.edit().putBoolean(BATTERY_LOW, true).commit();
|
||||
}
|
||||
|
||||
/*
|
||||
* if the phone is plugged in then
|
||||
* check to see if the battery was reported low, if it was then
|
||||
* restart the service, and remove shared_prefs entry
|
||||
*/
|
||||
if(intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)){
|
||||
if (systemEventHistory.getBoolean(BATTERY_LOW, false)) {
|
||||
systemEventHistory.edit().remove(BATTERY_LOW).commit();
|
||||
context.startService(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* LocationService.java
|
||||
* @date Jul 3, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.services;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.LocationRinger;
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.ui.SettingsActivity;
|
||||
import com.TwentyCodes.android.SkyHook.SkyHookService;
|
||||
import com.TwentyCodes.android.exception.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* We override the location service so we can attach the exception handler
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class LocationService extends SkyHookService {
|
||||
|
||||
private final int GATHERING_LOCATION_ONGING_NOTIFICATION_ID = 232903877;
|
||||
private SharedPreferences mSettings;
|
||||
private NotificationManager mNotificationManager;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.TwentyCodes.android.SkyHook.SkyHookService#onStartCommand(android.content.Intent, int, int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
this.mPeriod = (long) (60000 * Integer.parseInt(this.mSettings.getString(SettingsActivity.UPDATE_INTVERVAL , "10")));
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.TwentyCodes.android.SkyHook.SkyHookService#onDestroy()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
this.mSettings.edit().remove(SettingsActivity.IS_SERVICE_STARTED).commit();
|
||||
this.mNotificationManager.cancel(this.GATHERING_LOCATION_ONGING_NOTIFICATION_ID);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.TwentyCodes.android.SkyHook.SkyHookService#onCreate()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
|
||||
this.mSettings = this.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_WRITEABLE);
|
||||
this.mSettings.edit().putBoolean(SettingsActivity.IS_SERVICE_STARTED, true).commit();
|
||||
startOnGoingNotification();
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
* starts a simple ongoing notification to inform the user that we are gathering location
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void startOnGoingNotification() {
|
||||
this.mNotificationManager = (NotificationManager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Notification notifyDetails = new Notification(R.drawable.newstatusbar_icon, this.getString(R.string.app_name), System.currentTimeMillis());
|
||||
PendingIntent intent = PendingIntent.getActivity(this, 0, new Intent(this, LocationRinger.class), android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
notifyDetails.setLatestEventInfo(this, this.getString(R.string.app_name), this.getString(R.string.gathering), intent);
|
||||
notifyDetails.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
this.mNotificationManager.notify(this.GATHERING_LOCATION_ONGING_NOTIFICATION_ID, notifyDetails);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* RingerProcessingService.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.services;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.media.AudioManager;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.db.RingerDatabase;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.LocationRinger.receivers.LocationReceiver;
|
||||
import com.TwentyCodes.android.LocationRinger.ui.SettingsActivity;
|
||||
import com.TwentyCodes.android.exception.ExceptionHandler;
|
||||
import com.TwentyCodes.android.location.GeoUtils;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
/**
|
||||
* This service will handle processing the users location and the ringers
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class RingerProcessingService extends Service {
|
||||
|
||||
private static final String TAG = "RingerProcessingService";
|
||||
private int mStartId;
|
||||
private Location mLocation;
|
||||
private RingerDatabase mDb;
|
||||
private WakeLock mWakeLock;
|
||||
private AudioManager mAudioManager;
|
||||
private SharedPreferences mSettings;
|
||||
private WifiManager mWifiManager;
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
/**
|
||||
* Applies a ringers options to the current system settings
|
||||
* @param id
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void applyRinger(ContentValues values) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "applyRigner()");
|
||||
|
||||
String name = values.getAsString(RingerDatabase.KEY_RINGER_NAME);
|
||||
|
||||
/*
|
||||
* Make it toasty if the user wants to be notified.
|
||||
* This will display a toast msg "Applying <ringer name>"
|
||||
*/
|
||||
if(this.getSharedPreferences(SettingsActivity.SETTINGS, 2).getBoolean(SettingsActivity.TOASTY, false))
|
||||
Toast.makeText(this.getApplicationContext(), "Applying "+ name, Toast.LENGTH_SHORT).show();
|
||||
|
||||
/*
|
||||
* We need to null check all the value except ring/notification tone uri's and boolean values.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ringtone & volume
|
||||
* if the ringtone is set to silent we want to set the volume to 0
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_RINGTONE_IS_SILENT)){
|
||||
Log.d(TAG, "Ringtone: "+ applyRingtone(RingtoneManager.TYPE_RINGTONE, RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_RINGTONE_IS_SILENT)), values.getAsString(RingerDatabase.KEY_RINGTONE_URI)));
|
||||
if(RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_RINGTONE_IS_SILENT)))
|
||||
setStreamVolume(0, AudioManager.STREAM_RING);
|
||||
else
|
||||
if(values.get(RingerDatabase.KEY_RINGTONE_VOLUME) != null)
|
||||
setStreamVolume(values.getAsInteger(RingerDatabase.KEY_RINGTONE_VOLUME), AudioManager.STREAM_RING);
|
||||
}
|
||||
|
||||
/*
|
||||
* notification ringtone & volume
|
||||
* if the notification ringtone is silent, we want to set the volume to 0
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_NOTIFICATION_IS_SILENT)){
|
||||
Log.d(TAG, "Notification Ringtone: "+ applyRingtone(RingtoneManager.TYPE_NOTIFICATION, RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_NOTIFICATION_IS_SILENT)), values.getAsString(RingerDatabase.KEY_NOTIFICATION_RINGTONE_URI)));
|
||||
if(RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_NOTIFICATION_IS_SILENT)))
|
||||
setStreamVolume(0, AudioManager.STREAM_NOTIFICATION);
|
||||
else
|
||||
if(values.get(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME) != null)
|
||||
setStreamVolume(values.getAsInteger(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME), AudioManager.STREAM_NOTIFICATION);
|
||||
}
|
||||
|
||||
if(Debug.DEBUG){
|
||||
Log.d(TAG, "Music "+ (mAudioManager.isMusicActive() ? "is playing " : "is not playing"));
|
||||
Log.d(TAG, "Wired Headset "+ (mAudioManager.isWiredHeadsetOn() ? "is on " : "is off"));
|
||||
}
|
||||
|
||||
/*
|
||||
* music volume
|
||||
* we will set the music volume only if music is not playing, and there is no wired head set
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_MUSIC_VOLUME))
|
||||
if(values.get(RingerDatabase.KEY_MUSIC_VOLUME) != null)
|
||||
if(! mAudioManager.isMusicActive())
|
||||
if(! mAudioManager.isWiredHeadsetOn())
|
||||
setStreamVolume(values.getAsInteger(RingerDatabase.KEY_MUSIC_VOLUME), AudioManager.STREAM_MUSIC);
|
||||
|
||||
/*
|
||||
* alarm volume
|
||||
* we will set the alarm volume only if music is not playing, and there is no wired head set
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_ALARM_VOLUME))
|
||||
if(values.get(RingerDatabase.KEY_ALARM_VOLUME) != null)
|
||||
if(! mAudioManager.isMusicActive())
|
||||
if(! mAudioManager.isWiredHeadsetOn())
|
||||
setStreamVolume(values.getAsInteger(RingerDatabase.KEY_ALARM_VOLUME), AudioManager.STREAM_ALARM);
|
||||
|
||||
/*
|
||||
* wifi & bluetooth
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_WIFI))
|
||||
if(mWifiManager != null)
|
||||
mWifiManager.setWifiEnabled(RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_WIFI)));
|
||||
|
||||
if(values.containsKey(RingerDatabase.KEY_BT))
|
||||
if(mBluetoothAdapter != null)
|
||||
if(RingerDatabase.parseBoolean(values.getAsString(RingerDatabase.KEY_BT)))
|
||||
mBluetoothAdapter.enable();
|
||||
else
|
||||
mBluetoothAdapter.disable();
|
||||
|
||||
/*
|
||||
* update interval
|
||||
*/
|
||||
if(values.containsKey(RingerDatabase.KEY_UPDATE_INTERVAL))
|
||||
if (values.get(RingerDatabase.KEY_UPDATE_INTERVAL) != null){
|
||||
Intent i = new Intent(this, LocationService.class)
|
||||
.putExtra(LocationService.INTENT_EXTRA_REQUIRED_ACCURACY, Integer.parseInt(this.getSharedPreferences(SettingsActivity.SETTINGS, 2).getString(SettingsActivity.ACCURACY , "50")))
|
||||
.setAction(LocationReceiver.LR_ACTION_UPDATE);
|
||||
PendingIntent pi = PendingIntent.getService(this, LocationService.REQUEST_CODE, i, 0);
|
||||
|
||||
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
/*
|
||||
* cancel the existing schedule
|
||||
*/
|
||||
am.cancel(pi);
|
||||
|
||||
/*
|
||||
* reschedule the location service
|
||||
*/
|
||||
am.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + (long) (60000 * Integer.parseInt(values.getAsString(RingerDatabase.KEY_UPDATE_INTERVAL))), pi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the ring tone
|
||||
* @param stream audio stream to apply to
|
||||
* @param isSilent true if silent
|
||||
* @param uri of ringtone, if null silent will be applied
|
||||
* @return string uri of applied ringtone, null if silent was applied
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private String applyRingtone(int type, boolean isSilent, String uri) {
|
||||
String ringtoneURI = null;
|
||||
if(isSilent){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "Ringtone was set to silent ");
|
||||
} else
|
||||
ringtoneURI = uri;
|
||||
RingtoneManager.setActualDefaultRingtoneUri(this, type, ringtoneURI == null ? null : Uri.parse(ringtoneURI));
|
||||
return uri;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Backs up the current settings into the database to be re applied as default
|
||||
// * @author ricky barrette
|
||||
// */
|
||||
// private void backup() {
|
||||
//
|
||||
// if(Debug.DEBUG)
|
||||
// Log.d(TAG, "backup()");
|
||||
//
|
||||
// ContentValues ringer = new ContentValues();
|
||||
// ContentValues info = new ContentValues();
|
||||
//
|
||||
// /*
|
||||
// * package the ringer table information
|
||||
// */
|
||||
// ringer.put(RingerDatabase.KEY_RINGER_NAME, DEFAULT_RINGER);
|
||||
//
|
||||
// /*
|
||||
// * package the ringer_info table information
|
||||
// */
|
||||
// info.put(RingerDatabase.KEY_RINGTONE_IS_SILENT, mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT ? true : false);
|
||||
// info.put(RingerDatabase.KEY_RINGTONE_URI, RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE).toString());
|
||||
// info.put(RingerDatabase.KEY_NOTIFICATION_IS_SILENT, mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT ? true : false);
|
||||
// info.put(RingerDatabase.KEY_NOTIFICATION_RINGTONE_URI, RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION).toString());
|
||||
// info.put(RingerDatabase.KEY_RINGTONE_VOLUME, mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
|
||||
// info.put(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME, mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION));
|
||||
// info.put(RingerDatabase.KEY_MUSIC_VOLUME, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
|
||||
// info.put(RingerDatabase.KEY_ALARM_VOLUME, mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM));
|
||||
// info.put(RingerDatabase.KEY_UPDATE_INTERVAL, this.mSettings.getString(SettingsActivity.SETTINGS, "10"));
|
||||
//
|
||||
// if(this.mBluetoothAdapter != null)
|
||||
// info.put(RingerDatabase.KEY_BT, this.mBluetoothAdapter.isEnabled());
|
||||
//
|
||||
// if(this.mWifiManager != null)
|
||||
// info.put(RingerDatabase.KEY_WIFI, this.mWifiManager.isWifiEnabled());
|
||||
//
|
||||
// this.mDb.updateRinger(1, ringer, info);
|
||||
// }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Service#onBind(android.content.Intent)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is first created
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate();
|
||||
this.mDb = new RingerDatabase(this);
|
||||
this.mSettings = this.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_WRITEABLE);
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
this.mWakeLock = (WakeLock) pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
this.mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
this.mWifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
|
||||
this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
this.mWakeLock.acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if(mWakeLock.isHeld())
|
||||
mWakeLock.release();
|
||||
System.gc();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is first started
|
||||
* @param intent
|
||||
* @param flags
|
||||
* @param startId
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "onStartCommand: "+startId);
|
||||
this.mStartId = startId;
|
||||
|
||||
/*
|
||||
* try to sleep so skyhook doesn't cock block us
|
||||
*/
|
||||
try {
|
||||
Thread.sleep(1000l);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// //if this is the first time the service ever starts, then back up the current settings to create a back up
|
||||
// if(this.mSettings.getBoolean(SettingsActivity.IS_FIRST_RINGER_PROCESSING, true)){
|
||||
// backup();
|
||||
// this.mSettings.edit().putBoolean(SettingsActivity.IS_FIRST_RINGER_PROCESSING, false).commit();
|
||||
// }
|
||||
//
|
||||
// //if the default ringer is the currently applied ringer back up the current settings
|
||||
// if(this.mSettings.getBoolean(SettingsActivity.IS_DEFAULT, false)){
|
||||
// backup();
|
||||
// }
|
||||
|
||||
if(intent.getParcelableExtra(LocationReceiver.INTENT_EXTRA_LOCATION_PARCEL) != null){
|
||||
this.mLocation = intent.getParcelableExtra(LocationReceiver.INTENT_EXTRA_LOCATION_PARCEL);
|
||||
processRingers();
|
||||
}else if(Debug.DEBUG)
|
||||
Log.d(TAG, "Location was null");
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the ringer database for applicable ringers
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void processRingers() {
|
||||
long index = 1;
|
||||
boolean isDeafult = true;
|
||||
|
||||
/*
|
||||
* get the default ringer information
|
||||
*/
|
||||
ContentValues ringer = getRinger(1);
|
||||
|
||||
GeoPoint point = new GeoPoint((int) (mLocation.getLatitude() * 1E6), (int) (mLocation.getLongitude()*1E6));
|
||||
if(Debug.DEBUG){
|
||||
Log.d(TAG, "Processing ringers");
|
||||
Log.d(TAG, "Current location "+(int) (mLocation.getLatitude() * 1E6)+", "+(int) (mLocation.getLongitude() * 1E6)+" @ "+ new Float(mLocation.getAccuracy()) / 1000+"km");
|
||||
}
|
||||
|
||||
Cursor c = mDb.getAllRingers();
|
||||
c.moveToFirst();
|
||||
if (c.moveToFirst()) {
|
||||
do {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "Checking ringer "+c.getString(0)+" "+c.getInt(3)+", "+c.getInt(4)+" @ "+ c.getInt(2) +"m");
|
||||
|
||||
if(RingerDatabase.parseBoolean(c.getString(1)))
|
||||
if(GeoUtils.isIntersecting(point, new Float(mLocation.getAccuracy()) / 1000, new GeoPoint(c.getInt(3), c.getInt(4)), new Float(c.getInt(2)) / 1000, Debug.FUDGE_FACTOR)){
|
||||
c.close();
|
||||
getRinger(ringer, index);
|
||||
isDeafult = false;
|
||||
//break loop, we will only apply the first applicable ringer
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
|
||||
c.close();
|
||||
|
||||
if(Debug.DEBUG)
|
||||
for(Entry<String,Object> item : ringer.valueSet())
|
||||
Log.d(TAG, item.getKey());
|
||||
|
||||
applyRinger(ringer);
|
||||
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "Finished processing ringers");
|
||||
|
||||
//store is default
|
||||
this.mSettings.edit().putBoolean(SettingsActivity.IS_DEFAULT, isDeafult).commit();
|
||||
|
||||
this.stopSelf(mStartId);
|
||||
}
|
||||
|
||||
/**
|
||||
* appends the new ringer's information in content values
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private ContentValues getRinger(ContentValues values, long id) {
|
||||
|
||||
String name = this.mDb.getRingerName(id);
|
||||
values.put(RingerDatabase.KEY_RINGER_NAME, name);
|
||||
|
||||
/*
|
||||
* get the ringer's info, and parse it into content values
|
||||
*/
|
||||
Cursor c = this.mDb.getRingerInfo(name);
|
||||
if (c.moveToFirst()) {
|
||||
do {
|
||||
values.put(c.getString(0), c.getString(1));
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
if (c != null && !c.isClosed()) {
|
||||
c.close();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all the ringers information as content values
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private ContentValues getRinger(long id) {
|
||||
return getRinger(new ContentValues(), id);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the volume of a particular stream
|
||||
* @param volume
|
||||
* @param stream
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void setStreamVolume(int volume, int stream) {
|
||||
/*
|
||||
* if the seek bar is set to a value that is higher than what the the stream value is set for
|
||||
* then subtract the seek bar's value from the current volume of the stream, and then
|
||||
* raise the stream by that many times
|
||||
*/
|
||||
if (volume > mAudioManager.getStreamVolume(stream)) {
|
||||
int adjust = volume - mAudioManager.getStreamVolume(stream);
|
||||
for (int i = 0; i < adjust; i++) {
|
||||
mAudioManager.adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, stream, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the seek bar is set to a value that is lower than what the the stream value is set for
|
||||
* then subtract the current volume of the stream from the seek bar's value, and then
|
||||
* lower the stream by that many times
|
||||
*/
|
||||
if (volume < mAudioManager.getStreamVolume(stream)) {
|
||||
int adjust = mAudioManager.getStreamVolume(stream) - volume;
|
||||
for (int i = 0; i < adjust; i++) {
|
||||
mAudioManager.adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, stream, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* FirstBootDialog.java
|
||||
* @date Jul 6, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
|
||||
/**
|
||||
* This class will be used to display the first boot dialog
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class FirstBootDialog extends Dialog implements android.view.View.OnClickListener {
|
||||
|
||||
/**
|
||||
* Creates a new FirstBootDialog
|
||||
* @param context
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public FirstBootDialog(Context context) {
|
||||
super(context);
|
||||
build(context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new FirstBootDialog
|
||||
* @param context
|
||||
* @param theme
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public FirstBootDialog(Context context, int theme) {
|
||||
super(context, theme);
|
||||
build(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FirstBootDialog
|
||||
* @param context
|
||||
* @param cancelable
|
||||
* @param cancelListener
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public FirstBootDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
|
||||
super(context, cancelable, cancelListener);
|
||||
build(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the dialog
|
||||
* @param context
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void build(Context context) {
|
||||
this.requestWindowFeature(Window.FEATURE_LEFT_ICON);
|
||||
this.setContentView(R.layout.first_boot_dialog);
|
||||
this.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.icon);
|
||||
this.setTitle(R.string.welcome);
|
||||
this.findViewById(R.id.ok_button).setOnClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the ok button is clicked
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
this.getContext().getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_WRITEABLE).edit().putBoolean(SettingsActivity.IS_FIRST_BOOT, false).commit();
|
||||
this.dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* @author Twenty Codes
|
||||
* @author ricky barrette
|
||||
*/
|
||||
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.TwentyCodes.android.location.GeoUtils;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
import com.google.android.maps.MapView;
|
||||
import com.google.android.maps.Overlay;
|
||||
import com.google.android.maps.OverlayItem;
|
||||
import com.google.android.maps.Projection;
|
||||
|
||||
/**
|
||||
* This class will used to draw a radius of a specified size in a specified location, then inserted into
|
||||
* an overlay list to be displayed a map
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class RadiusOverlay extends Overlay{
|
||||
|
||||
public OverlayItem mOverlayItem;
|
||||
private GeoPoint mPoint;
|
||||
private float mRadius = 0;
|
||||
private int mColor = Color.GREEN;
|
||||
private GeoPoint mRadiusPoint;
|
||||
|
||||
/**
|
||||
* Creates a new RadiusOverlay
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public RadiusOverlay(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new RadiusOverlay object that can be inserted into an overlay list.
|
||||
* @param point center of radius geopoint
|
||||
* @param radius radius in meters
|
||||
* @param color desired color of the radius from Color API
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public RadiusOverlay(GeoPoint point, float radius, int color) {
|
||||
mPoint = point;
|
||||
mRadius = radius;
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* draws a specific radius on the mapview that is handed to it
|
||||
* @param canvas canvas to be drawn on
|
||||
* @param mapView
|
||||
* @param shadow
|
||||
* @param when
|
||||
*/
|
||||
@Override
|
||||
public void draw(Canvas canvas, MapView mapView, boolean shadow){
|
||||
if(mPoint != null){
|
||||
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 and
|
||||
* convert the given GeoPoint and leftGeo to onscreen pixel coordinates,
|
||||
* relative to the top-left of the MapView that provided this Projection.
|
||||
*/
|
||||
mRadiusPoint = GeoUtils.distanceFrom(mPoint , mRadius);
|
||||
projection.toPixels(mRadiusPoint, left);
|
||||
projection.toPixels(mPoint, 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 circle on the map
|
||||
*/
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStrokeWidth(2.0f);
|
||||
paint.setColor(mColor);
|
||||
paint.setStyle(Style.STROKE);
|
||||
canvas.drawCircle(center.x, center.y, circleRadius, paint);
|
||||
|
||||
//draw a dot over the geopoint
|
||||
RectF oval = new RectF(center.x - 2, center.y - 2, center.x + 2, center.y + 2);
|
||||
canvas.drawOval(oval, paint);
|
||||
|
||||
//fill the radius with a nice green
|
||||
paint.setAlpha(25);
|
||||
paint.setStyle(Style.FILL);
|
||||
canvas.drawCircle(center.x, center.y, circleRadius, paint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the selected location
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public GeoPoint getLocation(){
|
||||
return mPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTap(GeoPoint p, MapView mapView) {
|
||||
mPoint = p;
|
||||
return super.onTap(p, mapView);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param color
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void setColor(int color){
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param location
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void setLocation(GeoPoint location){
|
||||
mPoint = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param radius in meters
|
||||
* @author ricky barrette
|
||||
* @param radius
|
||||
*/
|
||||
public void setRadius(int radius){
|
||||
mRadius = radius;
|
||||
}
|
||||
|
||||
public int getZoomLevel() {
|
||||
// GeoUtils.GeoUtils.distanceFrom(mPoint , mRadius)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,700 @@
|
||||
/**
|
||||
|
||||
* RingeInformationActivity.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.LocationSelectedListener;
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.db.RingerDatabase;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.SkyHook.SkyHook;
|
||||
import com.TwentyCodes.android.location.GeoPointLocationListener;
|
||||
import com.TwentyCodes.android.location.MapView;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
/**
|
||||
* This activity will be used to display all the ringers information, and handle modification to that information
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class RingerInformationActivity extends com.google.android.maps.MapActivity implements OnCheckedChangeListener, OnClickListener, OnSeekBarChangeListener, GeoPointLocationListener, LocationSelectedListener {
|
||||
|
||||
public static final String KEY_ROWID = "row_id";
|
||||
private static final int SAVE_ID = 0;
|
||||
private static final String TAG = "RingerInformationActivity";
|
||||
private static final int ADD_ID = 1;
|
||||
private SeekBar mRingtonVolume;
|
||||
private SeekBar mRadius;
|
||||
private SeekBar mNotificationRingtoneVolume;
|
||||
private MapView mMapView;
|
||||
private EditText mNotificationRingtone;
|
||||
private EditText mRingerName;
|
||||
private EditText mRingtone;
|
||||
private ToggleButton mNotificationRingtoneToggle;
|
||||
private ToggleButton mRingerToggle;
|
||||
private ToggleButton mRingtoneToggle;
|
||||
private ScrollView mScrollView;
|
||||
private String mRingtoneURI;
|
||||
private String mNotificationRingtoneURI;
|
||||
private ToggleButton mMapEditToggle;
|
||||
private RadiusOverlay mRadiusOverlay;
|
||||
private long mRowID;
|
||||
private ToggleButton mWifiToggle;
|
||||
private ToggleButton mBTToggle;
|
||||
private GeoPoint mPoint;
|
||||
private SeekBar mAlarmVolume;
|
||||
private ProgressBar mMusicVolume;
|
||||
private SkyHook mSkyHook;
|
||||
private ProgressDialog mGpsProgress;
|
||||
private boolean isFirstFix;
|
||||
|
||||
private void addFeature(int item) {
|
||||
String feature = this.getResources().getStringArray(R.array.features)[item];
|
||||
|
||||
if(feature.equals(this.getString(R.string.ringtone))){
|
||||
findViewById(R.id.ringtone_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.notification_ringtone))){
|
||||
findViewById(R.id.notification_ringtone_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.alarm_volume))){
|
||||
findViewById(R.id.alarm_volume_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.music_volume))){
|
||||
findViewById(R.id.music_volume_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.bluetooth))){
|
||||
findViewById(R.id.bluetooth_toggle).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.wifi))){
|
||||
findViewById(R.id.wifi_toggle).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(feature.equals(this.getString(R.string.update_interval))){
|
||||
findViewById(R.id.update_interval_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if(this.mBTToggle.isShown() || this.mWifiToggle.isShown())
|
||||
findViewById(R.id.data_label).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will display a prompt asking for what feature to add.
|
||||
* @author ricky
|
||||
*/
|
||||
private void displayFeaturesDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(this.getText(R.string.add_feature));
|
||||
builder.setItems(R.array.features, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
addFeature(item);
|
||||
}
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* starts the ringtone picker
|
||||
* @param ringtoneCode RingtoneManager.TYPE_?
|
||||
* @param uri of current tone
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void getRingtoneURI(int ringtoneCode, String uri){
|
||||
Intent intent = new Intent( RingtoneManager.ACTION_RINGTONE_PICKER);
|
||||
intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TYPE, ringtoneCode);
|
||||
intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TITLE, "Select Tone");
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
|
||||
if( uri == null)
|
||||
try {
|
||||
uri = RingtoneManager.getActualDefaultRingtoneUri(this, ringtoneCode).toString();
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, uri == null ? null : Uri.parse(uri));
|
||||
startActivityForResult( intent, ringtoneCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRouteDisplayed() {
|
||||
//UNUSED
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the rintone picker activity returns it's result
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultCode == RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case RingtoneManager.TYPE_RINGTONE:
|
||||
this.mRingtoneURI = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI).toString();
|
||||
Ringtone ringtone = RingtoneManager.getRingtone(this, Uri.parse(this.mRingtoneURI));
|
||||
this.mRingtone.setText(ringtone == null ? "Silent" : ringtone.getTitle(this));
|
||||
break;
|
||||
case RingtoneManager.TYPE_NOTIFICATION:
|
||||
this.mNotificationRingtoneURI = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI).toString();
|
||||
Ringtone notificationTone = RingtoneManager.getRingtone(this, Uri.parse(this.mNotificationRingtoneURI));
|
||||
this.mNotificationRingtone.setText(notificationTone == null ? "Silent" : notificationTone.getTitle(this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a toggle button's state is changed
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
switch(buttonView.getId()){
|
||||
case R.id.ringer_toggle:
|
||||
this.mRadius.setEnabled(isChecked);
|
||||
this.mRingtone.setEnabled(isChecked);
|
||||
this.mRingtonVolume.setEnabled(isChecked);
|
||||
this.mNotificationRingtone.setEnabled(isChecked);
|
||||
this.mNotificationRingtoneVolume.setEnabled(isChecked);
|
||||
this.mNotificationRingtoneToggle.setEnabled(isChecked);
|
||||
this.mMapView.setEnabled(isChecked);
|
||||
this.mNotificationRingtoneToggle.setEnabled(isChecked);
|
||||
this.mRingtoneToggle.setEnabled(isChecked);
|
||||
this.mMapEditToggle.setEnabled(isChecked);
|
||||
break;
|
||||
|
||||
case R.id.notification_silent_toggle:
|
||||
this.mNotificationRingtone.setEnabled(!isChecked);
|
||||
this.mNotificationRingtoneVolume.setEnabled(!isChecked);
|
||||
break;
|
||||
|
||||
case R.id.ringtone_silent_toggle:
|
||||
this.mRingtone.setEnabled(!isChecked);
|
||||
this.mRingtonVolume.setEnabled(!isChecked);
|
||||
break;
|
||||
|
||||
case R.id.map_edit_toggle:
|
||||
this.isFirstFix = isChecked;
|
||||
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
|
||||
isChecked
|
||||
? (this.getResources().getDisplayMetrics().heightPixels - findViewById(R.id.map_controls).getHeight())
|
||||
: (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 350, getResources().getDisplayMetrics())));
|
||||
if(isChecked){
|
||||
this.mSkyHook.getUpdates();
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_TOP );
|
||||
this.mGpsProgress = ProgressDialog.show(this, "", this.getText(R.string.gps_fix), true, true);
|
||||
} else {
|
||||
this.mSkyHook.removeUpdates();
|
||||
params.addRule(RelativeLayout.BELOW, R.id.info);
|
||||
params.addRule(RelativeLayout.ALIGN_BOTTOM );
|
||||
if(this.mGpsProgress != null)
|
||||
this.mGpsProgress.dismiss();
|
||||
}
|
||||
findViewById(R.id.map_info).setLayoutParams(params );
|
||||
|
||||
this.mMapView.setDoubleTapZoonEnabled(isChecked);
|
||||
//views
|
||||
findViewById(R.id.info).setVisibility(isChecked ? View.GONE : View.VISIBLE);
|
||||
findViewById(R.id.ringer_options).setVisibility(isChecked ? View.GONE : View.VISIBLE);
|
||||
//buttons
|
||||
findViewById(R.id.mark_my_location).setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.my_location).setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.map_mode).setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.search).setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.add_feature_button).setVisibility(isChecked ? View.GONE : View.VISIBLE);
|
||||
this.mScrollView.invalidate();
|
||||
this.mScrollView.setScrollEnabled(! isChecked);
|
||||
this.mMapView.setBuiltInZoomControls(isChecked);
|
||||
this.mMapView.setClickable(isChecked);
|
||||
this.mRadius.setEnabled(isChecked);
|
||||
Toast.makeText(this, isChecked ? getString(R.string.map_editing_enabled) : getString(R.string.map_editiing_disabled), Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a view is clicked
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()){
|
||||
case R.id.notification_ringtone_button:
|
||||
getRingtoneURI(RingtoneManager.TYPE_NOTIFICATION, mNotificationRingtoneURI);
|
||||
break;
|
||||
case R.id.ringtone_button:
|
||||
getRingtoneURI(RingtoneManager.TYPE_RINGTONE, mRingtoneURI);
|
||||
break;
|
||||
case R.id.save_ringer_button:
|
||||
save();
|
||||
break;
|
||||
case R.id.mark_my_location:
|
||||
if(this.mPoint != null){
|
||||
this.mRadiusOverlay.setLocation(mPoint);
|
||||
this.mMapView.getController().setCenter(mPoint);
|
||||
}
|
||||
break;
|
||||
case R.id.my_location:
|
||||
if(this.mPoint != null)
|
||||
this.mMapView.getController().setCenter(mPoint);
|
||||
break;
|
||||
case R.id.map_mode:
|
||||
this.mMapView.setSatellite(mMapView.isSatellite() ? false : true);
|
||||
break;
|
||||
case R.id.search:
|
||||
new SearchDialog(this, this).show();
|
||||
break;
|
||||
case R.id.add_feature_button:
|
||||
findViewById(R.id.add_a_feature_label).setVisibility(View.GONE);
|
||||
displayFeaturesDialog();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the acivity is first created
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* Check to see if wifi is available
|
||||
* check to see if bluetooth is available,
|
||||
* remove unavailable options
|
||||
*/
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
this.setContentView(R.layout.ringer_info);
|
||||
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
|
||||
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
this.mSkyHook = new SkyHook(this);
|
||||
this.mSkyHook.setLocationListener(this);
|
||||
|
||||
this.mScrollView = (ScrollView) findViewById(R.id.scrollview);
|
||||
|
||||
this.mRingerName = (EditText) findViewById(R.id.ringer_name);
|
||||
this.mRingerToggle = (ToggleButton) findViewById(R.id.ringer_toggle);
|
||||
this.mRingerToggle.setChecked(true);
|
||||
this.mRingerToggle.setOnCheckedChangeListener(this);
|
||||
|
||||
this.mMapView = (MapView) findViewById(R.id.mapview);
|
||||
this.mRadius = (SeekBar) findViewById(R.id.radius);
|
||||
this.mRadius.setMax(Debug.MAX_RADIUS_IN_METERS);
|
||||
this.mMapView.setClickable(false);
|
||||
this.mMapEditToggle = (ToggleButton) findViewById(R.id.map_edit_toggle);
|
||||
this.mMapEditToggle.setChecked(false);
|
||||
this.mMapEditToggle.setOnCheckedChangeListener(this);
|
||||
this.mRadiusOverlay = new RadiusOverlay();
|
||||
this.mRadius.setOnSeekBarChangeListener(this);
|
||||
this.mMapView.getOverlays().add(mRadiusOverlay);
|
||||
this.mRadius.setEnabled(false);
|
||||
|
||||
this.mRingtone = (EditText) findViewById(R.id.ringtone);
|
||||
this.mRingtoneToggle = (ToggleButton) findViewById(R.id.ringtone_silent_toggle);
|
||||
this.mRingtonVolume = (SeekBar) findViewById(R.id.ringtone_volume);
|
||||
this.mRingtonVolume.setMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING));
|
||||
this.mRingtonVolume.setProgress(mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
|
||||
this.mRingtoneToggle.setChecked(mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT ? true : false);
|
||||
this.mRingtoneToggle.setOnCheckedChangeListener(this);
|
||||
this.mRingtone.setEnabled(! mRingtoneToggle.isChecked());
|
||||
this.mRingtonVolume.setEnabled(! mRingtoneToggle.isChecked());
|
||||
this.mRingtone.setClickable(true);
|
||||
|
||||
this.mNotificationRingtone = (EditText) findViewById(R.id.notification_ringtone);
|
||||
this.mNotificationRingtoneVolume = (SeekBar) findViewById(R.id.notification_ringtone_volume);
|
||||
this.mNotificationRingtoneToggle = (ToggleButton) findViewById(R.id.notification_silent_toggle);
|
||||
this.mNotificationRingtoneVolume.setMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION));
|
||||
this.mNotificationRingtoneVolume.setProgress(mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION));
|
||||
this.mNotificationRingtoneToggle.setOnCheckedChangeListener(this);
|
||||
this.mNotificationRingtoneToggle.setChecked(mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT ? true : false);
|
||||
this.mNotificationRingtone.setEnabled(! mNotificationRingtoneToggle.isChecked());
|
||||
this.mNotificationRingtoneVolume.setEnabled(! mNotificationRingtoneToggle.isChecked());
|
||||
this.mNotificationRingtone.setClickable(true);
|
||||
|
||||
this.mMusicVolume = (SeekBar) findViewById(R.id.music_volume);
|
||||
this.mMusicVolume.setMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
|
||||
this.mMusicVolume.setProgress(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
|
||||
|
||||
this.mAlarmVolume = (SeekBar) findViewById(R.id.alarm_volume);
|
||||
this.mAlarmVolume.setMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM));
|
||||
this.mAlarmVolume.setProgress(mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM));
|
||||
|
||||
this.mWifiToggle = (ToggleButton) findViewById(R.id.wifi_toggle);
|
||||
this.mBTToggle = (ToggleButton) findViewById(R.id.bluetooth_toggle);
|
||||
|
||||
findViewById(R.id.ringtone_button).setOnClickListener(this);
|
||||
findViewById(R.id.notification_ringtone_button).setOnClickListener(this);
|
||||
findViewById(R.id.save_ringer_button).setOnClickListener(this);
|
||||
findViewById(R.id.mark_my_location).setOnClickListener(this);
|
||||
findViewById(R.id.my_location).setOnClickListener(this);
|
||||
findViewById(R.id.map_mode).setOnClickListener(this);
|
||||
findViewById(R.id.search).setOnClickListener(this);
|
||||
findViewById(R.id.add_feature_button).setOnClickListener(this);
|
||||
|
||||
try {
|
||||
this.mRingtoneURI = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE).toString();
|
||||
this.mRingtone.setText(RingtoneManager.getRingtone(this, Uri.parse(mRingtoneURI)).getTitle(this));
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
this.mRingtoneToggle.setChecked(true);
|
||||
}
|
||||
|
||||
try {
|
||||
this.mNotificationRingtoneURI = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION).toString();
|
||||
this.mNotificationRingtone.setText(RingtoneManager.getRingtone(this, Uri.parse(mNotificationRingtoneURI)).getTitle(this));
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
this.mNotificationRingtoneToggle.setChecked(true);
|
||||
}
|
||||
|
||||
Intent data = this.getIntent();
|
||||
|
||||
if(data.hasExtra(KEY_ROWID)){
|
||||
|
||||
this.mRowID = data.getLongExtra(KEY_ROWID, 0);
|
||||
this.mRingerToggle.setChecked(data.getBooleanExtra(RingerDatabase.KEY_IS_ENABLED, true));
|
||||
this.mRadiusOverlay.setLocation(new GeoPoint(data.getIntExtra(RingerDatabase.KEY_LOCATION_LAT, 0), data.getIntExtra(RingerDatabase.KEY_LOCATION_LON, 0)));
|
||||
this.mRadius.setProgress(data.getIntExtra(RingerDatabase.KEY_RADIUS, 0));
|
||||
this.mRingerName.setText(data.getStringExtra(RingerDatabase.KEY_RINGER_NAME));
|
||||
this.setTitle(getString(R.string.editing)+" "+mRingerName.getText().toString());
|
||||
|
||||
|
||||
/*
|
||||
* We need to null check all the values
|
||||
*/
|
||||
ContentValues info = (ContentValues) data.getParcelableExtra(RingerListActivity.KEY_INFO);
|
||||
|
||||
if(RingerDatabase.parseBoolean(info.getAsString(RingerDatabase.KEY_PLUS_BUTTON_HINT)));
|
||||
findViewById(R.id.add_a_feature_label).setVisibility(View.GONE);
|
||||
|
||||
if (info.get(RingerDatabase.KEY_NOTIFICATION_IS_SILENT) != null){
|
||||
this.mNotificationRingtoneToggle.setChecked(RingerDatabase.parseBoolean(info.getAsString(RingerDatabase.KEY_NOTIFICATION_IS_SILENT)));
|
||||
findViewById(R.id.notification_ringtone_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_NOTIFICATION_RINGTONE) != null){
|
||||
this.mNotificationRingtone.setText(info.getAsString(RingerDatabase.KEY_NOTIFICATION_RINGTONE));
|
||||
findViewById(R.id.notification_ringtone_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_NOTIFICATION_RINGTONE_URI) != null)
|
||||
this.mNotificationRingtoneURI = info.getAsString(RingerDatabase.KEY_NOTIFICATION_RINGTONE_URI);
|
||||
|
||||
if (info.get(RingerDatabase.KEY_RINGTONE) != null){
|
||||
findViewById(R.id.ringtone_info).setVisibility(View.VISIBLE);
|
||||
this.mRingtone.setText(info.getAsString(RingerDatabase.KEY_RINGTONE));
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_RINGTONE_IS_SILENT) != null) {
|
||||
this.mRingtoneToggle.setChecked(RingerDatabase.parseBoolean(info.getAsString(RingerDatabase.KEY_RINGTONE_IS_SILENT)));
|
||||
findViewById(R.id.ringtone_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_RINGTONE_URI) != null)
|
||||
this.mRingtoneURI = info.getAsString(RingerDatabase.KEY_RINGTONE_URI);
|
||||
|
||||
if (info.get(RingerDatabase.KEY_WIFI) != null){
|
||||
this.mWifiToggle.setChecked(RingerDatabase.parseBoolean(info.getAsString(RingerDatabase.KEY_WIFI)));
|
||||
findViewById(R.id.wifi_toggle).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.data_label).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_BT) != null){
|
||||
this.mBTToggle.setChecked(RingerDatabase.parseBoolean(info.getAsString(RingerDatabase.KEY_BT)));
|
||||
findViewById(R.id.bluetooth_toggle).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.data_label).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME) != null)
|
||||
this.mNotificationRingtoneVolume.setProgress(info.getAsInteger(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME));
|
||||
|
||||
if (info.get(RingerDatabase.KEY_RINGTONE_VOLUME) != null)
|
||||
this.mRingtonVolume.setProgress(info.getAsInteger(RingerDatabase.KEY_RINGTONE_VOLUME));
|
||||
|
||||
if (info.get(RingerDatabase.KEY_MUSIC_VOLUME) != null){
|
||||
this.mMusicVolume.setProgress(info.getAsInteger(RingerDatabase.KEY_MUSIC_VOLUME));
|
||||
findViewById(R.id.music_volume_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_ALARM_VOLUME) != null){
|
||||
this.mAlarmVolume.setProgress(info.getAsInteger(RingerDatabase.KEY_ALARM_VOLUME));
|
||||
findViewById(R.id.alarm_volume_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (info.get(RingerDatabase.KEY_UPDATE_INTERVAL) != null){
|
||||
String ui = info.getAsString(RingerDatabase.KEY_UPDATE_INTERVAL);
|
||||
findViewById(R.id.update_interval_info).setVisibility(View.VISIBLE);
|
||||
String[] values = this.getResources().getStringArray(R.array.runtimes);
|
||||
for(int i = 0; i < values.length; i++)
|
||||
if(ui.equals(values[i])){
|
||||
((Spinner) findViewById(R.id.update_interval)).setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
this.setTitle(R.string.new_ringer);
|
||||
|
||||
if(this.mRadiusOverlay.getLocation() != null){
|
||||
this.mMapView.getController().setCenter(this.mRadiusOverlay.getLocation());
|
||||
this.mMapView.getController().setZoom(16);
|
||||
}
|
||||
|
||||
if(this.mRingerName.getText().toString().equals(getString(R.string.default_ringer))){
|
||||
this.mMapView.setEnabled(false);
|
||||
this.mMapEditToggle.setEnabled(false);
|
||||
this.mRingerName.setEnabled(false);
|
||||
this.mRingerToggle.setEnabled(false);
|
||||
findViewById(R.id.ringer_options).setVisibility(View.GONE);
|
||||
findViewById(R.id.map_info).setVisibility(View.GONE);
|
||||
findViewById(R.id.notification_ringtone_info).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.ringtone_info).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.wifi_toggle).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.data_label).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.bluetooth_toggle).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.music_volume_info).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.alarm_volume_info).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.update_interval_info).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
this.mMapView.setDoubleTapZoonEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the main menu that is displayed when the menu button is clicked
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, SAVE_ID, 0, getString(R.string.save_ringer)).setIcon(android.R.drawable.ic_menu_save);
|
||||
menu.add(0, ADD_ID, 0, getString(R.string.add_feature)).setIcon(android.R.drawable.ic_menu_add);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.google.android.maps.MapActivity#onDestroy()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
this.mSkyHook.removeUpdates();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when skyhook has a location to report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(GeoPoint point, int accuracy) {
|
||||
this.mPoint = point;
|
||||
|
||||
if(point != null){
|
||||
|
||||
/*
|
||||
* if this is the first fix and the radius overlay does not have a point specified
|
||||
* then pan the map, and zoom in to the users current location
|
||||
*/
|
||||
if(this.isFirstFix)
|
||||
if(this.mRadiusOverlay.getLocation() == null){
|
||||
if(this.mMapView != null){
|
||||
this.mMapView.getController().setCenter(point);
|
||||
this.mMapView.getController().setZoom((this.mMapView.getMaxZoomLevel() - 5));
|
||||
}
|
||||
this.isFirstFix = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* dismiss the acquiring gps dialog
|
||||
*/
|
||||
if(this.mGpsProgress != null)
|
||||
this.mGpsProgress.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
@Override
|
||||
public void onLocationSelected(GeoPoint point) {
|
||||
if(point != null){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG, "onLocationSelected() "+ point.toString());
|
||||
|
||||
if(this.mRadiusOverlay != null)
|
||||
this.mRadiusOverlay.setLocation(point);
|
||||
|
||||
if(this.mMapView != null){
|
||||
this.mMapView.getController().setCenter(point);
|
||||
this.mMapView.getController().setZoom((this.mMapView.getMaxZoomLevel() - 5));
|
||||
}
|
||||
} else if(Debug.DEBUG)
|
||||
Log.d(TAG, "onLocationSelected() Location was null");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()){
|
||||
case ADD_ID:
|
||||
displayFeaturesDialog();
|
||||
break;
|
||||
case SAVE_ID:
|
||||
save();
|
||||
break;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a seekbar is has its progress changed
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
switch (seekBar.getId()){
|
||||
case R.id.radius:
|
||||
this.mRadiusOverlay.setRadius(progress);
|
||||
this.mMapView.invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
//UNUSED
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
//UNUSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a bundle containing all the information that needs to be saved, and returns it to the starting activity
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void save() {
|
||||
final ProgressDialog progress = ProgressDialog.show(this, "", this.getText(R.string.saving), true, true);
|
||||
|
||||
//Generate the intent in a thread to prevent anr's and allow for progress dialog
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
Looper.prepare();
|
||||
|
||||
Intent data = new Intent();
|
||||
GeoPoint point = RingerInformationActivity.this.mRadiusOverlay.getLocation();
|
||||
|
||||
//to prevent null pointers
|
||||
if(point == null)
|
||||
point = new GeoPoint(0,0);
|
||||
|
||||
if(RingerInformationActivity.this.mRowID > 0)
|
||||
data.putExtra(KEY_ROWID, mRowID);
|
||||
|
||||
ContentValues ringer = new ContentValues();
|
||||
ContentValues info = new ContentValues();
|
||||
|
||||
/*
|
||||
* package the ringer table information
|
||||
*/
|
||||
ringer.put(RingerDatabase.KEY_RINGER_NAME, RingerInformationActivity.this.mRingerName.getText().toString());
|
||||
ringer.put(RingerDatabase.KEY_IS_ENABLED, RingerInformationActivity.this.mRingerToggle.isChecked());
|
||||
ringer.put(RingerDatabase.KEY_LOCATION_LAT, point.getLatitudeE6());
|
||||
ringer.put(RingerDatabase.KEY_LOCATION_LON, point.getLongitudeE6());
|
||||
ringer.put(RingerDatabase.KEY_RADIUS, RingerInformationActivity.this.mRadius.getProgress());
|
||||
|
||||
/*
|
||||
* package the ringer_info table information
|
||||
*/
|
||||
if(findViewById(R.id.notification_ringtone_info).isShown()){
|
||||
info.put(RingerDatabase.KEY_NOTIFICATION_IS_SILENT, RingerInformationActivity.this.mNotificationRingtoneToggle.isChecked());
|
||||
info.put(RingerDatabase.KEY_NOTIFICATION_RINGTONE, RingerInformationActivity.this.mNotificationRingtone.getText().toString());
|
||||
info.put(RingerDatabase.KEY_NOTIFICATION_RINGTONE_URI, RingerInformationActivity.this.mNotificationRingtoneURI);
|
||||
info.put(RingerDatabase.KEY_NOTIFICATION_RINGTONE_VOLUME, RingerInformationActivity.this.mNotificationRingtoneVolume.getProgress());
|
||||
}
|
||||
|
||||
if(findViewById(R.id.ringtone_info).isShown()){
|
||||
info.put(RingerDatabase.KEY_RINGTONE, RingerInformationActivity.this.mRingtone.getText().toString());
|
||||
info.put(RingerDatabase.KEY_RINGTONE_IS_SILENT, RingerInformationActivity.this.mRingtoneToggle.isChecked());
|
||||
info.put(RingerDatabase.KEY_RINGTONE_URI, RingerInformationActivity.this.mRingtoneURI);
|
||||
info.put(RingerDatabase.KEY_RINGTONE_VOLUME, RingerInformationActivity.this.mRingtonVolume.getProgress());
|
||||
}
|
||||
|
||||
if(findViewById(R.id.wifi_toggle).isShown())
|
||||
info.put(RingerDatabase.KEY_WIFI, RingerInformationActivity.this.mWifiToggle.isChecked());
|
||||
|
||||
if(findViewById(R.id.bluetooth_toggle).isShown())
|
||||
info.put(RingerDatabase.KEY_BT, RingerInformationActivity.this.mBTToggle.isChecked());
|
||||
|
||||
if(findViewById(R.id.music_volume_info).isShown())
|
||||
info.put(RingerDatabase.KEY_MUSIC_VOLUME, RingerInformationActivity.this.mMusicVolume.getProgress());
|
||||
|
||||
if(findViewById(R.id.alarm_volume_info).isShown())
|
||||
info.put(RingerDatabase.KEY_ALARM_VOLUME, RingerInformationActivity.this.mAlarmVolume.getProgress());
|
||||
|
||||
if(findViewById(R.id.update_interval_info).isShown())
|
||||
info.put(RingerDatabase.KEY_UPDATE_INTERVAL,
|
||||
RingerInformationActivity.this.getResources().getStringArray(R.array.runtimes)[((Spinner) findViewById(R.id.update_interval)).getSelectedItemPosition()]);
|
||||
|
||||
info.put(RingerDatabase.KEY_PLUS_BUTTON_HINT, true);
|
||||
|
||||
//package the intent
|
||||
data.putExtra(RingerListActivity.KEY_RINGER, ringer).putExtra(RingerListActivity.KEY_INFO, info);
|
||||
RingerInformationActivity.this.setResult(RESULT_OK, data);
|
||||
progress.dismiss();
|
||||
RingerInformationActivity.this.finish();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/**
|
||||
* RingerListActivity.java
|
||||
* @date Apr 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.db.DatabaseListener;
|
||||
import com.TwentyCodes.android.LocationRinger.db.RingerDatabase;
|
||||
import com.TwentyCodes.android.LocationRinger.receivers.LocationReceiver;
|
||||
import com.TwentyCodes.android.LocationRinger.services.LocationService;
|
||||
import com.TwentyCodes.android.SkyHook.SkyHookRegistration;
|
||||
import com.TwentyCodes.android.SkyHook.Splash;
|
||||
import com.skyhookwireless.wps.RegistrationCallback;
|
||||
import com.skyhookwireless.wps.WPSContinuation;
|
||||
import com.skyhookwireless.wps.WPSReturnCode;
|
||||
|
||||
public class RingerListActivity extends Activity implements OnItemClickListener, OnClickListener, DatabaseListener, RegistrationCallback {
|
||||
|
||||
private RingerDatabase mDb;
|
||||
private ListView mListView;
|
||||
private SharedPreferences mSettings;
|
||||
private ProgressDialog mProgress;
|
||||
|
||||
public static final String KEY_RINGER = "key_ringer";
|
||||
public static final String KEY_INFO = "key_info";
|
||||
private static final int NEW_RINGER = 0;
|
||||
private static final int DELETE_ID = 1;
|
||||
private static final int ACTIVITY_CREATE = 3;
|
||||
private static final int ACTIVITY_EDIT = 4;
|
||||
private static final int SETTINGS = 7;
|
||||
private static final int BACKUP = 8;
|
||||
private static final int RESTORE = 9;
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WPSContinuation handleError(WPSReturnCode arg0) {
|
||||
Toast.makeText(this, R.string.skyhook_error_registration, Toast.LENGTH_SHORT).show();
|
||||
return WPSContinuation.WPS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
Toast.makeText(this, R.string.registered, Toast.LENGTH_SHORT).show();
|
||||
this.mSettings.edit().putBoolean(SettingsActivity.IS_REGISTERED, true).commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the note edit activity finishes
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent){
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
if(resultCode == RESULT_OK){
|
||||
switch(requestCode) {
|
||||
case ACTIVITY_CREATE:
|
||||
ContentValues ringer = (ContentValues) intent.getParcelableExtra(KEY_RINGER);
|
||||
mDb.insertRinger(ringer, (ContentValues) intent.getParcelableExtra(KEY_INFO));
|
||||
populate();
|
||||
break;
|
||||
case ACTIVITY_EDIT:
|
||||
mDb.updateRinger(intent.getLongExtra(RingerInformationActivity.KEY_ROWID, 0),
|
||||
(ContentValues) intent.getParcelableExtra(KEY_RINGER), (ContentValues) intent.getParcelableExtra(KEY_INFO));
|
||||
populate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(this, RingerInformationActivity.class);
|
||||
startActivityForResult(i, ACTIVITY_CREATE );
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the context menu item has been selected
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case DELETE_ID:
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
||||
if(info.id == 0)
|
||||
Toast.makeText(this, this.getString(R.string.cant_delete_default), Toast.LENGTH_SHORT).show();
|
||||
else
|
||||
mDb.deleteRinger(info.id +1);
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.ringer_list);
|
||||
this.mDb = new RingerDatabase(this, this);
|
||||
this.mListView = (ListView) findViewById(R.id.ringer_list);
|
||||
this.mListView.setOnItemClickListener(this);
|
||||
this.mListView.setOnCreateContextMenuListener(this);
|
||||
this.mListView.setEmptyView(findViewById(android.R.id.empty));
|
||||
findViewById(R.id.add_ringer_button).setOnClickListener(this);
|
||||
populate();
|
||||
this.mSettings = this.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_WRITEABLE);
|
||||
|
||||
if(this.mSettings.getBoolean(SettingsActivity.IS_FIRST_BOOT, true))
|
||||
new FirstBootDialog(this).show();
|
||||
|
||||
if(! this.mSettings.getBoolean(SettingsActivity.IS_REGISTERED, false)){
|
||||
new SkyHookRegistration(this).registerNewUser(this);
|
||||
}
|
||||
|
||||
this.startActivity(new Intent(this, Splash.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the activity is first created, creates a context menu
|
||||
* @param menu
|
||||
* @param v
|
||||
* @param menuInfo
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.add(0, DELETE_ID, 0, "Delete Ringer").setIcon(android.R.drawable.ic_menu_delete);
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the activity is first created, creates options menu
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu (Menu menu) {
|
||||
menu.add(1, NEW_RINGER, 0, getString(R.string.new_ringer)).setIcon(android.R.drawable.ic_menu_add);
|
||||
menu.add(1, BACKUP, 1, getString(R.string.backup)).setIcon(android.R.drawable.ic_menu_upload);
|
||||
menu.add(1, RESTORE, 2, getString(R.string.restore)).setIcon(android.R.drawable.ic_menu_revert);
|
||||
menu.add(1, SETTINGS, 5, getString(R.string.settings)).setIcon(android.R.drawable.ic_menu_preferences);
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a database is being upgraded
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onDatabaseUpgrade() {
|
||||
this.mProgress = ProgressDialog.show(this, "", this.getText(R.string.upgrading), true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* called when a database upgrade is finished
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onDatabaseUpgradeComplete() {
|
||||
populate();
|
||||
if(this.mProgress != null)
|
||||
this.mProgress.dismiss();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onDestroy()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
restartService();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* called when an item in the list view has been clicked,
|
||||
* this will open the note edit dialog for the selected note
|
||||
* (non-Javadoc)
|
||||
* @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> arg0, View v, int postion, final long id) {
|
||||
|
||||
final ProgressDialog progress = ProgressDialog.show(this, "", this.getText(R.string.loading), true, true);
|
||||
|
||||
//post to social sites in a new thread to prevent ANRs
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
Looper.prepare();
|
||||
|
||||
Intent i = new Intent(RingerListActivity.this, RingerInformationActivity.class);
|
||||
|
||||
/*
|
||||
* get the ringer
|
||||
*/
|
||||
Cursor ringer = mDb.getRingerFromId(id+1);
|
||||
if (ringer.moveToFirst()) {
|
||||
i.putExtra(RingerInformationActivity.KEY_ROWID, id+1)
|
||||
.putExtra(RingerDatabase.KEY_RINGER_NAME, ringer.getString(0))
|
||||
.putExtra(RingerDatabase.KEY_IS_ENABLED, ringer.getString(1)== null ? true :(Integer.parseInt(ringer.getString(1)) == 1 ? true : false))//5
|
||||
.putExtra(RingerDatabase.KEY_RADIUS, ringer.getInt(2))
|
||||
.putExtra(RingerDatabase.KEY_LOCATION_LAT, ringer.getInt(3))
|
||||
.putExtra(RingerDatabase.KEY_LOCATION_LON, ringer.getInt(4));
|
||||
}
|
||||
if (ringer != null && !ringer.isClosed()) {
|
||||
ringer.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* get the ringer's info, and parse it into content values
|
||||
*/
|
||||
ContentValues values = new ContentValues();
|
||||
Cursor info = mDb.getRingerInfo(i.getStringExtra(RingerDatabase.KEY_RINGER_NAME));
|
||||
if (info.moveToFirst()) {
|
||||
do {
|
||||
values.put(info.getString(0), info.getString(1));
|
||||
} while (info.moveToNext());
|
||||
}
|
||||
if (info != null && !info.isClosed()) {
|
||||
info.close();
|
||||
}
|
||||
i.putExtra(KEY_INFO, values);
|
||||
|
||||
progress.dismiss();
|
||||
|
||||
//start the ringer info activity in editor mode
|
||||
startActivityForResult(i, ACTIVITY_EDIT);
|
||||
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* called when an option is selected form the menu
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected (MenuItem item) {
|
||||
switch (item.getItemId()){
|
||||
case NEW_RINGER:
|
||||
Intent i = new Intent(this, RingerInformationActivity.class);
|
||||
startActivityForResult(i, ACTIVITY_CREATE );
|
||||
return true;
|
||||
|
||||
case SETTINGS:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
return true;
|
||||
|
||||
case BACKUP:
|
||||
mDb.backup();
|
||||
SettingsActivity.backup(this);
|
||||
break;
|
||||
|
||||
case RESTORE:
|
||||
mDb.restore();
|
||||
SettingsActivity.restore(this);
|
||||
break;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the database is restored
|
||||
*/
|
||||
@Override
|
||||
public void onRestoreComplete() {
|
||||
populate();
|
||||
}
|
||||
|
||||
/**
|
||||
* called when a ringer is deleted
|
||||
*/
|
||||
@Override
|
||||
public void onRingerDeletionComplete() {
|
||||
populate();
|
||||
}
|
||||
|
||||
/**
|
||||
* populates the list view from the data base
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void populate() {
|
||||
findViewById(R.id.add_ringer_button_hint).setVisibility(this.mDb.getAllRingerTitles().size() > 1 ? View.GONE : View.VISIBLE);
|
||||
mListView.setAdapter(new RingerListAdapter(this, mDb));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the service if its not already running.
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void restartService() {
|
||||
if(! this.getSharedPreferences(SettingsActivity.SETTINGS, Context.MODE_WORLD_WRITEABLE).getBoolean(SettingsActivity.IS_SERVICE_STARTED, false)){
|
||||
// cancel the previous service
|
||||
LocationService.stopService(this).run();
|
||||
//start the new service
|
||||
Intent i = new Intent(this, LocationService.class)
|
||||
.putExtra(LocationService.INTENT_EXTRA_REQUIRED_ACCURACY, Integer.parseInt(this.getSharedPreferences(SettingsActivity.SETTINGS, 2).getString(SettingsActivity.ACCURACY , "50")))
|
||||
.setAction(LocationReceiver.LR_ACTION_UPDATE);
|
||||
this.startService(i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* RingerListAdaptor.java
|
||||
* @date May 11, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.db.RingerDatabase;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
|
||||
/**
|
||||
* This adapter will be used to populate the list view with all the ringers names, and manage enabling/disabling of ringers based on their check box.
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class RingerListAdapter extends BaseAdapter {
|
||||
|
||||
private static final String TAG = "RingerListAdapter";
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.widget.BaseAdapter#notifyDataSetChanged()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private RingerDatabase mDb;
|
||||
private List<String> mList;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
/**
|
||||
* Creates a new RingerListAdapter
|
||||
* @param context
|
||||
* @param listener
|
||||
* @param db
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public RingerListAdapter(Context context, RingerDatabase db) {
|
||||
super();
|
||||
// Cache the LayoutInflate to avoid asking for a new one each time.
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mDb = db;
|
||||
mList = db.getAllRingerTitles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItem(int position) {
|
||||
return mList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
|
||||
// A ViewHolder keeps references to children views to avoid unnecessary calls to findViewById() on each row.
|
||||
ViewHolder holder;
|
||||
|
||||
// When convertView is not null, we can reuse it directly, there is no need
|
||||
// to reinflate it. We only inflate a new View when the convertView supplied
|
||||
// by ListView is null.
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.list_item, null);
|
||||
|
||||
// Creates a ViewHolder and store references to the two children views
|
||||
// we want to bind data to.
|
||||
holder = new ViewHolder();
|
||||
holder.text = (TextView) convertView.findViewById(android.R.id.text1);
|
||||
holder.checkbox = (CheckBox) convertView.findViewById(R.id.ringer_enabled_checkbox);
|
||||
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
// Get the ViewHolder back to get fast access to the TextView
|
||||
// and the ImageView.
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
if(Debug.DEBUG){
|
||||
Log.d(TAG, "postion = "+position);
|
||||
|
||||
if(convertView == null)
|
||||
Log.e(TAG,"convertview is null!!!");
|
||||
|
||||
if(holder == null)
|
||||
Log.e(TAG,"holder is null!!!");
|
||||
|
||||
if(holder.text == null)
|
||||
Log.e(TAG,"holder.text is null!!!");
|
||||
|
||||
if(holder.checkbox == null)
|
||||
Log.e(TAG,"holder.checkbox is null!!!");
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind the data efficiently with the holder.
|
||||
* Remember that you should always call setChecked() after calling setOnCheckedChangedListener.
|
||||
* This will prevent the list from changing the values on you.
|
||||
*/
|
||||
holder.text.setText(getItem(position));
|
||||
holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
mDb.setRingerEnabled(position +1, isChecked);
|
||||
}
|
||||
});
|
||||
holder.checkbox.setChecked(mDb.isRingerEnabled(position +1));
|
||||
|
||||
//Remove the checkbox for the default ringer
|
||||
if(position == 0)
|
||||
holder.checkbox.setVisibility(View.INVISIBLE);
|
||||
else
|
||||
holder.checkbox.setVisibility(View.VISIBLE);
|
||||
return convertView;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
TextView text;
|
||||
CheckBox checkbox;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* ScrollView.java
|
||||
* @date May 3, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* This is a simple scroll view that i have made to enable and disable scrolling
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ScrollView extends android.widget.ScrollView {
|
||||
|
||||
private boolean isEnabled = true;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param apiKey
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ScrollView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ScrollView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disabled the scrollview's ability to scroll
|
||||
* @param enabled
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void setScrollEnabled(boolean enabled){
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
return isEnabled ? super.onInterceptTouchEvent(ev) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
return isEnabled ? super.onTouchEvent(ev) : false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* SearchDialog.java
|
||||
* @date May 9, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.LocationSelectedListener;
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
import com.TwentyCodes.android.LocationRinger.debug.Debug;
|
||||
import com.TwentyCodes.android.location.ReverseGeocoder;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
|
||||
/**
|
||||
* This dialog will be used to get users input for the address that they want to search for. A GeoPoint location will be returned via LocationSelectedListener
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class SearchDialog extends Dialog implements android.view.View.OnClickListener, OnItemClickListener{
|
||||
|
||||
protected static final String TAG = "SearchDialog";
|
||||
private ListView mAddressList;
|
||||
private EditText mAddress;
|
||||
private JSONArray mResults;
|
||||
private ProgressBar mProgress;
|
||||
private Handler mHandler;
|
||||
private Context mContext;
|
||||
private LocationSelectedListener mListener;
|
||||
|
||||
/**
|
||||
* Creates a new search dialog
|
||||
* @param context
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public SearchDialog(Context context, LocationSelectedListener listener) {
|
||||
super(context);
|
||||
this.setTitle(R.string.search);
|
||||
this.setContentView(R.layout.address_dialog);
|
||||
findViewById(R.id.ok).setOnClickListener(this);
|
||||
mAddressList = (ListView) findViewById(R.id.address_list);
|
||||
mAddressList.setOnItemClickListener(this);
|
||||
mAddress = (EditText) findViewById(R.id.address);
|
||||
mProgress = (ProgressBar) findViewById(R.id.search_progress);
|
||||
mHandler = new Handler();
|
||||
mContext = context;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all the strings from the JSON Array
|
||||
* @return list of addresses
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private ArrayList<String> getAddress() {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"getAddress()");
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
try {
|
||||
for(int i = 0; i < mResults.length(); i++){
|
||||
list.add(mResults.getJSONObject(i).getString("address"));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the GeoPoint from the JSON Array for the given index
|
||||
* @param index for the place
|
||||
* @return GeoPoint of the place
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private GeoPoint getCoords(int index){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"getCoords()");
|
||||
try {
|
||||
JSONArray coords = mResults.getJSONObject(index).getJSONObject("Point").getJSONArray("coordinates");
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"creating geopoint: "+ new GeoPoint((int) (coords.getDouble(1) *1E6), (int) (coords.getDouble(0)*1E6)).toString());
|
||||
return new GeoPoint((int) (coords.getDouble(1) *1E6), (int) (coords.getDouble(0)*1E6));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
switch(v.getId()){
|
||||
case R.id.ok:
|
||||
v.setEnabled(false);
|
||||
mProgress.setVisibility(View.VISIBLE);
|
||||
mProgress.setIndeterminate(true);
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"strarting search and parsing") ;
|
||||
try {
|
||||
mResults = ReverseGeocoder.addressSearch(mAddress.getText().toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(mResults != null){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"finished searching and parsing");
|
||||
//update UI
|
||||
mHandler.post(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"populating list");
|
||||
mAddressList.setAdapter(new ArrayAdapter<String>(mContext, android.R.layout.simple_list_item_1, getAddress()));
|
||||
v.setEnabled(true);
|
||||
mProgress.setVisibility(View.INVISIBLE);
|
||||
mProgress.setIndeterminate(false);
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"finished");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//update the UI
|
||||
mHandler.post(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
v.setEnabled(true);
|
||||
mProgress.setVisibility(View.INVISIBLE);
|
||||
mProgress.setIndeterminate(false);
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"failed");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if(Debug.DEBUG)
|
||||
Log.d(TAG,"slected "+ (int) id);
|
||||
mListener.onLocationSelected(getCoords((int) id));
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* SettingsActivity.java
|
||||
* @date May 4, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
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;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
|
||||
/**
|
||||
* This is the settings activity for location ringer
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class SettingsActivity extends PreferenceActivity implements OnPreferenceClickListener {
|
||||
|
||||
public static final String SETTINGS = "settings";
|
||||
public static final String UPDATE_INTVERVAL = "update_interval";
|
||||
public static final String IGNORE_LOCATION = "ignore_location";
|
||||
public static final String ACCURACY = "accuracy";
|
||||
public static final String TOASTY = "toasty";
|
||||
public static final String EMAIL = "email";
|
||||
public static final String START_ON_BOOT = "start_on_boot";
|
||||
public static final String IS_SERVICE_STARTED = "is_service_started";
|
||||
public static final String IS_FIRST_BOOT = "is_first_boot";
|
||||
public static final String IS_REGISTERED = "is_registered";
|
||||
public static final String IS_FIRST_RINGER_PROCESSING = "is_first_ringer_processing";
|
||||
public static final String IS_DEFAULT = "is_default";
|
||||
public static final String RESTORE = "restore";
|
||||
public static final String BACKUP = "backup";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
this.getPreferenceManager().setSharedPreferencesName(SETTINGS);
|
||||
addPreferencesFromResource(R.xml.setings);
|
||||
this.findPreference(EMAIL).setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the email preference button is clicked
|
||||
*/
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
this.startActivity(generateEmailIntent());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* generates the exception repost email intent
|
||||
* @param report
|
||||
* @return intent to start users email client
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private Intent generateEmailIntent() {
|
||||
/*
|
||||
* get the build information, and build the string
|
||||
*/
|
||||
PackageManager pm = this.getPackageManager();
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(this.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 = 1;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
String theSubject = this.getString(R.string.app_name);
|
||||
String theBody = "\n\n\n"+ Build.FINGERPRINT +"\n"+ this.getString(R.string.app_name)+" "+pi.versionName+" bulid "+pi.versionCode;
|
||||
intent.putExtra(Intent.EXTRA_EMAIL,new String[] {this.getString(R.string.email)});
|
||||
intent.putExtra(Intent.EXTRA_TEXT, theBody);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, theSubject);
|
||||
intent.setType("message/rfc822");
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backs up the database
|
||||
* @return true if successful
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public static boolean backup(Context context){
|
||||
File dbFile = new File(Environment.getDataDirectory() + "/data/"+context.getPackageName()+"/shared_prefs/"+SETTINGS+".xml");
|
||||
|
||||
File exportDir = new File(Environment.getExternalStorageDirectory(), "/"+context.getString(R.string.app_name));
|
||||
if (!exportDir.exists()) {
|
||||
exportDir.mkdirs();
|
||||
}
|
||||
File file = new File(exportDir, dbFile.getName());
|
||||
|
||||
try {
|
||||
file.createNewFile();
|
||||
copyFile(dbFile, file);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file
|
||||
* @param src file
|
||||
* @param dst file
|
||||
* @throws IOException
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private static void copyFile(File src, File dst) throws IOException {
|
||||
FileChannel inChannel = new FileInputStream(src).getChannel();
|
||||
FileChannel outChannel = new FileOutputStream(dst).getChannel();
|
||||
try {
|
||||
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||
} finally {
|
||||
if (inChannel != null)
|
||||
inChannel.close();
|
||||
if (outChannel != null)
|
||||
outChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the database from the sdcard
|
||||
* @return true if successful
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public static void restore(Context context){
|
||||
File dbFile = new File(Environment.getDataDirectory() + "/data/"+context.getPackageName()+"/shared_prefs/"+SETTINGS+".xml");
|
||||
|
||||
File exportDir = new File(Environment.getExternalStorageDirectory(), "/"+context.getString(R.string.app_name));
|
||||
if (!exportDir.exists()) {
|
||||
exportDir.mkdirs();
|
||||
}
|
||||
File file = new File(exportDir, dbFile.getName());
|
||||
|
||||
try {
|
||||
file.createNewFile();
|
||||
copyFile(file, dbFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
context.getSharedPreferences(SETTINGS, Context.MODE_WORLD_WRITEABLE).edit().remove(IS_FIRST_RINGER_PROCESSING).remove(IS_DEFAULT).remove(IS_SERVICE_STARTED).commit();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @author Twenty Codes
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* this class will be a simple TextView to be used in a preference activity. you set the text using the set title tag
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class TextViewPreference extends Preference {
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
*/
|
||||
public TextViewPreference(Context context) {
|
||||
super(context);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public TextViewPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
*/
|
||||
public TextViewPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates a linear layout the contains only a textview.
|
||||
* (non-Javadoc)
|
||||
* @see android.preference.Preference#onCreateView(android.view.ViewGroup)
|
||||
* @param parent
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected View onCreateView(ViewGroup parent){
|
||||
|
||||
/*
|
||||
* create a vertical linear layout that width and height that wraps content
|
||||
*/
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
params.gravity = Gravity.CENTER;
|
||||
layout.setPadding(15, 5, 10, 5);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
layout.removeAllViews();
|
||||
|
||||
/*
|
||||
* create a textview that will be used to display the title provided in xml
|
||||
* and add it to the lay out
|
||||
*/
|
||||
TextView title = new TextView(getContext());
|
||||
title.setText(getTitle());
|
||||
title.setTextSize(16);
|
||||
title.setTypeface(Typeface.SANS_SERIF);
|
||||
title.setGravity(Gravity.LEFT);
|
||||
title.setLayoutParams(params);
|
||||
|
||||
/*
|
||||
* add the title and the time picker views to the layout
|
||||
*/
|
||||
layout.addView(title);
|
||||
layout.setId(android.R.id.widget_frame);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @author Twenty Codes
|
||||
* @author ricky barrette
|
||||
* @date June 29, 2011
|
||||
*/
|
||||
package com.TwentyCodes.android.LocationRinger.ui;
|
||||
|
||||
import com.TwentyCodes.android.LocationRinger.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* this class will be a simple preference that contains only a text view that will display the application build information
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class VersionInformationPreference extends Preference {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
*/
|
||||
public VersionInformationPreference(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates a linear layout the contains only a textview.
|
||||
* (non-Javadoc)
|
||||
* @see android.preference.Preference#onCreateView(android.view.ViewGroup)
|
||||
* @param parent
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected View onCreateView(ViewGroup parent){
|
||||
|
||||
/*
|
||||
* get the build information, and build the string
|
||||
*/
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(mContext.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 = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a vertical linear layout that width and height that wraps content
|
||||
*/
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
// params.gravity = Gravity.CENTER;
|
||||
layout.setPadding(15, 5, 10, 5);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
layout.removeAllViews();
|
||||
|
||||
/*
|
||||
* create a textview that will be used to display the application's name and build information
|
||||
* and add it to the layout
|
||||
*/
|
||||
TextView title = new TextView(getContext());
|
||||
title.setText(mContext.getString(R.string.app_name)+" "+pi.versionName+" bulid "+pi.versionCode);
|
||||
title.setTextSize(16);
|
||||
title.setTypeface(Typeface.SANS_SERIF);
|
||||
title.setGravity(Gravity.LEFT);
|
||||
title.setLayoutParams(params);
|
||||
|
||||
/*
|
||||
* add the title views to the layout
|
||||
*/
|
||||
layout.addView(title);
|
||||
layout.setId(android.R.id.widget_frame);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user