Make app more android like

Changed preferences to use android stype prefs
Allowed values to be passed to main screen
Start and stop ride in main menu
This commit is contained in:
Chet Henry
2014-11-28 02:34:11 -07:00
parent 7b84ea2355
commit 7d9c596ceb
12 changed files with 389 additions and 495 deletions

View File

@@ -30,5 +30,9 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.ridelogger.SettingsActivity"
android:label="@string/setting_title" >
</activity>
</application>
</manifest>
</manifest>

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AndroidXML>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/GridLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:columnCount="2"
android:rowCount="4"
android:orientation="horizontal"
tools:context=".GridXMLActivity" >
</GridLayout>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LayoutData"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" >
</TableLayout>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<preference-headers
xmlns:android="http://schemas.android.com/apk/res/android">
<header android:fragment="com.ridelogger.SettingsActivity$GeneralFragment"
android:title="@string/setting_general_title"
android:summary="@string/setting_general_note" />
<header android:fragment="com.ridelogger.SettingsActivity$AntFragment"
android:title="@string/setting_ant_title"
android:summary="@string/setting_ant_note" />
</preference-headers>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/Start"
android:title="@string/start" />
<item android:id="@+id/Stop"
android:title="@string/stop" />
<item android:id="@+id/Settings"
android:title="@string/edit_settings"
android:showAsAction="never" />
</menu>

View File

@@ -20,7 +20,7 @@
<string name="ant_setup_note">Pair your Ant+ devices now?</string>
<string name="ant_pair_dialog_title">Select Ant Devices</string>
<string name="ant_pair_dialog_button_label">Pair</string>
<string name="ant_pair_dialog_button_note">Pair</string>
<string name="gc_rider_name_dialog_title">Enter Rider Name</string>
<string name="gc_rider_name_dialog_note">What is your Golder Cheata Rider Name?</string>
@@ -42,13 +42,13 @@
<string name="ride_start_title">Start Ride</string>
<string name="ride_start_note">Make sure locations is turned on. Internet connection is NOT required.</string>
<string name="start_and_close">Start</string>
<string name="start">Start Logging</string>
<string name="edit_settings">Settings</string>
<string name="ride_stop_title">Ride in Progress</string>
<string name="ride_stop_note">Would you like to stop the ride or view current values.</string>
<string name="stop_and_close">Stop</string>
<string name="stop">Stop Logging</string>
<string name="view">View</string>
<string name="crash_warning">WARNING CRASH!</string>
@@ -57,7 +57,23 @@
<string name="crash_magnitude">Mag</string>
<string name="ride_start_sms">I\'m starting my ride.</string>
<string name="ride_stop_sms">I\'m starting my ride.</string>
<string name="ride_stop_sms">I have finished my ride.</string>
<string name="riding_ok_sms">I\'m ok.</string>
<string name="setting_title">Settings</string>
<string name="setting_general_title">General</string>
<string name="setting_general_note">Settings</string>
<string name="setting_ant_title">Ant+</string>
<string name="setting_ant_note">Setup your Ant+ Devices</string>
<string name="PREFS_NAME">RideLogger</string>
<string name="PREF_RIDER_NAME">RiderName</string>
<string name="PREF_EMERGENCY_NUMBER">EmergencyNumbuer</string>
<string name="PREF_DETECT_CRASH">DetectCrash</string>
<string name="PREF_PHONE_HOME">PhoneHome</string>
<string name="PREF_PAIRED_ANTS">PairedAnts</string>
<string name="PREF_PHONE_HOME_PERIOD">PhoneHomePeriod</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="@string/PREFS_NAME">
<com.ridelogger.DynamicMultiSelectListPreference
android:key="@string/PREF_PAIRED_ANTS"
android:title="@string/ant_pair_dialog_title"
android:summary="@string/ant_pair_dialog_button_note"
/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="@string/PREFS_NAME"
android:persistent="true">
<EditTextPreference
android:key="@string/PREF_RIDER_NAME"
android:title="@string/gc_rider_name_dialog_title"
android:summary="@string/gc_rider_name_dialog_note" />
<EditTextPreference
android:key="@string/PREF_EMERGENCY_NUMBER"
android:title="@string/emergency_contact_number_dialog_title"
android:summary="@string/emergency_contact_number_dialog_note" />
<CheckBoxPreference
android:layout="?android:attr/preferenceLayoutChild"
android:dependency="@string/PREF_EMERGENCY_NUMBER"
android:key="@string/PREF_DETECT_CRASH"
android:title="@string/crash_detection_dialog_title"
android:summary="@string/crash_detection_dialog_note" />
<!-- The visual style of a child is defined by this styled theme attribute. -->
<CheckBoxPreference
android:layout="?android:attr/preferenceLayoutChild"
android:dependency="@string/PREF_EMERGENCY_NUMBER"
android:key="@string/PREF_PHONE_HOME"
android:title="@string/emergency_contact_dialog_title"
android:summary="@string/emergency_contact_dialog_note" />
<EditTextPreference
android:layout="?android:attr/preferenceLayoutChild"
android:dependency="@string/PREF_PHONE_HOME"
android:key="@string/PREF_PHONE_HOME_PERIOD"
android:title="@string/sms_period_dialog_title"
android:summary="@string/sms_period_dialog_note" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,24 @@
package com.ridelogger;
import android.preference.MultiSelectListPreference;
import android.util.AttributeSet;
import android.app.Dialog;
import android.content.Context;
public class DynamicMultiSelectListPreference extends MultiSelectListPreference {
public DynamicMultiSelectListPreference(Context context) {
super(context);
}
public DynamicMultiSelectListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void refresh() {
Dialog test = getDialog();
if(test != null && test.isShowing()) {
test.dismiss();
showDialog(null);
}
}
}

View File

@@ -22,7 +22,6 @@ import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import com.ridelogger.R;
import com.ridelogger.listners.Base;
import com.ridelogger.listners.Gps;
import com.ridelogger.listners.HeartRate;
@@ -43,6 +42,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.telephony.SmsManager;
@@ -80,8 +80,13 @@ public class RideService extends Service
class IncomingHandler extends Handler { // Handler of incoming messages from clients.
@Override
public void handleMessage(Message msg) {
if(timerUI != null) {
timerUI.cancel();
}
if(msg.replyTo != null && timerUI != null) {
timerUI = new Timer();
if(msg.replyTo != null) {
replyTo = msg.replyTo;
timerUI.scheduleAtFixedRate(
new TimerTask() {
@@ -118,7 +123,6 @@ public class RideService extends Service
*/
@Override
public IBinder onBind(Intent arg0) {
timerUI = new Timer();
return mMessenger.getBinder();
}
@@ -166,9 +170,10 @@ public class RideService extends Service
String month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US);
String weekDay = cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US);
String year = Integer.toString(cal.get(Calendar.YEAR));
settings = getSharedPreferences(StartActivity.PREFS_NAME, 0);
emergencyNumbuer = settings.getString(StartActivity.EMERGENCY_NUMBER, "");
pairedAnts = settings.getStringSet(StartActivity.PAIRED_ANTS, null);
settings = PreferenceManager.getDefaultSharedPreferences(this);
emergencyNumbuer = settings.getString(getString(R.string.PREF_EMERGENCY_NUMBER), "");
pairedAnts = settings.getStringSet(getString(R.string.PREF_PAIRED_ANTS), null);
currentValues.put("SECS", "0.0");
@@ -179,7 +184,7 @@ public class RideService extends Service
"\"DEVICETYPE\":\"Android\"," +
"\"IDENTIFIER\":\"\"," +
"\"TAGS\":{" +
"\"Athlete\":\"" + settings.getString(StartActivity.RIDER_NAME, "") + "\"," +
"\"Athlete\":\"" + settings.getString(getString(R.string.PREF_RIDER_NAME), "") + "\"," +
"\"Calendar Text\":\"Auto Recored Android Ride\"," +
"\"Change History\":\"\"," +
"\"Data\":\"\"," +
@@ -256,9 +261,9 @@ public class RideService extends Service
}
rideStarted = true;
if(settings.getBoolean(StartActivity.PHONE_HOME, false)) {
if(settings.getBoolean(getString(R.string.PREF_PHONE_HOME), false)) {
timer = new Timer();
int period = Integer.parseInt(settings.getString(StartActivity.PHONE_HOME_PERIOD, "10"));
int period = Integer.parseInt(settings.getString(getString(R.string.PREF_PHONE_HOME_PERIOD), "10"));
timer.scheduleAtFixedRate(
new TimerTask() {
@@ -278,7 +283,7 @@ public class RideService extends Service
.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.ride_on))
.setContentText(getString(R.string.building_ride) + fileName + getString(R.string.click_to_stop))
.setContentText(getString(R.string.building_ride) + " " + fileName + " " + getString(R.string.click_to_stop))
.setProgress(0, 0, true)
.setContentIntent(
TaskStackBuilder
@@ -312,7 +317,7 @@ public class RideService extends Service
* confirm the crash if we are not moving
*/
public void phoneCrashConfirm() {
String body = getString(R.string.crash_warning) + "!\n";
String body = getString(R.string.crash_confirm) + "!\n";
if(currentValues.containsKey("LAT") && currentValues.containsKey("LON")) {
body = body + "https://www.google.com/maps/place/" + currentValues.get("LAT") + "," + currentValues.get("LON");
} else {

View File

@@ -0,0 +1,131 @@
package com.ridelogger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
public class SettingsActivity extends PreferenceActivity {
/**
* This fragment contains a second-level set of preference that you
* can get to by tapping an item in the first preferences fragment.
*/
public static class GeneralFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.general_settings);
}
}
@Override
public boolean isValidFragment(String fragment) {
return true;
}
/**
* This fragment contains a second-level set of preference that you
* can get to by tapping an item in the first preferences fragment.
*/
public static class AntFragment extends PreferenceFragment {
private MultiDeviceSearch mSearch;
private DynamicMultiSelectListPreference mMultiSelectListPreference;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.ant_settings);
mMultiSelectListPreference = (DynamicMultiSelectListPreference) findPreference(getString(R.string.PREF_PAIRED_ANTS));
setupAnt();
}
/**
* try to pair some ant+ devices
*/
protected void setupAnt() {
MultiDeviceSearch.SearchCallbacks mCallback;
MultiDeviceSearch.RssiCallback mRssiCallback;
final ArrayList<MultiDeviceSearchResult> foundDevices = new ArrayList<MultiDeviceSearchResult>();
updateList(foundDevices);
mCallback = new MultiDeviceSearch.SearchCallbacks(){
public void onDeviceFound(final MultiDeviceSearchResult deviceFound)
{
if(!foundDevices.contains(deviceFound)) {
foundDevices.add(deviceFound);
updateList(foundDevices);
}
}
@Override
public void onSearchStopped(RequestAccessResult arg0) {}
};
mRssiCallback = new MultiDeviceSearch.RssiCallback() {
@Override
public void onRssiUpdate(final int resultId, final int rssi){}
};
// start the multi-device search
mSearch = new MultiDeviceSearch(this.getActivity(), EnumSet.allOf(DeviceType.class), mCallback, mRssiCallback);
}
/**
* dialog of soon to be paired ant devices
* @param foundDevices
*/
protected void updateList(final ArrayList<MultiDeviceSearchResult> foundDevices) {
ArrayList<CharSequence> foundDevicesString = new ArrayList<CharSequence>();
ArrayList<CharSequence> foundDevicesValues = new ArrayList<CharSequence>();
for(MultiDeviceSearchResult device : foundDevices) {
foundDevicesString.add(device.getAntDeviceType() + ": " + String.valueOf(device.getAntDeviceNumber()));
}
for(MultiDeviceSearchResult device : foundDevices) {
foundDevicesValues.add(String.valueOf(device.getAntDeviceNumber()));
}
if(mMultiSelectListPreference != null) {
mMultiSelectListPreference.setEntries(
foundDevicesString.toArray(new CharSequence[foundDevicesString.size()])
);
mMultiSelectListPreference.setEntryValues(
foundDevicesValues.toArray(new CharSequence[foundDevicesValues.size()])
);
}
mMultiSelectListPreference.refresh();
}
@Override
public void onDestroy() {
if(mSearch != null) mSearch.close();
super.onDestroy();
}
}
/**
* Populate the activity with the top-level headers.
*/
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.layout.settings, target);
}
}

View File

@@ -1,32 +1,18 @@
package com.ridelogger;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -34,33 +20,29 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.FragmentActivity;
import android.text.InputType;
import android.view.View;
import android.widget.EditText;
import android.widget.GridLayout;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
public class StartActivity extends FragmentActivity
{
Intent rsi;
public static final String PREFS_NAME = "RideLogger";
public static final String RIDER_NAME = "RiderName";
public static final String EMERGENCY_NUMBER = "EmergencyNumbuer";
public static final String DETECT_CRASH = "DetectCrash";
public static final String PHONE_HOME = "PhoneHome";
public static final String PAIRED_ANTS = "PairedAnts";
public static final String PHONE_HOME_PERIOD = "PhoneHomePeriod";
GridLayout grid;
TableLayout layout;
public Map<String, TextView> textViews;
private SharedPreferences settings;
private MultiDeviceSearch mSearch;
private RunningServiceInfo service;
Messenger mService = null;
boolean mIsBound;
BroadcastReceiver mReceiver;
private MenuItem startMenu;
private MenuItem stopMenu;
final Messenger mMessenger = new Messenger(new IncomingHandler());
class IncomingHandler extends Handler {
@@ -77,8 +59,7 @@ public class StartActivity extends FragmentActivity
Message msg = Message.obtain();
msg.replyTo = mMessenger;
mService.send(msg);
}
catch (RemoteException e) {
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
@@ -88,8 +69,33 @@ public class StartActivity extends FragmentActivity
mService = null;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.start_activity, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
if(item.getItemId() == R.id.Settings) {
setupSettings();
} else if(item.getItemId() == R.id.Start) {
startRide();
} else {
stopRide();
}
return true;
}
/**
* start up our class
@@ -97,397 +103,36 @@ public class StartActivity extends FragmentActivity
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
rsi = new Intent(this, RideService.class);
settings = getSharedPreferences(PREFS_NAME, 0);
if(settings.getString(RIDER_NAME, "") == "") {
setupSettings();
} else {
toggleRide();
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
rsi = new Intent(this, RideService.class);
layout = (TableLayout)findViewById(R.id.LayoutData);
textViews = new HashMap<String, TextView>();
}
BroadcastReceiver mReceiver;
@Override
protected void onResume() {
super.onResume();
bindToService();
}
@Override
protected void onPause() {
super.onPause();
unBindToService();
}
/**
* setup the settings for the user
*/
public void setupSettings() {
final Runnable askAntRunnable = new Runnable() {
@Override
public void run() {
final Runnable setupAntRunnable = new Runnable() {
@Override
public void run() {
setupAnt();
}
};
final Runnable skipAntRunnable = new Runnable() {
@Override
public void run() {
toggleRide();
}
};
promptDialogBoolean(getString(R.string.ant_setup_title), getString(R.string.ant_setup_note), setupAntRunnable, skipAntRunnable);
}
};
final Runnable setupPhoneHomePeriod = new Runnable() {
@Override
public void run() {
promptDialogPhone(
getString(R.string.sms_period_dialog_title),
getString(R.string.sms_period_dialog_note),
PHONE_HOME_PERIOD,
askAntRunnable
);
}
};
final Runnable setupPhoneHomeRunnable = new Runnable() {
@Override
public void run() {
promptDialogBoolean(
getString(R.string.emergency_contact_dialog_title),
getString(R.string.emergency_contact_dialog_note),
PHONE_HOME,
setupPhoneHomePeriod
);
}
};
final Runnable setupDetectCrashRunnable = new Runnable() {
@Override
public void run() {
promptDialogBoolean(
getString(R.string.crash_detection_dialog_title),
getString(R.string.crash_detection_dialog_note),
DETECT_CRASH,
setupPhoneHomeRunnable
);
}
};
Runnable setupEmergencyContactRunnable = new Runnable() {
@Override
public void run() {
promptDialogPhone(
getString(R.string.emergency_contact_number_dialog_title),
getString(R.string.emergency_contact_number_dialog_note),
EMERGENCY_NUMBER,
setupDetectCrashRunnable
);
}
};
promptDialogInput(
getString(R.string.gc_rider_name_dialog_title),
getString(R.string.gc_rider_name_dialog_note),
RIDER_NAME,
setupEmergencyContactRunnable
);
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
/**
* TextBox Dialog Prompt
* @param title
* @param message
* @param settingSaveKey
* @param callBack
*/
public void promptDialogInput(String title, String message, final String settingSaveKey, final Runnable callBack) {
// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setText(settings.getString(settingSaveKey, ""));
OnClickListener positiveClick = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String value = input.getText().toString();
if(value != "" && value != null) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(settingSaveKey, value).commit();
callBack.run();
}
}
};
promptDialog(title, message, input, positiveClick);
}
/**
* TextBox Dialog Prompt
* @param title
* @param message
* @param settingSaveKey
* @param callBack
*/
public void promptDialogPhone(String title, String message, final String settingSaveKey, final Runnable callBack) {
// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_PHONE);
input.setText(settings.getString(settingSaveKey, ""));
OnClickListener positiveClick = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String value = input.getText().toString();
if(value != "" && value != null) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(settingSaveKey, value).commit();
callBack.run();
}
}
};
promptDialog(title, message, input, positiveClick);
}
/**
* Boolean dialog prompt
* @param title
* @param message
* @param settingSaveKey
* @param positiveCallback
*/
public void promptDialogBoolean(String title, String message, Runnable positiveCallback, Runnable negativeCallback) {
promptDialogBoolean(title, message, null, positiveCallback, negativeCallback);
}
/**
* Boolean dialog prompt
* @param title
* @param message
* @param settingSaveKey
* @param positiveCallback
*/
public void promptDialogBoolean(String title, String message, String settingSaveKey, Runnable positiveCallback) {
promptDialogBoolean(title, message, settingSaveKey, positiveCallback, positiveCallback);
}
/**
* Boolean dialog prompt
* @param title
* @param message
* @param settingSaveKey
* @param positiveCallback
*/
public void promptDialogBoolean(String title, String message, Runnable positiveCallback, Runnable negativeCallback, String positiveButtonLabel, String negativeButtonLabel) {
promptDialogBoolean(title, message, null, positiveCallback, negativeCallback, positiveButtonLabel, negativeButtonLabel);
}
/**
* Boolean dialog prompt
* @param title
* @param message
* @param settingSaveKey
* @param positiveCallback
*/
public void promptDialogBoolean(String title, String message, String settingSaveKey, Runnable positiveCallback, Runnable negativeCallback) {
promptDialogBoolean(title, message, settingSaveKey, positiveCallback, negativeCallback, getString(R.string.boolean_dialog_yes), getString(R.string.boolean_dialog_no));
}
/**
* Boolean dialog prompt
* @param title
* @param message
* @param settingSaveKey
* @param positiveCallback
* @param negativeCallback
*/
public void promptDialogBoolean(String title, String message, final String settingSaveKey, final Runnable positiveCallback, final Runnable negativeCallback, String positiveButtonLabel, String negativeButtonLabel) {
OnClickListener positiveClick = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if(settingSaveKey != null) {
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(settingSaveKey, true).commit();
}
positiveCallback.run();
}
};
OnClickListener negativeClick = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if(settingSaveKey != null) {
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(settingSaveKey, false).commit();
}
negativeCallback.run();
}
};
promptDialog(title, message, null, positiveClick, positiveButtonLabel, negativeClick, negativeButtonLabel);
}
/**
* very general dialog prompt without positiveLabel
* @param title
* @param message
* @param view
* @param positiveClick
*/
public void promptDialog(
String title,
String message,
View view,
OnClickListener positiveClick
) {
promptDialog(title, message, view, positiveClick, null, null, null);
}
/**
* very general dialog prompt
* @param title
* @param message
* @param view
* @param positiveClick
* @param positiveLabel
*/
public void promptDialog(
String title,
String message,
View view,
OnClickListener positiveClick,
String positiveLabel,
OnClickListener negativeClick,
String negativeLabel
) {
if(positiveLabel == null) positiveLabel = getString(R.string.save_setting_button);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(message)
.setTitle(title)
.setPositiveButton(positiveLabel, positiveClick);
if(view != null) {
builder.setView(view);
}
if(negativeClick != null) {
if(negativeLabel == null) negativeLabel = getString(R.string.skip_setting_button);
builder.setNegativeButton(negativeLabel, negativeClick);
}
AlertDialog dialog = builder.create();
// 3. Get the AlertDialog from create()
dialog.show();
}
/**
* try to pair some ant+ devices
*/
protected void setupAnt() {
MultiDeviceSearch.SearchCallbacks mCallback;
MultiDeviceSearch.RssiCallback mRssiCallback;
final ArrayList<MultiDeviceSearchResult> foundDevices = new ArrayList<MultiDeviceSearchResult>();
selectDevicesDialog(foundDevices);
mCallback = new MultiDeviceSearch.SearchCallbacks(){
public void onDeviceFound(final MultiDeviceSearchResult deviceFound)
{
if(!foundDevices.contains(deviceFound)) {
foundDevices.add(deviceFound);
selectDevicesDialog(foundDevices);
}
}
@Override
public void onSearchStopped(RequestAccessResult arg0) {}
};
mRssiCallback = new MultiDeviceSearch.RssiCallback() {
@Override
public void onRssiUpdate(final int resultId, final int rssi){}
};
// start the multi-device search
mSearch = new MultiDeviceSearch(this, EnumSet.allOf(DeviceType.class), mCallback, mRssiCallback);
}
/**
* dialog of soon to be paired ant devices
* @param foundDevices
*/
protected void selectDevicesDialog(final ArrayList<MultiDeviceSearchResult> foundDevices) {
final ArrayList<Integer> mSelectedItems = new ArrayList<Integer>(); // Where we track the selected items
final ArrayList<CharSequence> foundDevicesString = new ArrayList<CharSequence>();
for(MultiDeviceSearchResult device : foundDevices) {
foundDevicesString.add(device.getAntDeviceType() + " - " + device.getDeviceDisplayName());
}
CharSequence[] foundDevicesCharSeq = foundDevicesString.toArray(new CharSequence[foundDevicesString.size()]);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// Set the dialog title
builder.setTitle(getString(R.string.ant_pair_dialog_title))
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(foundDevicesCharSeq, null, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(getString(R.string.ant_pair_dialog_button_label), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
ArrayList<String> ids = new ArrayList<String>();
for(Integer index : mSelectedItems) {
ids.add(Integer.toString(foundDevices.get(index).getAntDeviceNumber()));
}
SharedPreferences.Editor editor = settings.edit();
editor.putStringSet(PAIRED_ANTS, new HashSet<String>(ids));
editor.commit();
toggleRide();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
protected void onDestroy() {
if(mSearch != null) mSearch.close();
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
super.onDestroy();
finish();
}
/**
* stop ride and clean up references
*/
@@ -495,67 +140,31 @@ public class StartActivity extends FragmentActivity
Toast toast = Toast.makeText(getApplicationContext(), getString(R.string.stopping_ride), Toast.LENGTH_LONG);
toast.show();
this.stopService(rsi);
finish();
}
/**
* start or stop ride
* tell the service to start sending us messages with current values
*/
protected void toggleRide() {
public void bindToService() {
service = getServiceRunning(RideService.class);
if(service == null) {
final Runnable startAndCloseRunnable = new Runnable() {
@Override
public void run() {
startRide();
finish();
}
};
final Runnable settingsRunnable = new Runnable() {
@Override
public void run() {
setupSettings();
}
};
promptDialogBoolean(
getString(R.string.ride_start_title),
getString(R.string.ride_start_note),
startAndCloseRunnable,
settingsRunnable,
getString(R.string.start_and_close),
getString(R.string.edit_settings)
);
} else {
if(service != null) {
final StartActivity that = this;
final Runnable viewRunnable = new Runnable() {
@Override
public void run() {
bindService(new Intent(that, RideService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
setContentView(R.layout.activity_dashboard);
textViews = new HashMap<String, TextView>();
grid = (GridLayout)findViewById(R.id.GridLayout1);
}
};
final Runnable stopRunnable = new Runnable() {
@Override
public void run() {
stopRide();
finish();
}
};
promptDialogBoolean(
getString(R.string.ride_stop_title),
getString(R.string.ride_stop_note),
stopRunnable,
viewRunnable,
getString(R.string.stop_and_close),
getString(R.string.view)
);
bindService(new Intent(that, RideService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
/**
* tell the service to stop sending us messages with current values
*/
public void unBindToService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
@@ -569,18 +178,41 @@ public class StartActivity extends FragmentActivity
Map<String, String> currentValues = (Map<String, String>) bundle.getSerializable("currentValues");
TextView tv;
Iterator<Entry<String, String>> it = currentValues.entrySet().iterator();
while (it.hasNext()) {
Entry<String, String> entry = it.next();
String key = entry.getKey();
if(!textViews.containsKey(key)) {
tv = new TextView(this);
tv.setTextAppearance(this, android.R.attr.textAppearanceLarge);
tv.setTypeface(null, Typeface.BOLD);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);
textViews.put(key, tv);
grid.addView(tv);
layout.addView(tv);
}
textViews.get(key).setText(entry.getValue() + " " + key);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
service = getServiceRunning(RideService.class);
startMenu = menu.findItem(R.id.Start);
stopMenu = menu.findItem(R.id.Stop);
if(service == null) {
startMenu.setVisible(true);
stopMenu.setVisible(false);
} else {
startMenu.setVisible(false);
stopMenu.setVisible(true);
}
return true;
}
/**
* start the ride and notify the user of success
@@ -588,6 +220,11 @@ public class StartActivity extends FragmentActivity
private void startRide() {
this.startService(rsi);
startMenu.setVisible(false);
stopMenu.setVisible(true);
bindToService();
Toast toast = Toast.makeText(getApplicationContext(), getString(R.string.starting_ride), Toast.LENGTH_LONG);
toast.show();
}

View File

@@ -5,8 +5,8 @@ import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import com.ridelogger.R;
import com.ridelogger.RideService;
import com.ridelogger.StartActivity;
import android.content.Context;
import android.hardware.Sensor;
@@ -63,7 +63,7 @@ public class Sensors extends Base<Object>
mSensorManager.registerListener(luxListner, mLight, 3000000);
}
if(mAccel != null) {
if(context.settings.getBoolean(StartActivity.DETECT_CRASH, false)) {
if(context.settings.getBoolean(context.getString(R.string.PREF_DETECT_CRASH), false)) {
accelListner = new SensorEventListener() {
private boolean crashed = false;
private Timer timer = new Timer();