Separate fragments for all activity kinds and just sleep #45

master
cpfeiffer 2015-07-13 21:54:46 +02:00
parent 8b44f90bb6
commit 04e628b2d1
6 changed files with 98 additions and 89 deletions

View File

@ -67,7 +67,7 @@ public abstract class AbstractChartFragment extends Fragment {
return provider; return provider;
} }
protected ArrayList<GBActivitySample> getAllSamples(GBDevice device, int tsFrom, int tsTo) { protected List<GBActivitySample> getAllSamples(GBDevice device, int tsFrom, int tsTo) {
if (tsFrom == -1) { if (tsFrom == -1) {
tsFrom = getTSLast24Hours(); tsFrom = getTSLast24Hours();
} }
@ -80,7 +80,7 @@ public abstract class AbstractChartFragment extends Fragment {
return (int) ((now / 1000) - (24 * 60 * 60) & 0xffffffff); // -24 hours return (int) ((now / 1000) - (24 * 60 * 60) & 0xffffffff); // -24 hours
} }
protected ArrayList<GBActivitySample> getActivitySamples(GBDevice device, int tsFrom, int tsTo) { protected List<GBActivitySample> getActivitySamples(GBDevice device, int tsFrom, int tsTo) {
if (tsFrom == -1) { if (tsFrom == -1) {
tsFrom = getTSLast24Hours(); tsFrom = getTSLast24Hours();
} }
@ -89,7 +89,7 @@ public abstract class AbstractChartFragment extends Fragment {
} }
protected ArrayList<GBActivitySample> getSleepSamples(GBDevice device, int tsFrom, int tsTo) { protected List<GBActivitySample> getSleepSamples(GBDevice device, int tsFrom, int tsTo) {
if (tsFrom == -1) { if (tsFrom == -1) {
tsFrom = getTSLast24Hours(); tsFrom = getTSLast24Hours();
} }
@ -97,7 +97,7 @@ public abstract class AbstractChartFragment extends Fragment {
return GBApplication.getActivityDatabaseHandler().getSleepSamples(tsFrom, tsTo, provider); return GBApplication.getActivityDatabaseHandler().getSleepSamples(tsFrom, tsTo, provider);
} }
protected ArrayList<GBActivitySample> getTestSamples(GBDevice device, int tsFrom, int tsTo) { protected List<GBActivitySample> getTestSamples(GBDevice device, int tsFrom, int tsTo) {
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.clear(); cal.clear();
cal.set(2015, Calendar.JUNE, 10, 6, 40); cal.set(2015, Calendar.JUNE, 10, 6, 40);
@ -139,7 +139,7 @@ public abstract class AbstractChartFragment extends Fragment {
} }
// ArrayList<GBActivitySample> samples = getTestSamples(mGBDevice, -1, -1); // ArrayList<GBActivitySample> samples = getTestSamples(mGBDevice, -1, -1);
ArrayList<GBActivitySample> samples = getSleepSamples(mGBDevice, -1, -1); List<GBActivitySample> samples = getSamples(mGBDevice, -1, -1);
Calendar cal = GregorianCalendar.getInstance(); Calendar cal = GregorianCalendar.getInstance();
cal.clear(); cal.clear();
@ -275,6 +275,8 @@ public abstract class AbstractChartFragment extends Fragment {
} }
} }
protected abstract List<GBActivitySample> getSamples(GBDevice device, int tsFrom, int tsTo);
protected abstract void setupLegend(BarLineChartBase chart); protected abstract void setupLegend(BarLineChartBase chart);
protected BarEntry createBarEntry(float value, int index) { protected BarEntry createBarEntry(float value, int index) {

View File

@ -4,37 +4,26 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.github.mikephil.charting.animation.Easing;
import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.BarLineChartBase;
import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.ControlCenter; import nodomain.freeyourgadget.gadgetbridge.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.charts.SleepUtils;
public class ActivitySleepChartFragment extends AbstractChartFragment { public class ActivitySleepChartFragment extends AbstractChartFragment {
@ -146,4 +135,9 @@ public class ActivitySleepChartFragment extends AbstractChartFragment {
chart.getLegend().setColors(legendColors); chart.getLegend().setColors(legendColors);
chart.getLegend().setLabels(legendLabels); chart.getLegend().setLabels(legendLabels);
} }
@Override
protected List<GBActivitySample> getSamples(GBDevice device, int tsFrom, int tsTo) {
return getAllSamples(device, tsFrom, tsTo);
}
} }

View File

@ -63,20 +63,21 @@ public class ChartsActivity extends FragmentActivity {
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
if (position == 0) {
return new ActivitySleepChartFragment();
}
// getItem is called to instantiate the fragment for the given page. // getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below). switch (position) {
return PlaceholderFragment.newInstance(position + 1); case 0:
return new ActivitySleepChartFragment();
case 1:
return new SleepChartFragment();
}
return null;
} }
@Override @Override
public int getCount() { public int getCount() {
return 1; // Show 2 total pages.
// Show 3 total pages. return 2;
// return 3;
} }
@Override @Override
@ -93,41 +94,4 @@ public class ChartsActivity extends FragmentActivity {
return null; return null;
} }
} }
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dummy, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
int number = getArguments().getInt(ARG_SECTION_NUMBER);
textView.setText("Fragment " + number);
return rootView;
}
}
} }

View File

@ -4,38 +4,26 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.github.mikephil.charting.animation.Easing;
import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.BarLineChartBase;
import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.ControlCenter; import nodomain.freeyourgadget.gadgetbridge.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.charts.SleepUtils;
public class SleepChartFragment extends AbstractChartFragment { public class SleepChartFragment extends AbstractChartFragment {
@ -87,10 +75,16 @@ public class SleepChartFragment extends AbstractChartFragment {
return rootView; return rootView;
} }
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mReceiver);
super.onDestroy();
}
private void setupChart() { private void setupChart() {
mChart.setBackgroundColor(BACKGROUND_COLOR); mChart.setBackgroundColor(BACKGROUND_COLOR);
mChart.setDescriptionColor(DESCRIPTION_COLOR); mChart.setDescriptionColor(DESCRIPTION_COLOR);
configureBarLineChartDefaults(mChart);
XAxis x = mChart.getXAxis(); XAxis x = mChart.getXAxis();
x.setDrawLabels(true); x.setDrawLabels(true);
@ -128,17 +122,9 @@ public class SleepChartFragment extends AbstractChartFragment {
mChart.invalidate(); mChart.invalidate();
} }
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mReceiver);
super.onDestroy();
}
protected void setupLegend(BarLineChartBase chart) { protected void setupLegend(BarLineChartBase chart) {
List<Integer> legendColors = new ArrayList<>(3); List<Integer> legendColors = new ArrayList<>(3);
List<String> legendLabels = new ArrayList<>(3); List<String> legendLabels = new ArrayList<>(3);
legendColors.add(akActivity.color);
legendLabels.add(akActivity.label);
legendColors.add(akLightSleep.color); legendColors.add(akLightSleep.color);
legendLabels.add(akLightSleep.label); legendLabels.add(akLightSleep.label);
legendColors.add(akDeepSleep.color); legendColors.add(akDeepSleep.color);
@ -146,4 +132,9 @@ public class SleepChartFragment extends AbstractChartFragment {
chart.getLegend().setColors(legendColors); chart.getLegend().setColors(legendColors);
chart.getLegend().setLabels(legendLabels); chart.getLegend().setLabels(legendLabels);
} }
@Override
protected List<GBActivitySample> getSamples(GBDevice device, int tsFrom, int tsTo) {
return super.getSleepSamples(device, tsFrom, tsTo);
}
} }

View File

@ -33,6 +33,13 @@ public final class BtLEQueue {
private GBDevice mGbDevice; private GBDevice mGbDevice;
private BluetoothAdapter mBluetoothAdapter; private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt; private BluetoothGatt mBluetoothGatt;
/**
* When an automatic reconnect was attempted after a connection breakdown (error)
*/
private long lastReconnectTime = System.currentTimeMillis();
private static final long MIN_MILLIS_BEFORE_RECONNECT = 1000 * 60 * 5; // 5 minutes
private volatile BlockingQueue<Transaction> mTransactions = new LinkedBlockingQueue<Transaction>(); private volatile BlockingQueue<Transaction> mTransactions = new LinkedBlockingQueue<Transaction>();
private volatile boolean mDisposed; private volatile boolean mDisposed;
private volatile boolean mCrashed; private volatile boolean mCrashed;
@ -169,16 +176,29 @@ public final class BtLEQueue {
} }
} }
private void handleDisconnected() { private void handleDisconnected(int status) {
mTransactions.clear(); mTransactions.clear();
if (mWaitForActionResultLatch != null) { if (mWaitForActionResultLatch != null) {
mWaitForActionResultLatch.countDown(); mWaitForActionResultLatch.countDown();
} }
setDeviceConnectionState(State.NOT_CONNECTED); setDeviceConnectionState(State.NOT_CONNECTED);
// either we've been disconnected because the device is out of range // either we've been disconnected because the device is out of range
// or because of an explicit @{link #disconnect()) // or because of an explicit @{link #disconnect())
// To support automatic reconnection, we keep the mBluetoothGatt instance // To support automatic reconnection, we keep the mBluetoothGatt instance
// alive (we do not close() it). // alive (we do not close() it). Unfortunately we sometimes have problems
// reconnecting automatically, so we try to fix this by re-creating mBluetoothGatt.
if (status != 0 ) {
maybeReconnect();
}
}
private void maybeReconnect() {
long currentTime = System.currentTimeMillis();
if (currentTime - lastReconnectTime >= MIN_MILLIS_BEFORE_RECONNECT) {
lastReconnectTime = currentTime;
connect();
}
} }
public void dispose() { public void dispose() {
@ -259,7 +279,7 @@ public final class BtLEQueue {
break; break;
case BluetoothProfile.STATE_DISCONNECTED: case BluetoothProfile.STATE_DISCONNECTED:
LOG.info("Disconnected from GATT server."); LOG.info("Disconnected from GATT server.");
handleDisconnected(); handleDisconnected(status);
break; break;
case BluetoothProfile.STATE_CONNECTING: case BluetoothProfile.STATE_CONNECTING:
LOG.info("Connecting to GATT server..."); LOG.info("Connecting to GATT server...");

View File

@ -11,13 +11,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import nodomain.freeyourgadget.gadgetbridge.GB; import nodomain.freeyourgadget.gadgetbridge.GB;
import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript; import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.*; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.DATABASE_NAME;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
public class ActivityDatabaseHandler extends SQLiteOpenHelper { public class ActivityDatabaseHandler extends SQLiteOpenHelper {
@ -143,7 +149,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper {
timestamp_to = Integer.MAX_VALUE; // dont know what happens when I use more than max of a signed int timestamp_to = Integer.MAX_VALUE; // dont know what happens when I use more than max of a signed int
} }
ArrayList<GBActivitySample> GBActivitySampleList = new ArrayList<GBActivitySample>(); ArrayList<GBActivitySample> GBActivitySampleList = new ArrayList<GBActivitySample>();
final String where = "(provider=" + provider + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + ")"; final String where = "(provider=" + provider + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + getWhereClauseFor(activityTypes) +")";
final String order = "timestamp"; final String order = "timestamp";
try (SQLiteDatabase db = this.getReadableDatabase()) { try (SQLiteDatabase db = this.getReadableDatabase()) {
Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order); Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order);
@ -163,4 +169,36 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper {
return GBActivitySampleList; return GBActivitySampleList;
} }
private String getWhereClauseFor(int activityTypes) {
if (activityTypes == TYPE_ALL) {
return ""; // no further restriction
}
StringBuilder builder = new StringBuilder(" and (");
byte[] dbActivityTypes = mapToDBActivityTypes(activityTypes);
for (int i = 0; i < dbActivityTypes.length; i++) {
builder.append(" type=").append(dbActivityTypes[i]);
if (i + 1 < dbActivityTypes.length) {
builder.append(" or ");
}
}
builder.append(')');
return builder.toString();
}
private byte[] mapToDBActivityTypes(int types) {
byte[] result = new byte[3];
int i = 0;
if ((types & TYPE_ACTIVITY) != 0) {
result[i++] = GBActivitySample.TYPE_UNKNOWN;
}
if ((types & TYPE_DEEP_SLEEP) != 0) {
result[i++] = GBActivitySample.TYPE_DEEP_SLEEP;
}
if ((types & TYPE_LIGHT_SLEEP) != 0) {
result[i++] = GBActivitySample.TYPE_LIGHT_SLEEP;
}
return Arrays.copyOf(result, i);
}
} }