diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 70080701a..9de4385ec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -901,6 +901,11 @@ android:name=".activities.CameraActivity" android:launchMode="singleInstance" android:exported="false" /> + + \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/activity/CyclingLiveDataActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/activity/CyclingLiveDataActivity.java new file mode 100644 index 000000000..98a415325 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/activity/CyclingLiveDataActivity.java @@ -0,0 +1,170 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.cycling_sensor.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity; +import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity; +import nodomain.freeyourgadget.gadgetbridge.entities.CyclingSample; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; +import nodomain.freeyourgadget.gadgetbridge.util.GB; + +public class CyclingLiveDataActivity extends AbstractGBActivity { + private TextView speedView, tripDistanceView, totalDistanceView; + private GBDevice selectedDevice; + private float tripStartDistance = 0, tripCurrentDistance = 0; + private float toUnitFactor = 1; + private int + speedStringResource = R.string.km_h, + tripStringResource = R.string.label_distance_trip, + totalStringResource = R.string.label_distance_total; + + private static final String PREFS_KEY_TRIP_START = "CYCLING_TRIP_START"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if(getIntent() == null) { + selectedDevice = getStoredCyclingSensor(); + }else if(getIntent().getExtras() == null) { + selectedDevice = getStoredCyclingSensor(); + }else if((selectedDevice = + getIntent().getExtras().getParcelable("device")) == null) { + selectedDevice = getStoredCyclingSensor(); + } + + if (selectedDevice == null) { + GB.toast(getString(R.string.error_no_cycling_sensor_found), Toast.LENGTH_SHORT, GB.ERROR); + finish(); + return; + } + + setContentView(R.layout.activity_cycling_live_data); + + speedView = findViewById(R.id.cycling_data_speed); + tripDistanceView = findViewById(R.id.cycling_data_trip_distance); + totalDistanceView = findViewById(R.id.cycling_data_total_distance); + + tripStartDistance = GBApplication + .getDevicePrefs(selectedDevice) + .getFloat(PREFS_KEY_TRIP_START, 0); + + tripDistanceView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if(tripCurrentDistance == 0) { + return true; + } + + tripStartDistance = tripCurrentDistance; + + GBApplication + .getDeviceSpecificSharedPrefs(selectedDevice.getAddress()) + .edit() + .putFloat(PREFS_KEY_TRIP_START, tripStartDistance) + .apply(); + + tripDistanceView.setText(getString(tripStringResource, 0f)); + + return true; + } + }); + + String measurementSystem = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, "metric"); + + if(!measurementSystem.equals("metric")) { + toUnitFactor = 0.621371f; + + speedStringResource = R.string.mi_h; + tripStringResource = R.string.label_distance_trip_mph; + totalStringResource = R.string.label_distance_total_mph; + } + } + + private GBDevice getStoredCyclingSensor(){ + List devices = GBApplication + .app() + .getDeviceManager() + .getDevices(); + + for(GBDevice device: devices) { + if (device.getState() != GBDevice.State.INITIALIZED) continue; + if (device.getType() != DeviceType.CYCLING_SENSOR) continue; + + return device; + } + + return null; + } + + private BroadcastReceiver cyclingDataReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String deviceAddress = intent.getStringExtra("EXTRA_DEVICE_ADDRESS"); + + if(deviceAddress == null) { + return; + } + + if(!deviceAddress.equals(selectedDevice.getAddress())) { + return; + } + + CyclingSample sample = (CyclingSample) intent.getSerializableExtra(DeviceService.EXTRA_REALTIME_SAMPLE); + + if(sample == null) { + return; + } + + Float metersPerSecond = sample.getSpeed(); + if(metersPerSecond != null) { + float kmh = metersPerSecond * 3.6f * toUnitFactor; + speedView.setText(String.format("%.1f %s", kmh, getString(speedStringResource))); + }else{ + speedView.setText(String.format("%.1f %s", 0f, getString(speedStringResource))); + } + + tripCurrentDistance = sample.getDistance(); + + tripDistanceView.setText(getString(tripStringResource, ((tripCurrentDistance - tripStartDistance) * toUnitFactor) / 1000)); + totalDistanceView.setText(getString(totalStringResource, (tripCurrentDistance * toUnitFactor) / 1000)); + } + }; + + @Override + protected void onResume() { + super.onResume(); + + LocalBroadcastManager + .getInstance(this) + .registerReceiver( + cyclingDataReceiver, + new IntentFilter(DeviceService.ACTION_REALTIME_SAMPLES) + ); + } + + @Override + protected void onPause() { + super.onPause(); + + LocalBroadcastManager + .getInstance(this) + .unregisterReceiver(cyclingDataReceiver); + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/coordinator/CyclingSensorCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/coordinator/CyclingSensorCoordinator.java index 8dedd9fd5..ed74e0be0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/coordinator/CyclingSensorCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cycling_sensor/coordinator/CyclingSensorCoordinator.java @@ -11,6 +11,7 @@ import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.cycling_sensor.activity.CyclingLiveDataActivity; import nodomain.freeyourgadget.gadgetbridge.devices.cycling_sensor.db.CyclingSampleProvider; import nodomain.freeyourgadget.gadgetbridge.entities.CyclingSample; import nodomain.freeyourgadget.gadgetbridge.entities.CyclingSampleDao; @@ -80,7 +81,7 @@ public class CyclingSensorCoordinator extends AbstractBLEDeviceCoordinator { @Override public Class getAppsManagementActivity() { - return null; + return CyclingLiveDataActivity.class; } @Override @@ -110,4 +111,11 @@ public class CyclingSensorCoordinator extends AbstractBLEDeviceCoordinator { public int getDeviceNameResource() { return R.string.devicetype_cycling_sensor; } + + @Override + public boolean supportsAppsManagement(GBDevice device) { + return true; + } + + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cycling_sensor/support/CyclingSensorSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cycling_sensor/support/CyclingSensorSupport.java index aceb4d361..69367dfb0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cycling_sensor/support/CyclingSensorSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cycling_sensor/support/CyclingSensorSupport.java @@ -1,7 +1,5 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.cycling_sensor.support; -import static nodomain.freeyourgadget.gadgetbridge.model.ActivityKind.CYCLING; - import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.content.Intent; @@ -93,7 +91,7 @@ public class CyclingSensorSupport extends CyclingSensorBaseSupport { private long persistenceInterval; private long nextPersistenceTimestamp = 0; - private float wheelCircumference; + private float wheelCircumferenceMeters; private CyclingSpeedCadenceMeasurement lastReportedMeasurement = null; private long lastMeasurementTime = 0; @@ -125,7 +123,7 @@ public class CyclingSensorSupport extends CyclingSensorBaseSupport { nextPersistenceTimestamp = 0; float wheelDiameter = deviceSpecificPrefs.getFloat(DeviceSettingsPreferenceConst.PREF_CYCLING_SENSOR_WHEEL_DIAMETER, 29); - wheelCircumference = (float)(wheelDiameter * 2.54 * Math.PI) / 100; + wheelCircumferenceMeters = (float)(wheelDiameter * 2.54 * Math.PI) / 100; } @Override @@ -196,13 +194,30 @@ public class CyclingSensorSupport extends CyclingSensorBaseSupport { float revolutionsPerSecond = revolutionsDelta * (1000f / millisDelta); - speed = revolutionsPerSecond * wheelCircumference; + speed = revolutionsPerSecond * wheelCircumferenceMeters; } } lastReportedMeasurement = currentMeasurement; lastMeasurementTime = now; + CyclingSample sample = new CyclingSample(); + + if (currentMeasurement.revolutionDataPresent) { + sample.setRevolutionCount(currentMeasurement.revolutionCount); + sample.setSpeed(speed); + sample.setDistance(currentMeasurement.revolutionCount * wheelCircumferenceMeters); + } + + sample.setTimestamp(now); + + Intent liveIntent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES); + liveIntent.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample); + liveIntent.putExtra("EXTRA_DEVICE_ADDRESS", getDevice().getAddress()); + LocalBroadcastManager.getInstance(getContext()) + .sendBroadcast(liveIntent); + + if(now < nextPersistenceTimestamp){ // too early return; @@ -210,21 +225,6 @@ public class CyclingSensorSupport extends CyclingSensorBaseSupport { nextPersistenceTimestamp = now + persistenceInterval; - CyclingSample sample = new CyclingSample(); - - if (currentMeasurement.revolutionDataPresent) { - sample.setRevolutionCount(currentMeasurement.revolutionCount); - sample.setSpeed(speed); - sample.setDistance(currentMeasurement.revolutionCount * wheelCircumference); - } - - sample.setTimestamp(now); - - Intent liveIntent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES); - liveIntent.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample); - LocalBroadcastManager.getInstance(getContext()) - .sendBroadcast(liveIntent); - try(DBHandler handler = GBApplication.acquireDB()) { DaoSession session = handler.getDaoSession(); diff --git a/app/src/main/res/layout/activity_cycling_live_data.xml b/app/src/main/res/layout/activity_cycling_live_data.xml new file mode 100644 index 000000000..b06560ba1 --- /dev/null +++ b/app/src/main/res/layout/activity_cycling_live_data.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7204f749c..cb2297548 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3296,4 +3296,9 @@ Abort the import? This may lead to a corrupted or inconsistent database. Restart %1s will now restart. + Trip: %.1f km + Total: %.1f km + Trip: %.1f mi + Total: %.1f mi + no cycling sensor found