Sensor settings: added NONE bluetooth sensor.

This commit is contained in:
Dennis Guse
2019-07-20 00:21:27 +02:00
parent 1e1d4f6f4b
commit 3ef1ae4b09
24 changed files with 237 additions and 1187 deletions
-3
View File
@@ -8,7 +8,6 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 28
testApplicationId "com.google.android.maps.mytracks.test"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -22,8 +21,6 @@ android {
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.protobuf:protobuf-java:2.5.0'
androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
@@ -16,12 +16,12 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track;
import android.location.Location; import android.location.Location;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.sensor.Sensor.SensorDataSet;
/** /**
* Commons utilities for creating stubs of track, location. The class will be * Commons utilities for creating stubs of track, location. The class will be
* enriched if needs more similar stubs for test. * enriched if needs more similar stubs for test.
@@ -679,7 +679,7 @@ public class MyTracksProviderUtilsImplTest {
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn( AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn(
index++); index++);
// Sensor // Sensor
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR)).andReturn( AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_HEARTRATE)).andReturn(
index++); index++);
// Set return value of isNull(). // Set return value of isNull().
@@ -24,8 +24,8 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.google.android.apps.mytracks.ChartView; import com.google.android.apps.mytracks.ChartView;
import com.google.android.apps.mytracks.TrackStubUtils; import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.sensor.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.sensor.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.apps.mytracks.util.UnitConversions;
import org.junit.Assert; import org.junit.Assert;
@@ -22,16 +22,15 @@ import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
import android.widget.TextView; import android.widget.TextView;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.sensor.SensorState;
import com.google.android.apps.mytracks.services.ITrackRecordingService; import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection; import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.services.sensors.SensorManager; import com.google.android.apps.mytracks.services.sensors.SensorManager;
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory; import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils; import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils;
import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import com.google.protobuf.InvalidProtocolBufferException;
/** /**
* An activity that displays information about sensors. * An activity that displays information about sensors.
@@ -118,8 +117,8 @@ public class SensorStateActivity extends AbstractActivity {
* Updates from a temp sensor manager. * Updates from a temp sensor manager.
*/ */
private void updateFromTempSensorManager() { private void updateFromTempSensorManager() {
Sensor.SensorState sensorState = Sensor.SensorState.NONE; SensorState sensorState = SensorState.NONE;
Sensor.SensorDataSet sensorDataSet = null; SensorDataSet sensorDataSet = null;
if (tempSensorManager == null) { if (tempSensorManager == null) {
tempSensorManager = SensorManagerFactory.getSensorManagerTemporary(this); tempSensorManager = SensorManagerFactory.getSensorManagerTemporary(this);
@@ -137,28 +136,13 @@ public class SensorStateActivity extends AbstractActivity {
* Updates from the system sensor manager. * Updates from the system sensor manager.
*/ */
private void updateFromSystemSensorManager() { private void updateFromSystemSensorManager() {
Sensor.SensorState sensorState = Sensor.SensorState.NONE;
Sensor.SensorDataSet sensorDataSet = null;
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound(); ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
// Get sensor details from the service.
if (trackRecordingService == null) { if (trackRecordingService == null) {
Log.d(TAG, "Cannot get the track recording service."); Log.d(TAG, "Cannot get the track recording service.");
updateSensorStateAndDataSet(SensorState.NONE, null);
} else { } else {
sensorState = Sensor.SensorState.valueOf(trackRecordingService.getSensorState()); updateSensorStateAndDataSet(trackRecordingService.getSensorState(), trackRecordingService.getSensorData());
try {
byte[] buff = trackRecordingService.getSensorData();
if (buff != null) {
sensorDataSet = Sensor.SensorDataSet.parseFrom(buff);
}
} catch (InvalidProtocolBufferException e) {
Log.e(TAG, "Cannot read sensor data set.", e);
}
} }
updateSensorStateAndDataSet(sensorState, sensorDataSet);
} }
/** /**
@@ -167,8 +151,8 @@ public class SensorStateActivity extends AbstractActivity {
* @param sensorState sensor state * @param sensorState sensor state
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private void updateSensorStateAndDataSet(Sensor.SensorState sensorState, Sensor.SensorDataSet sensorDataSet) { private void updateSensorStateAndDataSet(SensorState sensorState, SensorDataSet sensorDataSet) {
((TextView) findViewById(R.id.sensor_state)).setText(SensorUtils.getStateAsString(sensorState, this)); ((TextView) findViewById(R.id.sensor_state)).setText(SensorState.getStateAsString(sensorState, this));
String lastSensorTime = sensorDataSet == null ? getString(R.string.value_unknown) : getLastSensorTime(sensorDataSet); String lastSensorTime = sensorDataSet == null ? getString(R.string.value_unknown) : getLastSensorTime(sensorDataSet);
String heartRate = sensorDataSet == null ? getString(R.string.value_unknown) : getHeartRate(sensorDataSet); String heartRate = sensorDataSet == null ? getString(R.string.value_unknown) : getHeartRate(sensorDataSet);
@@ -188,7 +172,7 @@ public class SensorStateActivity extends AbstractActivity {
* *
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private String getLastSensorTime(Sensor.SensorDataSet sensorDataSet) { private String getLastSensorTime(SensorDataSet sensorDataSet) {
return DateFormat.format("h:mm:ss aa", sensorDataSet.getCreationTime()).toString(); return DateFormat.format("h:mm:ss aa", sensorDataSet.getCreationTime()).toString();
} }
@@ -197,13 +181,12 @@ public class SensorStateActivity extends AbstractActivity {
* *
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private String getHeartRate(Sensor.SensorDataSet sensorDataSet) { private String getHeartRate(SensorDataSet sensorDataSet) {
String value; String value;
if (sensorDataSet.hasHeartRate() && sensorDataSet.getHeartRate().hasValue() && sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING) { if (sensorDataSet.hasHeartRate()) {
value = getString( value = getString(R.string.sensor_state_heart_rate_value, (int)sensorDataSet.getHeartRate());
R.string.sensor_state_heart_rate_value, sensorDataSet.getHeartRate().getValue());
} else { } else {
value = SensorUtils.getStateAsString(sensorDataSet.hasHeartRate() ? sensorDataSet.getHeartRate().getState() : Sensor.SensorState.NONE, this); value = SensorState.getStateAsString(SensorState.NONE, this);
} }
return value; return value;
} }
@@ -213,15 +196,12 @@ public class SensorStateActivity extends AbstractActivity {
* *
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private String getCadence(Sensor.SensorDataSet sensorDataSet) { private String getCadence(SensorDataSet sensorDataSet) {
String value; String value;
if (sensorDataSet.hasCadence() && sensorDataSet.getCadence().hasValue() if (sensorDataSet.hasCadence()) {
&& sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING) { value = getString(R.string.sensor_state_cadence_value, (int)sensorDataSet.getCadence());
value = getString(R.string.sensor_state_cadence_value, sensorDataSet.getCadence().getValue());
} else { } else {
value = SensorUtils.getStateAsString( value = SensorState.getStateAsString(SensorState.NONE, this);
sensorDataSet.hasCadence() ? sensorDataSet.getCadence().getState()
: Sensor.SensorState.NONE, this);
} }
return value; return value;
} }
@@ -231,15 +211,12 @@ public class SensorStateActivity extends AbstractActivity {
* *
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private String getPower(Sensor.SensorDataSet sensorDataSet) { private String getPower(SensorDataSet sensorDataSet) {
String value; String value;
if (sensorDataSet.hasPower() && sensorDataSet.getPower().hasValue() if (sensorDataSet.hasPower()) {
&& sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING) { value = getString(R.string.sensor_state_power_value, (int)sensorDataSet.getPower());
value = getString(R.string.sensor_state_power_value, sensorDataSet.getPower().getValue());
} else { } else {
value = SensorUtils.getStateAsString( value = SensorState.getStateAsString(SensorState.NONE,this);
sensorDataSet.hasPower() ? sensorDataSet.getPower().getState() : Sensor.SensorState.NONE,
this);
} }
return value; return value;
} }
@@ -249,15 +226,12 @@ public class SensorStateActivity extends AbstractActivity {
* *
* @param sensorDataSet sensor data set * @param sensorDataSet sensor data set
*/ */
private String getBattery(Sensor.SensorDataSet sensorDataSet) { private String getBattery(SensorDataSet sensorDataSet) {
String value; String value;
if (sensorDataSet.hasBatteryLevel() && sensorDataSet.getBatteryLevel().hasValue() if (sensorDataSet.hasBatteryLevel()) {
&& sensorDataSet.getBatteryLevel().getState() == Sensor.SensorState.SENDING) { value = getString(R.string.value_integer_percent, sensorDataSet.getBatteryLevel());
value = getString(R.string.value_integer_percent, sensorDataSet.getBatteryLevel().getValue());
} else { } else {
value = SensorUtils.getStateAsString( value = SensorState.getStateAsString(SensorState.NONE, this);
sensorDataSet.hasBatteryLevel() ? sensorDataSet.getBatteryLevel().getState()
: Sensor.SensorState.NONE, this);
} }
return value; return value;
} }
@@ -15,10 +15,10 @@
*/ */
package com.google.android.apps.mytracks.content; package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import android.location.Location; import android.location.Location;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
/** /**
* This class extends the standard Android location with extra information. * This class extends the standard Android location with extra information.
* *
@@ -33,9 +33,9 @@ public class MyTracksLocation extends Location {
*/ */
private int id = -1; private int id = -1;
public MyTracksLocation(Location location, Sensor.SensorDataSet sd) { public MyTracksLocation(Location location, SensorDataSet sensorDataSet) {
super(location); super(location);
this.sensorDataSet = sd; this.sensorDataSet = sensorDataSet;
} }
public MyTracksLocation(String provider) { public MyTracksLocation(String provider) {
@@ -52,7 +52,7 @@ public class MyTracksProvider extends ContentProvider {
private static final String TAG = MyTracksProvider.class.getSimpleName(); private static final String TAG = MyTracksProvider.class.getSimpleName();
@VisibleForTesting @VisibleForTesting
static final int DATABASE_VERSION = 22; static final int DATABASE_VERSION = 23;
@VisibleForTesting @VisibleForTesting
static final String DATABASE_NAME = "mytracks.db"; static final String DATABASE_NAME = "mytracks.db";
@@ -24,11 +24,10 @@ import android.location.Location;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@@ -999,10 +998,18 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
values.put(TrackPointsColumns.BEARING, location.getBearing()); values.put(TrackPointsColumns.BEARING, location.getBearing());
} }
//SensorData
if (location instanceof MyTracksLocation) { if (location instanceof MyTracksLocation) {
MyTracksLocation myTracksLocation = (MyTracksLocation) location; MyTracksLocation myTracksLocation = (MyTracksLocation) location;
if (myTracksLocation.getSensorDataSet() != null) { SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
values.put(TrackPointsColumns.SENSOR, myTracksLocation.getSensorDataSet().toByteArray()); if (sensorDataSet != null && sensorDataSet.hasHeartRate()) {
values.put(TrackPointsColumns.SENSOR_HEARTRATE, myTracksLocation.getSensorDataSet().getHeartRate());
}
if (sensorDataSet != null && sensorDataSet.hasCadence()) {
values.put(TrackPointsColumns.SENSOR_CADENCE, myTracksLocation.getSensorDataSet().getCadence());
}
if (sensorDataSet != null && sensorDataSet.hasPower()) {
values.put(TrackPointsColumns.SENSOR_POWER, myTracksLocation.getSensorDataSet().getPower());
} }
} }
return values; return values;
@@ -1039,13 +1046,14 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
if (!cursor.isNull(indexes.bearingIndex)) { if (!cursor.isNull(indexes.bearingIndex)) {
location.setBearing(cursor.getFloat(indexes.bearingIndex)); location.setBearing(cursor.getFloat(indexes.bearingIndex));
} }
if (location instanceof MyTracksLocation && !cursor.isNull(indexes.sensorIndex)) { if (location instanceof MyTracksLocation) {
MyTracksLocation myTracksLocation = (MyTracksLocation) location; MyTracksLocation myTracksLocation = (MyTracksLocation) location;
try {
myTracksLocation.setSensorDataSet(SensorDataSet.parseFrom(cursor.getBlob(indexes.sensorIndex))); float heartRate = cursor.isNull(indexes.sensorHeartRateIndex) ? SensorDataSet.DATA_UNAVAILABLE : cursor.getFloat(indexes.sensorHeartRateIndex);
} catch (InvalidProtocolBufferException e) { float cadence = cursor.isNull(indexes.sensorCadenceIndex) ? SensorDataSet.DATA_UNAVAILABLE : cursor.getFloat(indexes.sensorCadenceIndex);
Log.w(TAG, "Failed to parse sensor data.", e); float power = cursor.isNull(indexes.sensorPowerIndex) ? SensorDataSet.DATA_UNAVAILABLE : cursor.getFloat(indexes.sensorPowerIndex);
}
myTracksLocation.setSensorDataSet(new SensorDataSet(heartRate, cadence, power, SensorDataSet.DATA_UNAVAILABLE, location.getTime()));
} }
} }
@@ -1084,7 +1092,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
final int accuracyIndex; final int accuracyIndex;
final int speedIndex; final int speedIndex;
final int bearingIndex; final int bearingIndex;
final int sensorIndex; final int sensorHeartRateIndex;
final int sensorCadenceIndex;
final int sensorPowerIndex;
CachedTrackPointsIndexes(Cursor cursor) { CachedTrackPointsIndexes(Cursor cursor) {
idIndex = cursor.getColumnIndex(TrackPointsColumns._ID); idIndex = cursor.getColumnIndex(TrackPointsColumns._ID);
@@ -1095,7 +1105,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
accuracyIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ACCURACY); accuracyIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ACCURACY);
speedIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED); speedIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED);
bearingIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING); bearingIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING);
sensorIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR); sensorHeartRateIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_HEARTRATE);
sensorCadenceIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_CADENCE);
sensorPowerIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_POWER);
} }
} }
@@ -1,882 +0,0 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: proto/sensor.proto
package com.google.android.apps.mytracks.content;
public final class Sensor {
private Sensor() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public enum SensorState
implements com.google.protobuf.Internal.EnumLite {
NONE(0, 1),
CONNECTING(1, 2),
CONNECTED(2, 3),
DISCONNECTED(3, 4),
SENDING(4, 5),
;
public final int getNumber() { return value; }
public static SensorState valueOf(int value) {
switch (value) {
case 1: return NONE;
case 2: return CONNECTING;
case 3: return CONNECTED;
case 4: return DISCONNECTED;
case 5: return SENDING;
default: return null;
}
}
public static com.google.protobuf.Internal.EnumLiteMap<SensorState>
internalGetValueMap() {
return internalValueMap;
}
private static com.google.protobuf.Internal.EnumLiteMap<SensorState>
internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<SensorState>() {
public SensorState findValueByNumber(int number) {
return SensorState.valueOf(number)
; }
};
private final int index;
private final int value;
SensorState(int index, int value) {
this.index = index;
this.value = value;
}
// @@protoc_insertion_point(enum_scope:com.google.android.apps.mytracks.content.SensorState)
}
public static final class SensorData extends
com.google.protobuf.GeneratedMessageLite {
// Use SensorData.newBuilder() to construct.
private SensorData() {
initFields();
}
private SensorData(boolean noInit) {}
private static final SensorData defaultInstance;
public static SensorData getDefaultInstance() {
return defaultInstance;
}
public SensorData getDefaultInstanceForType() {
return defaultInstance;
}
// required .com.google.android.apps.mytracks.content.SensorState state = 1 [default = NONE];
public static final int STATE_FIELD_NUMBER = 1;
private boolean hasState;
private com.google.android.apps.mytracks.content.Sensor.SensorState state_;
public boolean hasState() { return hasState; }
public com.google.android.apps.mytracks.content.Sensor.SensorState getState() { return state_; }
// optional int32 value = 2;
public static final int VALUE_FIELD_NUMBER = 2;
private boolean hasValue;
private int value_ = 0;
public boolean hasValue() { return hasValue; }
public int getValue() { return value_; }
private void initFields() {
state_ = com.google.android.apps.mytracks.content.Sensor.SensorState.NONE;
}
public final boolean isInitialized() {
return hasState;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasState()) {
output.writeEnum(1, getState().getNumber());
}
if (hasValue()) {
output.writeInt32(2, getValue());
}
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasState()) {
size += com.google.protobuf.CodedOutputStream
.computeEnumSize(1, getState().getNumber());
}
if (hasValue()) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(2, getValue());
}
memoizedSerializedSize = size;
return size;
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(com.google.android.apps.mytracks.content.Sensor.SensorData prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessageLite.Builder<
com.google.android.apps.mytracks.content.Sensor.SensorData, Builder> {
private com.google.android.apps.mytracks.content.Sensor.SensorData result;
// Construct using com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new com.google.android.apps.mytracks.content.Sensor.SensorData();
return builder;
}
protected com.google.android.apps.mytracks.content.Sensor.SensorData internalGetResult() {
return result;
}
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new com.google.android.apps.mytracks.content.Sensor.SensorData();
return this;
}
public Builder clone() {
return create().mergeFrom(result);
}
public com.google.android.apps.mytracks.content.Sensor.SensorData getDefaultInstanceForType() {
return com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
}
public boolean isInitialized() {
return result.isInitialized();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private com.google.android.apps.mytracks.content.Sensor.SensorData buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
com.google.android.apps.mytracks.content.Sensor.SensorData returnMe = result;
result = null;
return returnMe;
}
public Builder mergeFrom(com.google.android.apps.mytracks.content.Sensor.SensorData other) {
if (other == com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) return this;
if (other.hasState()) {
setState(other.getState());
}
if (other.hasValue()) {
setValue(other.getValue());
}
return this;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
return this;
default: {
if (!parseUnknownField(input, extensionRegistry, tag)) {
return this;
}
break;
}
case 8: {
int rawValue = input.readEnum();
com.google.android.apps.mytracks.content.Sensor.SensorState value = com.google.android.apps.mytracks.content.Sensor.SensorState.valueOf(rawValue);
if (value != null) {
setState(value);
}
break;
}
case 16: {
setValue(input.readInt32());
break;
}
}
}
}
// required .com.google.android.apps.mytracks.content.SensorState state = 1 [default = NONE];
public boolean hasState() {
return result.hasState();
}
public com.google.android.apps.mytracks.content.Sensor.SensorState getState() {
return result.getState();
}
public Builder setState(com.google.android.apps.mytracks.content.Sensor.SensorState value) {
if (value == null) {
throw new NullPointerException();
}
result.hasState = true;
result.state_ = value;
return this;
}
public Builder clearState() {
result.hasState = false;
result.state_ = com.google.android.apps.mytracks.content.Sensor.SensorState.NONE;
return this;
}
// optional int32 value = 2;
public boolean hasValue() {
return result.hasValue();
}
public int getValue() {
return result.getValue();
}
public Builder setValue(int value) {
result.hasValue = true;
result.value_ = value;
return this;
}
public Builder clearValue() {
result.hasValue = false;
result.value_ = 0;
return this;
}
// @@protoc_insertion_point(builder_scope:com.google.android.apps.mytracks.content.SensorData)
}
static {
defaultInstance = new SensorData(true);
com.google.android.apps.mytracks.content.Sensor.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:com.google.android.apps.mytracks.content.SensorData)
}
public static final class SensorDataSet extends
com.google.protobuf.GeneratedMessageLite {
// Use SensorDataSet.newBuilder() to construct.
private SensorDataSet() {
initFields();
}
private SensorDataSet(boolean noInit) {}
private static final SensorDataSet defaultInstance;
public static SensorDataSet getDefaultInstance() {
return defaultInstance;
}
public SensorDataSet getDefaultInstanceForType() {
return defaultInstance;
}
// optional uint64 creation_time = 1 [default = 0];
public static final int CREATION_TIME_FIELD_NUMBER = 1;
private boolean hasCreationTime;
private long creationTime_ = 0L;
public boolean hasCreationTime() { return hasCreationTime; }
public long getCreationTime() { return creationTime_; }
// optional .com.google.android.apps.mytracks.content.SensorData heart_rate = 2;
public static final int HEART_RATE_FIELD_NUMBER = 2;
private boolean hasHeartRate;
private com.google.android.apps.mytracks.content.Sensor.SensorData heartRate_;
public boolean hasHeartRate() { return hasHeartRate; }
public com.google.android.apps.mytracks.content.Sensor.SensorData getHeartRate() { return heartRate_; }
// optional .com.google.android.apps.mytracks.content.SensorData cadence = 3;
public static final int CADENCE_FIELD_NUMBER = 3;
private boolean hasCadence;
private com.google.android.apps.mytracks.content.Sensor.SensorData cadence_;
public boolean hasCadence() { return hasCadence; }
public com.google.android.apps.mytracks.content.Sensor.SensorData getCadence() { return cadence_; }
// optional .com.google.android.apps.mytracks.content.SensorData power = 4;
public static final int POWER_FIELD_NUMBER = 4;
private boolean hasPower;
private com.google.android.apps.mytracks.content.Sensor.SensorData power_;
public boolean hasPower() { return hasPower; }
public com.google.android.apps.mytracks.content.Sensor.SensorData getPower() { return power_; }
// optional .com.google.android.apps.mytracks.content.SensorData battery_level = 5;
public static final int BATTERY_LEVEL_FIELD_NUMBER = 5;
private boolean hasBatteryLevel;
private com.google.android.apps.mytracks.content.Sensor.SensorData batteryLevel_;
public boolean hasBatteryLevel() { return hasBatteryLevel; }
public com.google.android.apps.mytracks.content.Sensor.SensorData getBatteryLevel() { return batteryLevel_; }
private void initFields() {
heartRate_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
cadence_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
power_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
batteryLevel_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
}
public final boolean isInitialized() {
if (hasHeartRate()) {
if (!getHeartRate().isInitialized()) return false;
}
if (hasCadence()) {
if (!getCadence().isInitialized()) return false;
}
if (hasPower()) {
if (!getPower().isInitialized()) return false;
}
if (hasBatteryLevel()) {
return getBatteryLevel().isInitialized();
}
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasCreationTime()) {
output.writeUInt64(1, getCreationTime());
}
if (hasHeartRate()) {
output.writeMessage(2, getHeartRate());
}
if (hasCadence()) {
output.writeMessage(3, getCadence());
}
if (hasPower()) {
output.writeMessage(4, getPower());
}
if (hasBatteryLevel()) {
output.writeMessage(5, getBatteryLevel());
}
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasCreationTime()) {
size += com.google.protobuf.CodedOutputStream
.computeUInt64Size(1, getCreationTime());
}
if (hasHeartRate()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(2, getHeartRate());
}
if (hasCadence()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(3, getCadence());
}
if (hasPower()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(4, getPower());
}
if (hasBatteryLevel()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(5, getBatteryLevel());
}
memoizedSerializedSize = size;
return size;
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(com.google.android.apps.mytracks.content.Sensor.SensorDataSet prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessageLite.Builder<
com.google.android.apps.mytracks.content.Sensor.SensorDataSet, Builder> {
private com.google.android.apps.mytracks.content.Sensor.SensorDataSet result;
// Construct using com.google.android.apps.mytracks.content.Sensor.SensorDataSet.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new com.google.android.apps.mytracks.content.Sensor.SensorDataSet();
return builder;
}
protected com.google.android.apps.mytracks.content.Sensor.SensorDataSet internalGetResult() {
return result;
}
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new com.google.android.apps.mytracks.content.Sensor.SensorDataSet();
return this;
}
public Builder clone() {
return create().mergeFrom(result);
}
public com.google.android.apps.mytracks.content.Sensor.SensorDataSet getDefaultInstanceForType() {
return com.google.android.apps.mytracks.content.Sensor.SensorDataSet.getDefaultInstance();
}
public boolean isInitialized() {
return result.isInitialized();
}
public com.google.android.apps.mytracks.content.Sensor.SensorDataSet build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private com.google.android.apps.mytracks.content.Sensor.SensorDataSet buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
public com.google.android.apps.mytracks.content.Sensor.SensorDataSet buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
com.google.android.apps.mytracks.content.Sensor.SensorDataSet returnMe = result;
result = null;
return returnMe;
}
public Builder mergeFrom(com.google.android.apps.mytracks.content.Sensor.SensorDataSet other) {
if (other == com.google.android.apps.mytracks.content.Sensor.SensorDataSet.getDefaultInstance()) return this;
if (other.hasCreationTime()) {
setCreationTime(other.getCreationTime());
}
if (other.hasHeartRate()) {
mergeHeartRate(other.getHeartRate());
}
if (other.hasCadence()) {
mergeCadence(other.getCadence());
}
if (other.hasPower()) {
mergePower(other.getPower());
}
if (other.hasBatteryLevel()) {
mergeBatteryLevel(other.getBatteryLevel());
}
return this;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
return this;
default: {
if (!parseUnknownField(input, extensionRegistry, tag)) {
return this;
}
break;
}
case 8: {
setCreationTime(input.readUInt64());
break;
}
case 18: {
com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder();
if (hasHeartRate()) {
subBuilder.mergeFrom(getHeartRate());
}
input.readMessage(subBuilder, extensionRegistry);
setHeartRate(subBuilder.buildPartial());
break;
}
case 26: {
com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder();
if (hasCadence()) {
subBuilder.mergeFrom(getCadence());
}
input.readMessage(subBuilder, extensionRegistry);
setCadence(subBuilder.buildPartial());
break;
}
case 34: {
com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder();
if (hasPower()) {
subBuilder.mergeFrom(getPower());
}
input.readMessage(subBuilder, extensionRegistry);
setPower(subBuilder.buildPartial());
break;
}
case 42: {
com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder();
if (hasBatteryLevel()) {
subBuilder.mergeFrom(getBatteryLevel());
}
input.readMessage(subBuilder, extensionRegistry);
setBatteryLevel(subBuilder.buildPartial());
break;
}
}
}
}
// optional uint64 creation_time = 1 [default = 0];
public boolean hasCreationTime() {
return result.hasCreationTime();
}
public long getCreationTime() {
return result.getCreationTime();
}
public Builder setCreationTime(long value) {
result.hasCreationTime = true;
result.creationTime_ = value;
return this;
}
public Builder clearCreationTime() {
result.hasCreationTime = false;
result.creationTime_ = 0L;
return this;
}
// optional .com.google.android.apps.mytracks.content.SensorData heart_rate = 2;
public boolean hasHeartRate() {
return result.hasHeartRate();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData getHeartRate() {
return result.getHeartRate();
}
public Builder setHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (value == null) {
throw new NullPointerException();
}
result.hasHeartRate = true;
result.heartRate_ = value;
return this;
}
public Builder setHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) {
result.hasHeartRate = true;
result.heartRate_ = builderForValue.build();
return this;
}
public Builder mergeHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (result.hasHeartRate() &&
result.heartRate_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) {
result.heartRate_ =
com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.heartRate_).mergeFrom(value).buildPartial();
} else {
result.heartRate_ = value;
}
result.hasHeartRate = true;
return this;
}
public Builder clearHeartRate() {
result.hasHeartRate = false;
result.heartRate_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
return this;
}
// optional .com.google.android.apps.mytracks.content.SensorData cadence = 3;
public boolean hasCadence() {
return result.hasCadence();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData getCadence() {
return result.getCadence();
}
public Builder setCadence(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (value == null) {
throw new NullPointerException();
}
result.hasCadence = true;
result.cadence_ = value;
return this;
}
public Builder setCadence(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) {
result.hasCadence = true;
result.cadence_ = builderForValue.build();
return this;
}
public Builder mergeCadence(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (result.hasCadence() &&
result.cadence_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) {
result.cadence_ =
com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.cadence_).mergeFrom(value).buildPartial();
} else {
result.cadence_ = value;
}
result.hasCadence = true;
return this;
}
public Builder clearCadence() {
result.hasCadence = false;
result.cadence_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
return this;
}
// optional .com.google.android.apps.mytracks.content.SensorData power = 4;
public boolean hasPower() {
return result.hasPower();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData getPower() {
return result.getPower();
}
public Builder setPower(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (value == null) {
throw new NullPointerException();
}
result.hasPower = true;
result.power_ = value;
return this;
}
public Builder setPower(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) {
result.hasPower = true;
result.power_ = builderForValue.build();
return this;
}
public Builder mergePower(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (result.hasPower() &&
result.power_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) {
result.power_ =
com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.power_).mergeFrom(value).buildPartial();
} else {
result.power_ = value;
}
result.hasPower = true;
return this;
}
public Builder clearPower() {
result.hasPower = false;
result.power_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
return this;
}
// optional .com.google.android.apps.mytracks.content.SensorData battery_level = 5;
public boolean hasBatteryLevel() {
return result.hasBatteryLevel();
}
public com.google.android.apps.mytracks.content.Sensor.SensorData getBatteryLevel() {
return result.getBatteryLevel();
}
public Builder setBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (value == null) {
throw new NullPointerException();
}
result.hasBatteryLevel = true;
result.batteryLevel_ = value;
return this;
}
public Builder setBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) {
result.hasBatteryLevel = true;
result.batteryLevel_ = builderForValue.build();
return this;
}
public Builder mergeBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData value) {
if (result.hasBatteryLevel() &&
result.batteryLevel_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) {
result.batteryLevel_ =
com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.batteryLevel_).mergeFrom(value).buildPartial();
} else {
result.batteryLevel_ = value;
}
result.hasBatteryLevel = true;
return this;
}
public Builder clearBatteryLevel() {
result.hasBatteryLevel = false;
result.batteryLevel_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance();
return this;
}
// @@protoc_insertion_point(builder_scope:com.google.android.apps.mytracks.content.SensorDataSet)
}
static {
defaultInstance = new SensorDataSet(true);
com.google.android.apps.mytracks.content.Sensor.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:com.google.android.apps.mytracks.content.SensorDataSet)
}
static {
}
public static void internalForceInit() {}
// @@protoc_insertion_point(outer_class_scope)
}
@@ -41,7 +41,9 @@ public interface TrackPointsColumns extends BaseColumns {
String ACCURACY = "accuracy"; String ACCURACY = "accuracy";
String SPEED = "speed"; String SPEED = "speed";
String BEARING = "bearing"; String BEARING = "bearing";
String SENSOR = "sensor"; String SENSOR_HEARTRATE = "sensor_heartrate";
String SENSOR_CADENCE = "sensor_cadence";
String SENSOR_POWER = "sensor_power";
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -53,6 +55,7 @@ public interface TrackPointsColumns extends BaseColumns {
+ ACCURACY + " FLOAT, " + ACCURACY + " FLOAT, "
+ SPEED + " FLOAT, " + SPEED + " FLOAT, "
+ BEARING + " FLOAT, " + BEARING + " FLOAT, "
+ SENSOR + " BLOB" + SENSOR_HEARTRATE + " FLOAT, "
+ ");"; + SENSOR_CADENCE + " FLOAT, "
+ SENSOR_POWER + " FLOAT);";
} }
@@ -0,0 +1,74 @@
package com.google.android.apps.mytracks.content.sensor;
public final class SensorDataSet {
public static final float DATA_UNAVAILABLE = Integer.MAX_VALUE;
//TODO It might be necessary to consider: sensor if sensor was connected as well.
private float heartRate;
private float cadence;
private float power;
private float batteryLevel;
private long creationTimestamp;
public SensorDataSet(float heartRate, float cadence, float power, float batteryLevel, long creationTimestamp) {
this.heartRate = heartRate;
this.cadence = cadence;
this.power = power;
this.batteryLevel = batteryLevel;
this.creationTimestamp = creationTimestamp;
}
public SensorDataSet(float heartRate, float cadence, float power, float batteryLevel) {
this(heartRate, cadence, power, batteryLevel, System.currentTimeMillis());
}
public SensorDataSet(float heartRate, float cadence, float power) {
this(heartRate, cadence, power, DATA_UNAVAILABLE, System.currentTimeMillis());
}
public SensorDataSet(float heartRate, float cadence) {
this(heartRate, cadence, DATA_UNAVAILABLE, DATA_UNAVAILABLE, System.currentTimeMillis());
}
public SensorDataSet(float heartRate) {
this(heartRate, DATA_UNAVAILABLE, DATA_UNAVAILABLE, DATA_UNAVAILABLE, System.currentTimeMillis());
}
public boolean hasHeartRate() {
return heartRate != DATA_UNAVAILABLE;
}
public float getHeartRate() {
return heartRate;
}
public boolean hasCadence() {
return cadence != DATA_UNAVAILABLE;
}
public float getCadence() {
return cadence;
}
public boolean hasPower() {
return power != DATA_UNAVAILABLE;
}
public float getPower() {
return power;
}
public long getCreationTime() {
return creationTimestamp;
}
public boolean hasBatteryLevel() {
return batteryLevel != DATA_UNAVAILABLE;
}
public float getBatteryLevel() {
return batteryLevel;
}
}
@@ -0,0 +1,27 @@
package com.google.android.apps.mytracks.content.sensor;
import android.content.Context;
import com.google.android.maps.mytracks.R;
public enum SensorState {
NONE,
CONNECTING,
CONNECTED,
DISCONNECTED;
public static String getStateAsString(SensorState state, Context c) {
switch (state) {
case NONE:
return c.getString(R.string.value_none);
case CONNECTING:
return c.getString(R.string.sensor_state_connecting);
case CONNECTED:
return c.getString(R.string.sensor_state_connected);
case DISCONNECTED:
return c.getString(R.string.sensor_state_disconnected);
default:
return "";
}
}
}
@@ -32,13 +32,12 @@ import androidx.fragment.app.FragmentActivity;
import com.google.android.apps.mytracks.ChartView; import com.google.android.apps.mytracks.ChartView;
import com.google.android.apps.mytracks.TrackDetailActivity; import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackDataHub; import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataListener; import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.TrackDataType; import com.google.android.apps.mytracks.content.TrackDataType;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.stats.TripStatisticsUpdater; import com.google.android.apps.mytracks.stats.TripStatisticsUpdater;
import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.LocationUtils;
@@ -478,23 +477,16 @@ public class ChartFragment extends Fragment implements TrackDataListener {
} }
pace = speed == 0 ? 0.0 : 60.0 / speed; pace = speed == 0 ? 0.0 : 60.0 / speed;
} }
if (location instanceof MyTracksLocation if (location instanceof MyTracksLocation && ((MyTracksLocation) location).getSensorDataSet() != null) {
&& ((MyTracksLocation) location).getSensorDataSet() != null) {
SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet(); SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet();
if (sensorDataSet.hasHeartRate() if (sensorDataSet.hasHeartRate()) {
&& sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING heartRate = sensorDataSet.getHeartRate();
&& sensorDataSet.getHeartRate().hasValue()) {
heartRate = sensorDataSet.getHeartRate().getValue();
} }
if (sensorDataSet.hasCadence() if (sensorDataSet.hasCadence()) {
&& sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING cadence = sensorDataSet.getCadence();
&& sensorDataSet.getCadence().hasValue()) {
cadence = sensorDataSet.getCadence().getValue();
} }
if (sensorDataSet.hasPower() if (sensorDataSet.hasPower()) {
&& sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING power = sensorDataSet.getPower();
&& sensorDataSet.getPower().hasValue()) {
power = sensorDataSet.getPower().getValue();
} }
} }
@@ -33,6 +33,7 @@ import java.util.Locale;
* *
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
//TODO Can we export Sensor.Data in GPX?
public class GpxTrackWriter implements TrackWriter { public class GpxTrackWriter implements TrackWriter {
private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US); private static final NumberFormat ELEVATION_FORMAT = NumberFormat.getInstance(Locale.US);
@@ -19,18 +19,17 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.location.Location; import android.location.Location;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.google.android.apps.mytracks.content.DescriptionGenerator; import com.google.android.apps.mytracks.content.DescriptionGenerator;
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl; import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorData;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.io.file.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackFileFormat;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -75,9 +74,9 @@ public class KmlTrackWriter implements TrackWriter {
private final MyTracksProviderUtils myTracksProviderUtils; private final MyTracksProviderUtils myTracksProviderUtils;
private PrintWriter printWriter; private PrintWriter printWriter;
private ArrayList<Integer> powerList = new ArrayList<>(); private ArrayList<Float> powerList = new ArrayList<>();
private ArrayList<Integer> cadenceList = new ArrayList<>(); private ArrayList<Float> cadenceList = new ArrayList<>();
private ArrayList<Integer> heartRateList = new ArrayList<>(); private ArrayList<Float> heartRateList = new ArrayList<>();
private boolean hasPower; private boolean hasPower;
private boolean hasCadence; private boolean hasCadence;
private boolean hasHeartRate; private boolean hasHeartRate;
@@ -264,36 +263,17 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<gx:coord>" + getCoordinates(location, " ") + "</gx:coord>"); printWriter.println("<gx:coord>" + getCoordinates(location, " ") + "</gx:coord>");
if (location instanceof MyTracksLocation) { if (location instanceof MyTracksLocation) {
SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet(); SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet();
int power = -1;
int cadence = -1;
int heartRate = -1;
if (sensorDataSet != null) { if (sensorDataSet != null) {
if (sensorDataSet.hasPower()) { if (sensorDataSet.hasHeartRate()) {
SensorData sensorData = sensorDataSet.getPower(); heartRateList.add(sensorDataSet.getHeartRate());
if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) {
hasPower = true;
power = sensorData.getValue();
}
} }
if (sensorDataSet.hasCadence()) { if (sensorDataSet.hasCadence()) {
SensorData sensorData = sensorDataSet.getCadence(); cadenceList.add(sensorDataSet.getCadence());
if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) {
hasCadence = true;
cadence = sensorData.getValue();
}
} }
if (sensorDataSet.hasHeartRate()) { if (sensorDataSet.hasPower()) {
SensorData sensorData = sensorDataSet.getHeartRate(); powerList.add(sensorDataSet.getPower());
if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) {
hasHeartRate = true;
heartRate = sensorData.getValue();
}
} }
} }
powerList.add(power);
cadenceList.add(cadence);
heartRateList.add(heartRate);
} }
} }
} }
@@ -304,7 +284,7 @@ public class KmlTrackWriter implements TrackWriter {
* @param list a list of sensor data * @param list a list of sensor data
* @param name the name of the sensor data * @param name the name of the sensor data
*/ */
private void writeSensorData(ArrayList<Integer> list, String name) { private void writeSensorData(ArrayList<Float> list, String name) {
printWriter.println("<gx:SimpleArrayData name=\"" + name + "\">"); printWriter.println("<gx:SimpleArrayData name=\"" + name + "\">");
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
printWriter.println("<gx:value>" + list.get(i) + "</gx:value>"); printWriter.println("<gx:value>" + list.get(i) + "</gx:value>");
@@ -24,9 +24,8 @@ import androidx.annotation.VisibleForTesting;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -223,9 +222,9 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
protected void onTrackSegmentStart() { protected void onTrackSegmentStart() {
super.onTrackSegmentStart(); super.onTrackSegmentStart();
locationList = new ArrayList<>(); locationList = new ArrayList<>();
powerList = new ArrayList<>();
cadenceList = new ArrayList<>();
heartRateList = new ArrayList<>(); heartRateList = new ArrayList<>();
cadenceList = new ArrayList<>();
powerList = new ArrayList<>();
} }
/** /**
@@ -233,9 +232,9 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
*/ */
private void onTrackSegmentEnd() { private void onTrackSegmentEnd() {
// Close a track segment by inserting the segment locations // Close a track segment by inserting the segment locations
boolean hasPower = powerList.size() == locationList.size();
boolean hasCadence = cadenceList.size() == locationList.size();
boolean hasHeartRate = heartRateList.size() == locationList.size(); boolean hasHeartRate = heartRateList.size() == locationList.size();
boolean hasCadence = cadenceList.size() == locationList.size();
boolean hasPower = powerList.size() == locationList.size();
for (int i = 0; i < locationList.size(); i++) { for (int i = 0; i < locationList.size(); i++) {
Location location = locationList.get(i); Location location = locationList.get(i);
@@ -243,21 +242,11 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
if (!hasPower && !hasCadence && !hasHeartRate) { if (!hasPower && !hasCadence && !hasHeartRate) {
insertTrackPoint(location); insertTrackPoint(location);
} else { } else {
SensorDataSet.Builder builder = Sensor.SensorDataSet.newBuilder(); float heartrate = hasHeartRate ? heartRateList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
if (hasPower) { float cadence = hasHeartRate ? cadenceList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
builder.setPower(Sensor.SensorData.newBuilder() float power = hasHeartRate ? powerList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
.setValue(powerList.get(i)).setState(Sensor.SensorState.SENDING));
} MyTracksLocation myTracksLocation = new MyTracksLocation(location, new SensorDataSet(heartrate, cadence, power, SensorDataSet.DATA_UNAVAILABLE, location.getTime()));
if (hasCadence) {
builder.setCadence(Sensor.SensorData.newBuilder()
.setValue(cadenceList.get(i)).setState(Sensor.SensorState.SENDING));
}
if (hasHeartRate) {
builder.setHeartRate(Sensor.SensorData.newBuilder()
.setValue(heartRateList.get(i)).setState(Sensor.SensorState.SENDING));
}
SensorDataSet sensorDataSet = builder.setCreationTime(location.getTime()).build();
MyTracksLocation myTracksLocation = new MyTracksLocation(location, sensorDataSet);
insertTrackPoint(myTracksLocation); insertTrackPoint(myTracksLocation);
} }
} }
@@ -18,6 +18,8 @@ package com.google.android.apps.mytracks.services;
import android.location.Location; import android.location.Location;
import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.sensor.SensorState;
/** /**
* MyTracks service. * MyTracks service.
@@ -98,14 +100,14 @@ public interface ITrackRecordingService {
/** /**
* Gets the current sensor data. Returns null if there is no data. * Gets the current sensor data. Returns null if there is no data.
* @return a byte array of the binary version of the Sensor.SensorDataSet object. * @return SensorDataSet object.
*/ */
byte[] getSensorData(); SensorDataSet getSensorData();
/** /**
* Gets the current sensor manager state. * Gets the current sensor manager state.
* *
* return a Sensor.SensorState enum value. * return a Sensor.SensorState enum value.
*/ */
int getSensorState(); SensorState getSensorState();
} }
@@ -49,12 +49,12 @@ import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProvider; import com.google.android.apps.mytracks.content.MyTracksProvider;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.sensor.SensorState;
import com.google.android.apps.mytracks.services.sensors.SensorManager; import com.google.android.apps.mytracks.services.sensors.SensorManager;
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory; import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;
import com.google.android.apps.mytracks.services.tasks.AnnouncementPeriodicTaskFactory; import com.google.android.apps.mytracks.services.tasks.AnnouncementPeriodicTaskFactory;
@@ -1129,7 +1129,7 @@ public class TrackRecordingService extends Service {
} }
@Override @Override
public byte[] getSensorData() { public SensorDataSet getSensorData() {
if (trackRecordingService.sensorManager == null) { if (trackRecordingService.sensorManager == null) {
Log.d(TAG, "sensorManager is null."); Log.d(TAG, "sensorManager is null.");
return null; return null;
@@ -1138,16 +1138,16 @@ public class TrackRecordingService extends Service {
Log.d(TAG, "Sensor data set is null."); Log.d(TAG, "Sensor data set is null.");
return null; return null;
} }
return trackRecordingService.sensorManager.getSensorDataSet().toByteArray(); return trackRecordingService.sensorManager.getSensorDataSet();
} }
@Override @Override
public int getSensorState() { public SensorState getSensorState() {
if (trackRecordingService.sensorManager == null) { if (trackRecordingService.sensorManager == null) {
Log.d(TAG, "sensorManager is null."); Log.d(TAG, "sensorManager is null.");
return Sensor.SensorState.NONE.getNumber(); return SensorState.NONE;
} }
return trackRecordingService.sensorManager.getSensorState().getNumber(); return trackRecordingService.sensorManager.getSensorState();
} }
/** /**
@@ -30,8 +30,7 @@ import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.sensor.SensorState;
import com.google.android.apps.mytracks.content.Sensor.SensorState;
import java.util.UUID; import java.util.UUID;
@@ -123,7 +122,7 @@ public class BluetoothConnectionManager {
* *
* @param sensorState the sensor state * @param sensorState the sensor state
*/ */
private synchronized void setState(Sensor.SensorState sensorState) { private synchronized void setState(SensorState sensorState) {
this.sensorState = sensorState; this.sensorState = sensorState;
} }
@@ -132,7 +131,7 @@ public class BluetoothConnectionManager {
*/ */
public synchronized void reset() { public synchronized void reset() {
//TODO Disconnect //TODO Disconnect
setState(Sensor.SensorState.NONE); setState(SensorState.NONE);
} }
/** /**
@@ -144,6 +143,6 @@ public class BluetoothConnectionManager {
Log.d(TAG, "connect to: " + bluetoothDevice); Log.d(TAG, "connect to: " + bluetoothDevice);
bluetoothDevice.connectGatt(this.context, false, this.connectCallback); bluetoothDevice.connectGatt(this.context, false, this.connectCallback);
setState(Sensor.SensorState.CONNECTING); setState(SensorState.CONNECTING);
} }
} }
@@ -25,9 +25,8 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.sensor.SensorState;
import com.google.android.apps.mytracks.content.Sensor.SensorState;
import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -98,10 +97,7 @@ public class BluetoothSensorManager extends SensorManager {
Toast.makeText(context, context.getString(R.string.settings_sensor_connected, deviceName), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getString(R.string.settings_sensor_connected, deviceName), Toast.LENGTH_LONG).show();
break; break;
case BluetoothConnectionManager.MESSAGE_READ: case BluetoothConnectionManager.MESSAGE_READ:
sensorDataSet = SensorDataSet.newBuilder() sensorDataSet = new SensorDataSet(message.arg1, SensorDataSet.DATA_UNAVAILABLE, SensorDataSet.DATA_UNAVAILABLE);
.setHeartRate(Sensor.SensorData.newBuilder().setValue(message.arg1)
.setState(SensorState.SENDING))
.build();
break; break;
default: default:
break; break;
@@ -16,11 +16,11 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Sensor.SensorState;
import android.util.Log; import android.util.Log;
import com.google.android.apps.mytracks.content.sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.sensor.SensorState;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@@ -1,115 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R;
import android.content.Context;
/**
* A collection of methods for message parsers.
*
* @author Sandor Dornbush
* @author Nico Laum
*/
public class SensorUtils {
private SensorUtils() {
}
/**
* Extract one unsigned short from a big endian byte array.
*
* @param buffer the buffer to extract the short from
* @param index the first byte to be interpreted as part of the short
* @return The unsigned short at the given index in the buffer
*/
public static int unsignedShortToInt(byte[] buffer, int index) {
int r = (buffer[index] & 0xFF) << 8;
r |= buffer[index + 1] & 0xFF;
return r;
}
/**
* Extract one unsigned short from a little endian byte array.
*
* @param buffer the buffer to extract the short from
* @param index the first byte to be interpreted as part of the short
* @return The unsigned short at the given index in the buffer
*/
public static int unsignedShortToIntLittleEndian(byte[] buffer, int index) {
int r = buffer[index] & 0xFF;
r |= (buffer[index + 1] & 0xFF) << 8;
return r;
}
/**
* Returns CRC8 (polynomial 0x8C) from byte array buffer[start] to
* (excluding) buffer[start + length]
*
* @param buffer the byte array of data (payload)
* @param start the position in the byte array where the payload begins
* @param length the length
* @return CRC8 value
*/
public static byte getCrc8(byte[] buffer, int start, int length) {
byte crc = 0x0;
for (int i = start; i < (start + length); i++) {
crc = crc8PushByte(crc, buffer[i]);
}
return crc;
}
/**
* Updates a CRC8 value by using the next byte passed to this method
*
* @param crc int of crc value
* @param add the next byte to add to the CRC8 calculation
*/
private static byte crc8PushByte(byte crc, byte add) {
crc = (byte) (crc ^ add);
for (int i = 0; i < 8; i++) {
if ((crc & 0x1) != 0x0) {
// Using a 0xFF bit assures that 0-bits are introduced during the shift operation.
// Otherwise, implicit casts to signed int could shift in 1-bits if the signed bit is 1.
crc = (byte) (((crc & 0xFF) >> 1) ^ 0x8C);
} else {
crc = (byte) ((crc & 0xFF) >> 1);
}
}
return crc;
}
public static String getStateAsString(Sensor.SensorState state, Context c) {
switch (state) {
case NONE:
return c.getString(R.string.value_none);
case CONNECTING:
return c.getString(R.string.sensor_state_connecting);
case CONNECTED:
return c.getString(R.string.sensor_state_connected);
case DISCONNECTED:
return c.getString(R.string.sensor_state_disconnected);
case SENDING:
return c.getString(R.string.sensor_state_sending);
default:
return "";
}
}
}
@@ -65,31 +65,33 @@ public class SensorSettingsActivity extends AbstractSettingsActivity {
* Configures the bluetooth sensor. * Configures the bluetooth sensor.
*/ */
private void configBluetoothSensor() { private void configBluetoothSensor() {
ListPreference preference = (ListPreference) findPreference( ListPreference preference = (ListPreference) findPreference(getString(R.string.bluetooth_sensor_key));
getString(R.string.bluetooth_sensor_key)); String value = PreferencesUtils.getString(this, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
String value = PreferencesUtils.getString( List<String> devicesNameList = new ArrayList<>();
this, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT); List<String> devicesAddressList = new ArrayList<>();
List<String> optionsList = new ArrayList<>();
List<String> valuesList = new ArrayList<>();
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter != null) { if (bluetoothAdapter != null) {
BluetoothDeviceUtils.populateDeviceLists(bluetoothAdapter, optionsList, valuesList); BluetoothDeviceUtils.populateDeviceLists(bluetoothAdapter, devicesNameList, devicesAddressList);
} }
if (valuesList.size() == 1) { //TODO Investigate why the settings are also written here?
if (!valuesList.get(0).equals(value)) { if (devicesAddressList.size() == 1) {
value = valuesList.get(0); if (!devicesAddressList.get(0).equals(value)) {
value = devicesAddressList.get(0);
PreferencesUtils.setString(this, R.string.bluetooth_sensor_key, value); PreferencesUtils.setString(this, R.string.bluetooth_sensor_key, value);
} }
} else { } else {
if (!valuesList.contains(value)) { if (!devicesAddressList.contains(value)) {
value = PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT; value = PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT;
PreferencesUtils.setString(this, R.string.bluetooth_sensor_key, value); PreferencesUtils.setString(this, R.string.bluetooth_sensor_key, value);
} }
} }
String[] options = optionsList.toArray(new String[0]); devicesNameList.add(0, getString(R.string.value_none));
String[] values = valuesList.toArray(new String[0]); devicesAddressList.add(0, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
String[] options = devicesNameList.toArray(new String[0]);
String[] values = devicesAddressList.toArray(new String[0]);
configureListPreference(preference, options, options, values, value, null); configureListPreference(preference, options, options, values, value, null);
} }
} }
@@ -39,8 +39,7 @@ public class BluetoothDeviceUtils {
* @param deviceNames list of device names * @param deviceNames list of device names
* @param deviceAddresses list of device addresses * @param deviceAddresses list of device addresses
*/ */
public static void populateDeviceLists( public static void populateDeviceLists(BluetoothAdapter bluetoothAdapter, List<String> deviceNames, List<String> deviceAddresses) {
BluetoothAdapter bluetoothAdapter, List<String> deviceNames, List<String> deviceAddresses) {
// Ensure the bluetooth adapter is not in discovery mode. // Ensure the bluetooth adapter is not in discovery mode.
bluetoothAdapter.cancelDiscovery(); bluetoothAdapter.cancelDiscovery();
@@ -48,7 +47,7 @@ public class BluetoothDeviceUtils {
for (BluetoothDevice device : pairedDevices) { for (BluetoothDevice device : pairedDevices) {
BluetoothClass bluetoothClass = device.getBluetoothClass(); BluetoothClass bluetoothClass = device.getBluetoothClass();
if (bluetoothClass != null) { if (bluetoothClass != null) {
// Not really sure what we want, but I know what we don't want. //TODO Not really sure what we want, but I know what we don't want.
switch (bluetoothClass.getMajorDeviceClass()) { switch (bluetoothClass.getMajorDeviceClass()) {
case BluetoothClass.Device.Major.COMPUTER: case BluetoothClass.Device.Major.COMPUTER:
case BluetoothClass.Device.Major.PHONE: case BluetoothClass.Device.Major.PHONE: