Skip to content

Commit

Permalink
[LEIP-120] Add digural UI, camera support, AppPreferences (#61)
Browse files Browse the repository at this point in the history
* Re-enable camera mode

* [LEIP-128] Add trigger hook

* [LEIP-127] Copy cyface UI to digural folder

* Disable camera on cyface ui again

* [LEIP-129] Refactor SettingsFragment: upload and centerMap

* [LEIP-120] Refactor SettingsFragment and AppPreferences

* Fix build

* Upgrade camera-service to 4.1.12 and remove CccTriggerHandler
  • Loading branch information
hb0 authored Jul 25, 2023
1 parent 104a200 commit 2e983a5
Show file tree
Hide file tree
Showing 149 changed files with 9,042 additions and 2,499 deletions.
1 change: 1 addition & 0 deletions .github/workflows/gradle_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
echo "cyface.staging_password=guestPassword" >> gradle.properties
echo "cyface.oauth_redirect=de.cyface.app:/oauth2redirect" >> gradle.properties
echo "cyface.oauth_redirect.r4r=de.cyface.app.r4r:/oauth2redirect" >> gradle.properties
echo "cyface.oauth_redirect.digural=de.cyface.app.digural:/oauth2redirect" >> gradle.properties
# Executing build here on Ubuntu stack (1/10th costs of MacOS stack)
# Not using "gradle build" as we don't want to run the tests of all dependencies (e.g. backend)
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/gradle_connected-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
echo "cyface.staging_password=guestPassword" >> gradle.properties
echo "cyface.oauth_redirect=de.cyface.app:/oauth2redirect" >> gradle.properties
echo "cyface.oauth_redirect.r4r=de.cyface.app.r4r:/oauth2redirect" >> gradle.properties
echo "cyface.oauth_redirect.digural=de.cyface.app.digural:/oauth2redirect" >> gradle.properties
# Not executing build here on MacOS stack (10x costs, if private repository)
# Not using "gradle build" as we don't want to run the tests of all dependencies (e.g. backend)
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/gradle_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ jobs:
# Inject OAuth redirect URIs
echo "cyface.oauth_redirect=de.cyface.app:/oauth2redirect" >> gradle.properties
echo "cyface.oauth_redirect.r4r=de.cyface.app.r4r:/oauth2redirect" >>gradle.properties
echo "cyface.oauth_redirect.digural=de.cyface.app.digural:/oauth2redirect" >> gradle.properties
# Inject Google Maps API key
echo "google.maps_api_key=${{ secrets.GOOGLE_MAPS_KEY }}" >> gradle.properties
echo "google.maps_api_key.r4r=${{ secrets.GOOGLE_MAPS_KEY_R4R }}" >> gradle.properties
Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ ext {
*/

// Cyface dependencies
cyfaceAndroidBackendVersion = "7.8.0" // Also update submodule commit ref
cyfaceUtilsVersion = "3.3.7"
cyfaceEnergySettingsVersion = "3.3.3" // Also update submodule commit ref
cyfaceCameraServiceVersion = "4.1.11" // Also update submodule commit ref
cyfaceAndroidBackendVersion = "7.8.1" // Also update submodule commit ref
cyfaceUtilsVersion = "3.5.0"
cyfaceEnergySettingsVersion = "3.3.4" // Also update submodule commit ref
cyfaceCameraServiceVersion = "4.1.12" // Also update submodule commit ref
// Maybe keep this in sync with the serialization library version used in `uploader` lib
cyfaceSerializationVersion = "2.3.7" // Keep im sync with version in submodule `backend`
cyfaceUploaderVersion = "1.0.0"
Expand Down
2 changes: 1 addition & 1 deletion camera_service
1 change: 1 addition & 0 deletions gradle.properties.template
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ hCaptcha.key.r4r=

cyface.oauth_redirect=
cyface.oauth_redirect.r4r=
cyface.oauth_redirect.digural=

cyface.api=
cyface.incentives_api=
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ include ':energy_settings'
include ':camera_service'
include ':bluetooth-le'
include ':ui:cyface'
include ':ui:digural'
include ':ui:r4r'
project(':persistence').projectDir = new File('backend/persistence')
project(':synchronization').projectDir = new File('backend/synchronization')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@
package de.cyface.app.ui.button;

import static de.cyface.app.utils.Constants.TAG;
import static de.cyface.app.utils.SharedConstants.ACCEPTED_REPORTING_KEY;
import static de.cyface.app.utils.SharedConstants.PREFERENCES_MODALITY_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_CAPTURING_ENABLED_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_DISTANCE_BASED_TRIGGERING_ENABLED_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_RAW_MODE_ENABLED_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_ENABLED_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_EXPOSURE_VALUE_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_STATIC_FOCUS_DISTANCE_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_STATIC_FOCUS_ENABLED_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_TRIGGERING_DISTANCE_KEY;
import static de.cyface.camera_service.Constants.PREFERENCES_CAMERA_VIDEO_MODE_ENABLED_KEY;
import static de.cyface.datacapturing.DataCapturingService.IS_RUNNING_CALLBACK_TIMEOUT;
import static de.cyface.energy_settings.TrackingSettings.isBackgroundProcessingRestricted;
import static de.cyface.energy_settings.TrackingSettings.isEnergySaferActive;
Expand All @@ -56,7 +44,6 @@
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.LocationManager;
import android.os.Build;
import android.os.Handler;
Expand All @@ -69,7 +56,6 @@
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;

import de.cyface.app.CapturingFragment;
import de.cyface.app.R;
Expand All @@ -78,6 +64,7 @@
import de.cyface.app.utils.CalibrationDialogListener;
import de.cyface.app.utils.Map;
import de.cyface.camera_service.CameraListener;
import de.cyface.camera_service.CameraPreferences;
import de.cyface.camera_service.CameraService;
import de.cyface.camera_service.Constants;
import de.cyface.camera_service.UIListener;
Expand All @@ -101,6 +88,7 @@
import de.cyface.persistence.model.ParcelableGeoLocation;
import de.cyface.persistence.model.Track;
import de.cyface.persistence.strategy.DefaultLocationCleaning;
import de.cyface.utils.AppPreferences;
import de.cyface.utils.DiskConsumption;
import de.cyface.utils.Validate;
import io.sentry.Sentry;
Expand Down Expand Up @@ -132,7 +120,14 @@ public class DataCapturingButton
* The {@link CameraService} required to control and check the visual capturing process.
*/
private CameraService cameraService = null;
private SharedPreferences preferences;
/**
* The `SharedPreferences` used to store the app preferences.
*/
private AppPreferences preferences;
/**
* The `SharedPreferences` used to store the camera preferences.
*/
private CameraPreferences cameraPreferences;
private final static long CALIBRATION_DIALOG_TIMEOUT = 1500L;
private Collection<CalibrationDialogListener> calibrationDialogListener;
/**
Expand Down Expand Up @@ -191,8 +186,9 @@ public void onCreateView(final ImageButton button, final DonutProgress ISNULL) {
this.cameraInfoTextView = button.getRootView().findViewById(R.id.camera_capturing_info);

// To get the vehicle
preferences = PreferenceManager.getDefaultSharedPreferences(context);
isReportingEnabled = preferences.getBoolean(ACCEPTED_REPORTING_KEY, false);
preferences = new AppPreferences(context);
cameraPreferences = new CameraPreferences(context);
isReportingEnabled = preferences.getReportingAccepted();

// To load the measurement distance
this.persistenceLayer = new DefaultPersistenceLayer<>(context, new DefaultPersistenceBehaviour());
Expand Down Expand Up @@ -564,7 +560,7 @@ private void startCapturing() {

// TODO [CY-3855]: we have to provide a listener for the button (<- ???)
try {
final Modality modality = Modality.valueOf(preferences.getString(PREFERENCES_MODALITY_KEY, null));
final var modality = Modality.valueOf(preferences.getModality());
Validate.notNull(modality);

currentMeasurementsTracks = new ArrayList<>();
Expand Down Expand Up @@ -691,26 +687,17 @@ private void showToastOnMainThread(final String toastMessage, final boolean long
private void startCameraService(final long measurementId)
throws DataCapturingException, MissingPermissionException {

final boolean rawModeSelected = preferences.getBoolean(PREFERENCES_CAMERA_RAW_MODE_ENABLED_KEY, false);
final boolean videoModeSelected = preferences.getBoolean(PREFERENCES_CAMERA_VIDEO_MODE_ENABLED_KEY, false);
final var rawModeSelected = cameraPreferences.getRawMode();
final var videoModeSelected = cameraPreferences.getVideoMode();
// We need to load and pass the preferences for the camera focus here as the preferences
// do not work reliably on multi-process access. https://stackoverflow.com/a/27987956/5815054
final boolean staticFocusSelected = preferences.getBoolean(PREFERENCES_CAMERA_STATIC_FOCUS_ENABLED_KEY,
false);
final float staticFocusDistance = preferences.getFloat(PREFERENCES_CAMERA_STATIC_FOCUS_DISTANCE_KEY,
Constants.DEFAULT_STATIC_FOCUS_DISTANCE);
final boolean distanceBasedTriggeringSelected = preferences.getBoolean(
PREFERENCES_CAMERA_DISTANCE_BASED_TRIGGERING_ENABLED_KEY,
true);
final float triggeringDistance = preferences.getFloat(PREFERENCES_CAMERA_TRIGGERING_DISTANCE_KEY,
Constants.DEFAULT_TRIGGERING_DISTANCE);
final boolean staticExposureTimeSelected = preferences.getBoolean(
PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_ENABLED_KEY,
false);
final long staticExposureTime = preferences.getLong(PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_KEY,
Constants.DEFAULT_STATIC_EXPOSURE_TIME);
final int exposureValueIso100 = preferences.getInt(PREFERENCES_CAMERA_STATIC_EXPOSURE_TIME_EXPOSURE_VALUE_KEY,
Constants.DEFAULT_STATIC_EXPOSURE_VALUE_ISO_100);
final var staticFocusSelected = cameraPreferences.getStaticFocus();
final var staticFocusDistance = cameraPreferences.getStaticFocusDistance();
final var distanceBasedTriggeringSelected = cameraPreferences.getDistanceBasedTriggering();
final var triggeringDistance = cameraPreferences.getTriggeringDistance();
final var staticExposureTimeSelected = cameraPreferences.getStaticExposure();
final var staticExposureTime = cameraPreferences.getStaticExposureTime();
final var exposureValueIso100 = cameraPreferences.getStaticExposureValue();

cameraService.start(measurementId, videoModeSelected, rawModeSelected, staticFocusSelected,
staticFocusDistance, staticExposureTimeSelected, staticExposureTime, exposureValueIso100,
Expand Down Expand Up @@ -869,7 +856,7 @@ public void addButtonListener(final ButtonListener buttonListener) {
}

private boolean isCameraServiceRequested() {
return preferences.getBoolean(PREFERENCES_CAMERA_CAPTURING_ENABLED_KEY, false);
return cameraPreferences.getCameraEnabled();
}

@Override
Expand Down
25 changes: 9 additions & 16 deletions ui/cyface/src/main/kotlin/de/cyface/app/CapturingFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
package de.cyface.app

import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.preference.PreferenceManager
import android.util.Log
import android.view.LayoutInflater
import android.view.View
Expand All @@ -41,8 +39,6 @@ import de.cyface.app.dialog.ModalityDialog
import de.cyface.app.ui.button.DataCapturingButton
import de.cyface.app.utils.Map
import de.cyface.app.utils.ServiceProvider
import de.cyface.app.utils.SharedConstants.ACCEPTED_REPORTING_KEY
import de.cyface.app.utils.SharedConstants.PREFERENCES_MODALITY_KEY
import de.cyface.camera_service.CameraService
import de.cyface.datacapturing.CyfaceDataCapturingService
import de.cyface.datacapturing.persistence.CapturingPersistenceBehaviour
Expand All @@ -51,6 +47,7 @@ import de.cyface.persistence.exception.NoSuchMeasurementException
import de.cyface.persistence.model.Event
import de.cyface.persistence.model.Modality
import de.cyface.synchronization.ConnectionStatusListener
import de.cyface.utils.AppPreferences
import de.cyface.utils.Validate
import io.sentry.Sentry

Expand Down Expand Up @@ -91,9 +88,9 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
private set

/**
* The `SharedPreferences` used to store the user's preferences.
* The `SharedPreferences` used to store the app preferences.
*/
private var preferences: SharedPreferences? = null
private lateinit var preferences: AppPreferences

/**
* The `DataCapturingService` which represents the API of the Cyface Android SDK.
Expand Down Expand Up @@ -150,8 +147,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
currentMeasurementsEvents = dataCapturingButton!!.loadCurrentMeasurementsEvents()
map!!.render(currentMeasurementsTracks, currentMeasurementsEvents, false, ArrayList())
} catch (e: NoSuchMeasurementException) {
val isReportingEnabled = preferences!!.getBoolean(ACCEPTED_REPORTING_KEY, false)
if (isReportingEnabled) {
if (preferences.getReportingAccepted()) {
Sentry.captureException(e)
}
Log.w(
Expand Down Expand Up @@ -184,7 +180,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
): View {
_binding = FragmentCapturingBinding.inflate(inflater, container, false)
dataCapturingButton = DataCapturingButton(this)
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
preferences = AppPreferences(requireContext())
// Register synchronization listener
capturing.addConnectionStatusListener(this)
syncButton = SynchronizationButton(capturing)
Expand Down Expand Up @@ -224,8 +220,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {

private fun showModalitySelectionDialogIfNeeded() {
registerModalityTabSelectionListener()
val selectedModality = preferences!!.getString(PREFERENCES_MODALITY_KEY, null)
if (selectedModality != null) {
if (preferences.getModality() != null) {
selectModalityTab()
return
}
Expand All @@ -242,7 +237,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
val newModality = arrayOfNulls<Modality>(1)
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
val oldModalityId = preferences!!.getString(PREFERENCES_MODALITY_KEY, null)
val oldModalityId = preferences.getModality()
val oldModality =
if (oldModalityId == null) null else Modality.valueOf(oldModalityId)
when (tab.position) {
Expand All @@ -253,9 +248,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
4 -> newModality[0] = Modality.TRAIN
else -> throw IllegalArgumentException("Unknown tab selected: " + tab.position)
}
preferences!!.edit()
.putString(PREFERENCES_MODALITY_KEY, newModality[0]!!.databaseIdentifier)
.apply()
preferences.saveModality(newModality[0]!!.databaseIdentifier)
if (oldModality != null && oldModality == newModality[0]) {
Log.d(
TAG,
Expand Down Expand Up @@ -305,7 +298,7 @@ class CapturingFragment : Fragment(), ConnectionStatusListener {
*/
private fun selectModalityTab() {
val tabLayout = binding.modalityTabs
val modality = preferences!!.getString(PREFERENCES_MODALITY_KEY, null)
val modality = preferences.getModality()
Validate.notNull(modality, "Modality should already be set but isn't.")

// Select the Modality tab
Expand Down
Loading

0 comments on commit 2e983a5

Please sign in to comment.