diff --git a/README.md b/README.md index 7ffcac4..d642992 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ two main steps in the process: 1. Check if permissions are required: - If the data collection is started using the paired smartphone, the check is automatic. You have to do nothing! - - If the data collection is started using the smartphone, you need to do the check using the [`PermissionsManager.launchPermissionsRequestIfNeeded()`](#permissionsmanager) method. + - If the data collection is started using the smartwatch, you need to do the check using the [`PermissionsManager.launchPermissionsRequestIfNeeded()`](#permissionsmanager) method. 2. Request the required permissions: the library handles mostly of the process by you, but you still have to do execute some steps: - Create an Activity: it will be used by the library to request the permissions. This will allow you to define a UI where some information can be given prior to the permissions request. - In your activity: @@ -182,9 +182,58 @@ public class MainActivity extends Activity { ``` #### Start/stop data collection from smartphone -The library fully handles this for you. You have to do nothing! +The library fully handles this for you. You can start and stop the data collection from the smartphone +and receive the collected data. You have to do nothing! #### Start/stop data collection from smartwatch +When starting the data collection from the smartwatch, you can chose where the collected data will be +delivered: to the smartwatch itself or to the paired smartphone. + +##### Obtain the data in the smartwatch +You can use the [`ServiceManager`](#servicemanager) provided by _Background Sensors_ to start and stop +the data collection and receive the data in the device: + +```java +public class MainActivity extends Activity { + // ... + private CommandClient commandClient; + + @Override + protected void onCreate(Bundle savedInstanceState) { + // ... + sensorManager = new SensorManager(context); + serviceManager = new ServiceManager(this, WearSensorRecordingService.class); + } + + public void setupUI() { + List availableSensors = sensorManager.availableSensors(WearSensor.values()); + } + + public void onStartSingleCommandTap(WearSensor sensor) { + CollectionConfiguration config = new CollectionConfiguration( + selectedSensor, + android.hardware.SensorManager.SENSOR_DELAY_GAME, + selectedSensor == WearSensor.HEART_RATE || selectedSensor == WearSensor.LOCATION ? 1 : 50 + ); + serviceManager.startCollection(config, records -> { + // ... + }); + } + + public void onStopSingleCommandTap(Sensor sensor) { + serviceManager.stopCollection(sensor, records -> { + // ... + }); + } + + // ... +} +``` + +> [!TIP] +> Please, refer to the [_Background Sensors_](https://github.com/GeoTecINIT/BackgroundSensors#servicemanager) documentation. + +##### Obtain the data in the smartphone To start or stop the data collection, the smartphone needs to be updated regarding the change in the data collection status. So, if we want to start/stop the data collection from the smartwatch, we have to notify that intention to the smartphone. Then, the smartphone will update its internal status and once everything is set up, it will confirm the smartwatch @@ -296,6 +345,9 @@ requested for the specified sensor. Use it along `PermissionsManager.launchPermi ### `SensorManager` Refer to the [_Background Sensors_](https://github.com/GeoTecINIT/BackgroundSensors#sensormanager) documentation. +### `ServiceManager` +Refer to the [_Background Sensors_](https://github.com/GeoTecINIT/BackgroundSensors#servicemanager) documentation. + ### [`PermissionsManager`](wearossensors/src/main/java/es/uji/geotec/wearossensors/permissions/PermissionsManager.java) | **Static Method** | **Return type** | **Description** | |--------------------------------------------------------------------------------------|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| diff --git a/app/build.gradle b/app/build.gradle index 89e97d1..5adaf05 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,8 +37,7 @@ dependencies { implementation 'com.google.android.support:wearable:2.8.1' implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.2.1' - implementation 'androidx.wear:wear:1.0.0' + implementation 'androidx.wear:wear:1.3.0' implementation project(path: ':wearossensors') compileOnly 'com.google.android.wearable:wearable:2.8.1' } \ No newline at end of file diff --git a/app/src/main/java/es/uji/geotec/wearossensorsdemo/MainActivity.java b/app/src/main/java/es/uji/geotec/wearossensorsdemo/MainActivity.java index c817777..e717637 100644 --- a/app/src/main/java/es/uji/geotec/wearossensorsdemo/MainActivity.java +++ b/app/src/main/java/es/uji/geotec/wearossensorsdemo/MainActivity.java @@ -9,24 +9,27 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; import android.widget.Spinner; -import es.uji.geotec.backgroundsensors.collection.CollectionConfiguration; import es.uji.geotec.backgroundsensors.sensor.Sensor; import es.uji.geotec.backgroundsensors.sensor.SensorManager; -import es.uji.geotec.wearossensors.command.CommandClient; import es.uji.geotec.wearossensors.plainmessage.PlainMessage; import es.uji.geotec.wearossensors.plainmessage.PlainMessageClient; import es.uji.geotec.wearossensors.permissions.PermissionsManager; import es.uji.geotec.wearossensors.sensor.WearSensor; +import es.uji.geotec.wearossensorsdemo.command.CollectionCommand; +import es.uji.geotec.wearossensorsdemo.command.LocalCollectionCommand; +import es.uji.geotec.wearossensorsdemo.command.RemoteCollectionCommand; public class MainActivity extends Activity { private LinearLayout linearLayout; + private RadioGroup destinationRadio; private Button startSingle, stopSingle; private Spinner sensorSpinner; - - private CommandClient commandClient; + private CollectionCommand command; private PlainMessageClient messageClient; @Override @@ -38,7 +41,7 @@ protected void onCreate(Bundle savedInstanceState) { setupButtons(); setupSpinner(); - commandClient = new CommandClient(this); + command = new LocalCollectionCommand(this); messageClient = new PlainMessageClient(this); messageClient.registerListener(message -> { Log.d("MainActivity", "received " + message); @@ -56,6 +59,20 @@ protected void onCreate(Bundle savedInstanceState) { } } + public void onDestinationButtonClicked(View view) { + boolean checked = ((RadioButton) view).isChecked(); + if (!checked) return; + + switch(view.getId()) { + case R.id.local_collection: + this.command = new LocalCollectionCommand(this); + break; + case R.id.remote_collection: + this.command = new RemoteCollectionCommand(this); + break; + } + } + public void onStartSingleCommandTap(View view) { WearSensor selectedSensor = (WearSensor) sensorSpinner.getSelectedItem(); boolean requested = PermissionsManager.launchPermissionsRequestIfNeeded(this, selectedSensor.getRequiredPermissions()); @@ -63,21 +80,18 @@ public void onStartSingleCommandTap(View view) { toggleVisibility(stopSingle, startSingle); sensorSpinner.setEnabled(false); + destinationRadio.setEnabled(false); - CollectionConfiguration config = new CollectionConfiguration( - selectedSensor, - android.hardware.SensorManager.SENSOR_DELAY_GAME, - selectedSensor == WearSensor.HEART_RATE || selectedSensor == WearSensor.LOCATION ? 1 : 50 - ); - commandClient.sendStartCommand(config); + command.executeStart(selectedSensor); } public void onStopSingleCommandTap(View view) { toggleVisibility(startSingle, stopSingle); - Sensor selectedSensor = (Sensor) sensorSpinner.getSelectedItem(); sensorSpinner.setEnabled(true); + destinationRadio.setEnabled(true); - commandClient.sendStopCommand(selectedSensor); + WearSensor selectedSensor = (WearSensor) sensorSpinner.getSelectedItem(); + command.executeStop(selectedSensor); } public void onSendFreeMessageTap(View view) { @@ -96,6 +110,7 @@ private void setupLayout() { private void setupButtons() { startSingle = findViewById(R.id.start_single_command); stopSingle = findViewById(R.id.stop_single_command); + destinationRadio = findViewById(R.id.destination_collection); } private void setupSpinner() { diff --git a/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/CollectionCommand.java b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/CollectionCommand.java new file mode 100644 index 0000000..5583f44 --- /dev/null +++ b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/CollectionCommand.java @@ -0,0 +1,8 @@ +package es.uji.geotec.wearossensorsdemo.command; + +import es.uji.geotec.wearossensors.sensor.WearSensor; + +public interface CollectionCommand { + void executeStart(WearSensor sensor); + void executeStop(WearSensor sensor); +} diff --git a/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/LocalCollectionCommand.java b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/LocalCollectionCommand.java new file mode 100644 index 0000000..5d819bb --- /dev/null +++ b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/LocalCollectionCommand.java @@ -0,0 +1,34 @@ +package es.uji.geotec.wearossensorsdemo.command; + +import android.content.Context; +import android.util.Log; + +import es.uji.geotec.backgroundsensors.collection.CollectionConfiguration; +import es.uji.geotec.backgroundsensors.service.manager.ServiceManager; +import es.uji.geotec.wearossensors.sensor.WearSensor; +import es.uji.geotec.wearossensors.services.WearSensorRecordingService; + +public class LocalCollectionCommand implements CollectionCommand { + + private ServiceManager serviceManager; + + public LocalCollectionCommand(Context context) { + this.serviceManager = new ServiceManager(context, WearSensorRecordingService.class); + } + @Override + public void executeStart(WearSensor sensor) { + CollectionConfiguration config = new CollectionConfiguration( + sensor, + android.hardware.SensorManager.SENSOR_DELAY_GAME, + sensor == WearSensor.HEART_RATE || sensor == WearSensor.LOCATION ? 1 : 50 + ); + this.serviceManager.startCollection(config, records -> { + Log.d("LOCAL COLLECTION", sensor.toString()+ " records: " + records.toString()); + }); + } + + @Override + public void executeStop(WearSensor sensor) { + this.serviceManager.stopCollection(sensor); + } +} diff --git a/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/RemoteCollectionCommand.java b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/RemoteCollectionCommand.java new file mode 100644 index 0000000..5679e72 --- /dev/null +++ b/app/src/main/java/es/uji/geotec/wearossensorsdemo/command/RemoteCollectionCommand.java @@ -0,0 +1,30 @@ +package es.uji.geotec.wearossensorsdemo.command; + +import android.content.Context; + +import es.uji.geotec.backgroundsensors.collection.CollectionConfiguration; +import es.uji.geotec.wearossensors.command.CommandClient; +import es.uji.geotec.wearossensors.sensor.WearSensor; + +public class RemoteCollectionCommand implements CollectionCommand { + + private CommandClient commandClient; + + public RemoteCollectionCommand(Context context) { + this.commandClient = new CommandClient(context); + } + @Override + public void executeStart(WearSensor sensor) { + CollectionConfiguration config = new CollectionConfiguration( + sensor, + android.hardware.SensorManager.SENSOR_DELAY_GAME, + sensor == WearSensor.HEART_RATE || sensor == WearSensor.LOCATION ? 1 : 50 + ); + this.commandClient.sendStartCommand(config); + } + + @Override + public void executeStop(WearSensor sensor) { + this.commandClient.sendStopCommand(sensor); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f9ac49a..3a78be2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,71 +6,101 @@ android:background="@color/dark_grey" tools:context=".MainActivity" tools:deviceIds="wear"> - - + + + + + + android:text="@string/select_collection_destination_txt" /> - + - + android:onClick="onDestinationButtonClicked" + android:text="@string/local_radio" /> - + android:onClick="onDestinationButtonClicked" + android:text="@string/remote_radio" /> + -