Merge remote-tracking branch 'origin/newTimestamps' into wifi_ftm
This commit is contained in:
46
.idea/assetWizardSettings.xml
generated
Normal file
46
.idea/assetWizardSettings.xml
generated
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WizardSettings">
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="vectorWizard">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="vectorAssetStep">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipartAsset">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="url" value="jar:file:/mnt/data/apps/android-studio/plugins/android/lib/android.jar!/images/material_design_icons/action/ic_3d_rotation_black_24dp.xml" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="outputName" value="ic_mess_around" />
|
||||
<entry key="sourceFile" value="$USER_HOME$" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
BIN
.idea/caches/build_file_checksums.ser
generated
Normal file
BIN
.idea/caches/build_file_checksums.ser
generated
Normal file
Binary file not shown.
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
||||
7
.idea/gradle.xml
generated
7
.idea/gradle.xml
generated
@@ -3,9 +3,11 @@
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="LOCAL" />
|
||||
<compositeConfiguration>
|
||||
<compositeBuild compositeDefinitionSource="SCRIPT" />
|
||||
</compositeConfiguration>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.10" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
@@ -13,6 +15,7 @@
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="testRunner" value="PLATFORM" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
26
.idea/misc.xml
generated
26
.idea/misc.xml
generated
@@ -1,30 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/SensorReadout.iml" filepath="$PROJECT_DIR$/SensorReadout.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sensorreadout.iml" filepath="$PROJECT_DIR$/sensorreadout.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
|
||||
12
.idea/runConfigurations.xml
generated
Normal file
12
.idea/runConfigurations.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,7 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.2'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "de.fhws.indoor.sensorreadout"
|
||||
@@ -20,10 +21,13 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:design:23.4.0'
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||
compile 'com.google.android.gms:play-services:10.2.0'
|
||||
implementation 'com.android.support:appcompat-v7:23.4.0'
|
||||
implementation 'com.google.android.gms:play-services:10.2.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
implementation 'org.apmem.tools:layouts:1.10@aar'
|
||||
//compile 'com.google.android.support:wearable:1.3.0'
|
||||
//compile 'com.google.android.gms:play-services-wearable:8.4.0'
|
||||
//provided 'com.google.android.wearable:wearable:1.0.0'
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.fhws.indoor.sensorreadout">
|
||||
>
|
||||
|
||||
<!-- <uses-feature android:name="android.hardware.type.watch" /> -->
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
@@ -13,8 +10,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.BODY_SENSORS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
|
||||
<uses-feature android:name="android.hardware.location.gps" />
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
@@ -24,6 +20,8 @@
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".SettingsActivity"></activity>
|
||||
|
||||
<uses-library
|
||||
android:name="com.google.android.wearable"
|
||||
android:required="false" />
|
||||
|
||||
@@ -4,59 +4,64 @@ import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.pm.ActivityInfoCompat;
|
||||
//import android.support.wearable.activity.WearableActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
|
||||
import com.google.android.gms.vision.text.Line;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import de.fhws.indoor.sensorreadout.sensors.Gps;
|
||||
import de.fhws.indoor.sensorreadout.sensors.GpsNew;
|
||||
import de.fhws.indoor.sensorreadout.sensors.GroundTruth;
|
||||
import de.fhws.indoor.sensorreadout.sensors.Logger;
|
||||
import de.fhws.indoor.sensorreadout.sensors.LoggerRAM;
|
||||
import de.fhws.indoor.sensorreadout.sensors.PedestrianActivity;
|
||||
import de.fhws.indoor.sensorreadout.sensors.PedestrianActivityButton;
|
||||
import de.fhws.indoor.sensorreadout.sensors.PhoneSensors;
|
||||
import de.fhws.indoor.sensorreadout.sensors.WiFi;
|
||||
import de.fhws.indoor.sensorreadout.sensors.WiFiRTT;
|
||||
import de.fhws.indoor.sensorreadout.sensors.iBeacon;
|
||||
import de.fhws.indoor.sensorreadout.sensors.iBeaconOld;
|
||||
import de.fhws.indoor.sensorreadout.sensors.mySensor;
|
||||
import de.fhws.indoor.sensorreadout.sensors.SensorType;
|
||||
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
MediaPlayer mpStart;
|
||||
MediaPlayer mpStop;
|
||||
MediaPlayer mpGround;
|
||||
MediaPlayer mpFailure;
|
||||
|
||||
private final ArrayList<mySensor> sensors = new ArrayList<mySensor>();
|
||||
private final Logger logger = new Logger(this);
|
||||
//private final Logger logger = new Logger(this);
|
||||
private final LoggerRAM logger = new LoggerRAM(this);
|
||||
private Button btnStart;
|
||||
private Button btnStop;
|
||||
private Button btnGround;
|
||||
private PedestrianActivityButton btnWalk;
|
||||
private PedestrianActivityButton btnStand;
|
||||
private PedestrianActivityButton btnStairsUp;
|
||||
private PedestrianActivityButton btnStairsDown;
|
||||
private PedestrianActivityButton btnElevatorUp;
|
||||
private PedestrianActivityButton btnElevatorDown;
|
||||
private PedestrianActivity currentPedestrianActivity;
|
||||
private PedestrianActivity pastPedestrianActivity;
|
||||
private Button btnSettings;
|
||||
private TableLayout activityButtonContainer;
|
||||
private HashMap<PedestrianActivity, PedestrianActivityButton> activityButtons = new HashMap<>();
|
||||
private PedestrianActivity currentPedestrianActivity = PedestrianActivity.STANDING;
|
||||
|
||||
private int groundTruthCounter = 0;
|
||||
private boolean isInitialized = false;
|
||||
@@ -71,10 +76,18 @@ public class MainActivity extends Activity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
// This static call will reset default values for preferences only on the first ever read
|
||||
PreferenceManager.setDefaultValues(getBaseContext(), R.xml.preferences, false);
|
||||
|
||||
// context access
|
||||
MainActivity.context = getApplicationContext();
|
||||
|
||||
// setup sound-effects
|
||||
mpStart = MediaPlayer.create(this, R.raw.go);
|
||||
mpStop = MediaPlayer.create(this, R.raw.go);
|
||||
mpGround = MediaPlayer.create(this, R.raw.go);
|
||||
mpFailure = MediaPlayer.create(this, R.raw.error);
|
||||
|
||||
//init Path spinner
|
||||
final Spinner pathSpinner = (Spinner) findViewById(R.id.pathspinner);
|
||||
List<String> pathList = new ArrayList<String>();
|
||||
@@ -101,31 +114,15 @@ public class MainActivity extends Activity {
|
||||
btnStart = (Button) findViewById(R.id.btnStart);
|
||||
btnStop = (Button) findViewById(R.id.btnStop);
|
||||
btnGround = (Button) findViewById(R.id.btnGround);
|
||||
|
||||
//get activity Buttons
|
||||
btnWalk = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnWalk), PedestrianActivity.WALK);
|
||||
btnStand = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStanding), PedestrianActivity.STANDING);
|
||||
btnStairsUp = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStairsUp), PedestrianActivity.STAIRS_UP);
|
||||
btnStairsDown = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStairsDown), PedestrianActivity.STAIRS_DOWN);
|
||||
btnElevatorUp = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnElevatorUp), PedestrianActivity.ELEVATOR_UP);
|
||||
btnElevatorDown = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnElevatorDown), PedestrianActivity.ELEVATOR_DOWN);
|
||||
|
||||
//set current activity
|
||||
btnStand.toggleActivity(); //first activity is standing!
|
||||
currentPedestrianActivity = PedestrianActivity.STANDING;
|
||||
|
||||
//Click Sound
|
||||
final MediaPlayer mpStart = MediaPlayer.create(this, R.raw.go);
|
||||
final MediaPlayer mpStop = MediaPlayer.create(this, R.raw.go);
|
||||
final MediaPlayer mpGround = MediaPlayer.create(this, R.raw.go);
|
||||
final MediaPlayer mpFailure = MediaPlayer.create(this, R.raw.error);
|
||||
btnSettings = (Button) findViewById(R.id.btnSettings);
|
||||
activityButtonContainer = (TableLayout) findViewById(R.id.pedestrianActivityButtonContainer);
|
||||
|
||||
// log GroundTruth ButtonClicks using sensor number 99
|
||||
final GroundTruth grndTruth = new GroundTruth(this);
|
||||
sensors.add(grndTruth);
|
||||
grndTruth.setListener(new mySensor.SensorListener() {
|
||||
@Override public void onData(final String csv) { return; }
|
||||
@Override public void onData(SensorType id, final String csv) {add(id, csv); }
|
||||
@Override public void onData(final long timestamp, final String csv) { return; }
|
||||
@Override public void onData(SensorType id, final long timestamp, final String csv) {add(id, csv, timestamp); }
|
||||
});
|
||||
|
||||
|
||||
@@ -145,7 +142,7 @@ public class MainActivity extends Activity {
|
||||
grndTruth.writeGroundTruth(groundTruthCounter);
|
||||
|
||||
//Write first activity
|
||||
add(SensorType.PEDESTRIAN_ACTIVITY, PedestrianActivity.STANDING.toString() + ";" + PedestrianActivity.STANDING.ordinal());
|
||||
add(SensorType.PEDESTRIAN_ACTIVITY, PedestrianActivity.STANDING.toString() + ";" + PedestrianActivity.STANDING.ordinal(), Logger.BEGINNING_TS);
|
||||
|
||||
//Disable the spinners
|
||||
groundSpinner.setEnabled(false);
|
||||
@@ -154,7 +151,6 @@ public class MainActivity extends Activity {
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -175,7 +171,7 @@ public class MainActivity extends Activity {
|
||||
pathSpinner.setEnabled(true);
|
||||
|
||||
//reset activity buttons
|
||||
setActivityBtn(PedestrianActivity.STANDING);
|
||||
setActivityBtn(PedestrianActivity.STANDING, false);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
@@ -202,174 +198,28 @@ public class MainActivity extends Activity {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
btnWalk.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.WALK);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnStand.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.STANDING);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnStairsUp.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.STAIRS_UP);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnStairsDown.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.STAIRS_DOWN);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnElevatorUp.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.ELEVATOR_UP);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnElevatorDown.getLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(PedestrianActivity.ELEVATOR_DOWN);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//all Sensors
|
||||
final PhoneSensors phoneSensors = new PhoneSensors(this);
|
||||
sensors.add(phoneSensors);
|
||||
phoneSensors.setListener(new mySensor.SensorListener(){
|
||||
@Override public void onData(final String csv) { return; }
|
||||
@Override public void onData(final SensorType id, final String csv) {add(id, csv); }
|
||||
});
|
||||
|
||||
// logo wifi using sensor number 8
|
||||
// final WiFi wifi = new WiFi(this);
|
||||
// sensors.add(wifi);
|
||||
// wifi.setListener(new mySensor.SensorListener() {
|
||||
// @Override public void onData(final String csv) { add(SensorType.WIFI, csv); }
|
||||
// @Override public void onData(final SensorType id, final String csv) {return; }
|
||||
// });
|
||||
|
||||
// log wifi RTT using sensor number 17
|
||||
final WiFiRTT wifirtt = new WiFiRTT(this);
|
||||
sensors.add(wifirtt);
|
||||
wifirtt.setListener(new mySensor.SensorListener() {
|
||||
@Override public void onData(final String csv) { add(SensorType.WIFIRTT, csv); }
|
||||
@Override public void onData(final SensorType id, final String csv) {add(id, csv); }
|
||||
});
|
||||
|
||||
//log gps using sensor number 16
|
||||
final GpsNew gps = new GpsNew(this);
|
||||
sensors.add(gps);
|
||||
gps.setListener(new mySensor.SensorListener(){
|
||||
@Override public void onData(final String csv) { add(SensorType.GPS, csv); }
|
||||
@Override public void onData(final SensorType id, final String csv) {return; }
|
||||
});
|
||||
|
||||
// log iBeacons using sensor number 9
|
||||
final mySensor beacon;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
beacon = new iBeacon(this);
|
||||
} else{
|
||||
beacon = new iBeaconOld(this);
|
||||
}
|
||||
|
||||
sensors.add(beacon);
|
||||
beacon.setListener(new mySensor.SensorListener() {
|
||||
@Override public void onData(final String csv) { add(SensorType.IBEACON, csv); }
|
||||
@Override public void onData(final SensorType id, final String csv) {return; }
|
||||
});
|
||||
|
||||
|
||||
// bluetooth permission
|
||||
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
btnSettings.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(!isInitialized) { // Only allow when not currently running
|
||||
startActivity(new Intent(context, SettingsActivity.class));
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
MY_PERMISSIONS_REQUEST_READ_BT);
|
||||
mpFailure.start();
|
||||
}
|
||||
|
||||
// heartbeat permission
|
||||
/* if(ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.BODY_SENSORS)) {
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.BODY_SENSORS},
|
||||
MY_PERMISSIONS_REQUEST_READ_HEART);
|
||||
}*/
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void setActivityBtn(PedestrianActivity act){
|
||||
|
||||
// set and write new activity
|
||||
if(currentPedestrianActivity != act){
|
||||
|
||||
// toggle past and current activity
|
||||
PedestrianActivity[] tmpActArray = new PedestrianActivity[] {currentPedestrianActivity, act};
|
||||
|
||||
for(PedestrianActivity a : tmpActArray){
|
||||
switch (a) {
|
||||
case WALK: btnWalk.toggleActivity();
|
||||
break;
|
||||
case STANDING: btnStand.toggleActivity();
|
||||
break;
|
||||
case STAIRS_UP: btnStairsUp.toggleActivity();
|
||||
break;
|
||||
case STAIRS_DOWN: btnStairsDown.toggleActivity();
|
||||
break;
|
||||
case ELEVATOR_UP: btnElevatorUp.toggleActivity();
|
||||
break;
|
||||
case ELEVATOR_DOWN: btnElevatorDown.toggleActivity();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
private void setActivityBtn(PedestrianActivity newActivity, boolean logChange){
|
||||
if(activityButtons.containsKey(currentPedestrianActivity)) {
|
||||
activityButtons.get(currentPedestrianActivity).setActivity(false);
|
||||
}
|
||||
currentPedestrianActivity = newActivity;
|
||||
activityButtons.get(newActivity).setActivity(true);
|
||||
if(logChange) {
|
||||
add(SensorType.PEDESTRIAN_ACTIVITY, newActivity.toString() + ";" + newActivity.ordinal());
|
||||
}
|
||||
|
||||
currentPedestrianActivity = act;
|
||||
add(SensorType.PEDESTRIAN_ACTIVITY, act.toString() + ";" + act.ordinal());
|
||||
} else {
|
||||
//do nothin
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void start() {
|
||||
@@ -395,31 +245,45 @@ public class MainActivity extends Activity {
|
||||
private int loadCounterGPS = 0;
|
||||
private int loadCounterAny = 0;
|
||||
private void add(final SensorType id, final String csv) {
|
||||
add(id, csv, SystemClock.elapsedRealtimeNanos());
|
||||
}
|
||||
private void add(final SensorType id, final String csv, final long timestamp) {
|
||||
|
||||
logger.addCSV(id, csv);
|
||||
logger.addCSV(id, timestamp, csv);
|
||||
|
||||
|
||||
// update UI for WIFI/BEACON/GPS
|
||||
if (id == SensorType.WIFI || id == SensorType.IBEACON || id == SensorType.GPS) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override public void run() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (id == SensorType.WIFI) {
|
||||
final TextView txt = (TextView) findViewById(R.id.txtWifi);
|
||||
txt.setText( ((++loadCounterWifi % 2) == 0) ? "wi" : "WI");
|
||||
} else if (id == SensorType.IBEACON){
|
||||
txt.setText(((++loadCounterWifi % 2) == 0) ? "wi" : "WI");
|
||||
} else if (id == SensorType.IBEACON) {
|
||||
final TextView txt = (TextView) findViewById(R.id.txtBeacon);
|
||||
txt.setText( ((++loadCounterBeacon % 2) == 0) ? "ib" : "IB");
|
||||
} else if (id == SensorType.GPS){
|
||||
txt.setText(((++loadCounterBeacon % 2) == 0) ? "ib" : "IB");
|
||||
} else if (id == SensorType.GPS) {
|
||||
final TextView txt = (TextView) findViewById(R.id.txtGPS);
|
||||
txt.setText( ((++loadCounterGPS % 2) == 0) ? "gps" : "GPS");}
|
||||
txt.setText(((++loadCounterGPS % 2) == 0) ? "gps" : "GPS");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// dump buffer stats every x entries
|
||||
if (++loadCounterAny % 250 == 0) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final TextView txt = (TextView) findViewById(R.id.txtBuffer);
|
||||
final int kbPerMin = (int) (logger.getTotalSize() / 1024 * 1000 * 60 / (System.currentTimeMillis() - logger.getStartTS()));
|
||||
txt.setText( (logger.getCurrentSize() / 1024) + "k, " + logger.getNumEntries() + ", " + kbPerMin + "k/m");
|
||||
}
|
||||
|
||||
final float elapsedMinutes = (timestamp - logger.getStartTS()) / 1000.0f / 1000.0f / 1000.0f / 60.0f;
|
||||
final int kBPerMin = (int) (logger.getTotalSize() / 1024.0f / elapsedMinutes);
|
||||
txt.setText((logger.getCurrentBufferSize() / 1024) + "k, " + logger.getNumEntries() + ", " + kBPerMin + "kB/m");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -429,11 +293,20 @@ public class MainActivity extends Activity {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if(!isInitialized) {
|
||||
// Do not apply new settings when recording is currently running, since we can't have come
|
||||
// from the SettingsActivity, then.
|
||||
setupActivityButtons();
|
||||
setupSensors();
|
||||
}
|
||||
}
|
||||
|
||||
/** resume activity */
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
//print memory info
|
||||
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
|
||||
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
||||
@@ -468,4 +341,151 @@ public class MainActivity extends Activity {
|
||||
return MainActivity.context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected void setupActivityButtons() {
|
||||
// cleanup before recreation
|
||||
for(int i = 0; i < activityButtonContainer.getChildCount(); ++i) {
|
||||
TableRow buttonRow = (TableRow)activityButtonContainer.getChildAt(i);
|
||||
buttonRow.removeAllViews();
|
||||
}
|
||||
activityButtonContainer.removeAllViews();
|
||||
activityButtons.clear();
|
||||
|
||||
// setup activity buttons
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
Set<String> activeActivities = preferences.getStringSet("prefActiveActions", new HashSet<String>());
|
||||
|
||||
activityButtons.put(PedestrianActivity.STANDING, new PedestrianActivityButton(this, PedestrianActivity.STANDING, R.drawable.ic_standing));
|
||||
if(activeActivities.contains("WALK")) {
|
||||
activityButtons.put(PedestrianActivity.WALK, new PedestrianActivityButton(this, PedestrianActivity.WALK, R.drawable.ic_walk));
|
||||
}
|
||||
if(activeActivities.contains("ELEVATOR")) {
|
||||
activityButtons.put(PedestrianActivity.ELEVATOR_UP, new PedestrianActivityButton(this, PedestrianActivity.ELEVATOR_UP, R.drawable.ic_elevator_up));
|
||||
activityButtons.put(PedestrianActivity.ELEVATOR_DOWN, new PedestrianActivityButton(this, PedestrianActivity.ELEVATOR_DOWN, R.drawable.ic_elevator_down));
|
||||
}
|
||||
if(activeActivities.contains("STAIRS")) {
|
||||
activityButtons.put(PedestrianActivity.STAIRS_UP, new PedestrianActivityButton(this, PedestrianActivity.STAIRS_UP, R.drawable.ic_stairs_up));
|
||||
activityButtons.put(PedestrianActivity.STAIRS_DOWN, new PedestrianActivityButton(this, PedestrianActivity.STAIRS_DOWN, R.drawable.ic_stairs_down));
|
||||
}
|
||||
if(activeActivities.contains("MESS_AROUND")) {
|
||||
activityButtons.put(PedestrianActivity.MESS_AROUND, new PedestrianActivityButton(this, PedestrianActivity.MESS_AROUND, R.drawable.ic_mess_around));
|
||||
}
|
||||
int activityButtonColumns = 1;
|
||||
if(activityButtons.size() > 6) { activityButtonColumns = 4; }
|
||||
else if(activityButtons.size() > 4) { activityButtonColumns = 3; }
|
||||
else if(activityButtons.size() > 2) { activityButtonColumns = 2; }
|
||||
|
||||
TableLayout.LayoutParams rowLayout = new TableLayout.LayoutParams();
|
||||
rowLayout.width = LayoutParams.MATCH_PARENT;
|
||||
rowLayout.height = LayoutParams.WRAP_CONTENT;
|
||||
rowLayout.weight = 1.0f;
|
||||
TableRow.LayoutParams columnLayout = new TableRow.LayoutParams();
|
||||
columnLayout.height = LayoutParams.MATCH_PARENT;
|
||||
columnLayout.width = 1; // set minWidth to 1, because this will be stretched, and the images adjust in size
|
||||
columnLayout.weight = 1.0f;
|
||||
PedestrianActivity[] activeActiviesArray = activityButtons.keySet().toArray(new PedestrianActivity[activityButtons.size()]);
|
||||
Arrays.sort(activeActiviesArray);
|
||||
TableRow currentButtonRow = null;
|
||||
for(int i = 0; i < activeActiviesArray.length; ++i) {
|
||||
final PedestrianActivityButton button = activityButtons.get(activeActiviesArray[i]);
|
||||
if(i % activityButtonColumns == 0) {
|
||||
currentButtonRow = new TableRow(this);
|
||||
currentButtonRow.setWeightSum(1.0f * activityButtonColumns);
|
||||
activityButtonContainer.addView(currentButtonRow, rowLayout);
|
||||
}
|
||||
currentButtonRow.addView(button, columnLayout);
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(isInitialized) {
|
||||
setActivityBtn(button.getPedestrianActivity(), true);
|
||||
}
|
||||
else{
|
||||
mpFailure.start();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set current activity
|
||||
setActivityBtn(PedestrianActivity.STANDING, false);
|
||||
}
|
||||
|
||||
protected void setupSensors() {
|
||||
//cleanup first
|
||||
sensors.clear();
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
Set<String> activeSensors = preferences.getStringSet("prefActiveSensors", new HashSet<String>());
|
||||
|
||||
if(activeSensors.contains("PHONE")) {
|
||||
// heartbeat permission
|
||||
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.BODY_SENSORS)) {
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.BODY_SENSORS},
|
||||
MY_PERMISSIONS_REQUEST_READ_HEART);
|
||||
}
|
||||
|
||||
//all Phone-Sensors (Accel, Gyro, Magnet, ...)
|
||||
final PhoneSensors phoneSensors = new PhoneSensors(this);
|
||||
sensors.add(phoneSensors);
|
||||
phoneSensors.setListener(new mySensor.SensorListener(){
|
||||
@Override public void onData(final long timestamp, final String csv) { return; }
|
||||
@Override public void onData(final SensorType id, final long timestamp, final String csv) {add(id, csv, timestamp); }
|
||||
});
|
||||
}
|
||||
if(activeSensors.contains("GPS")) {
|
||||
//log gps using sensor number 16
|
||||
final GpsNew gps = new GpsNew(this);
|
||||
sensors.add(gps);
|
||||
gps.setListener(new mySensor.SensorListener(){
|
||||
@Override public void onData(final long timestamp, final String csv) { add(SensorType.GPS, csv, timestamp); }
|
||||
@Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
|
||||
});
|
||||
}
|
||||
if(activeSensors.contains("WIFI")) {
|
||||
// log wifi using sensor number 8
|
||||
final WiFi wifi = new WiFi(this);
|
||||
sensors.add(wifi);
|
||||
wifi.setListener(new mySensor.SensorListener() {
|
||||
@Override public void onData(final long timestamp, final String csv) { add(SensorType.WIFI, csv, timestamp); }
|
||||
@Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
|
||||
});
|
||||
}
|
||||
if(activeSensors.contains("BLUETOOTH")) {
|
||||
// bluetooth permission
|
||||
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
MY_PERMISSIONS_REQUEST_READ_BT);
|
||||
}
|
||||
|
||||
// log iBeacons using sensor number 9
|
||||
final mySensor beacon;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
beacon = new iBeacon(this);
|
||||
} else {
|
||||
beacon = null;
|
||||
//beacon = new iBeaconOld(this);
|
||||
}
|
||||
|
||||
if (beacon != null) {
|
||||
sensors.add(beacon);
|
||||
beacon.setListener(new mySensor.SensorListener() {
|
||||
@Override public void onData(final long timestamp, final String csv) { add(SensorType.IBEACON, csv, timestamp); }
|
||||
@Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.fhws.indoor.sensorreadout;
|
||||
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.fhws.indoor.sensorreadout;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class SettingsFragment extends PreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class Gps extends mySensor implements LocationListener {
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.GRAVITY,
|
||||
listener.onData(SensorType.GRAVITY, location.getElapsedRealtimeNanos(), //TODO: Is this correct? SystemClock.elapsedRealtimeNanos() otherwise..
|
||||
Double.toString(location.getLatitude()) + ";" +
|
||||
Double.toString(location.getLongitude()) + ";" +
|
||||
Double.toString(location.getAltitude()) + ";" +
|
||||
|
||||
@@ -169,7 +169,7 @@ public class GpsNew extends mySensor implements ConnectionCallbacks, OnConnectio
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.GRAVITY,
|
||||
listener.onData(SensorType.GRAVITY, location.getElapsedRealtimeNanos(), //TODO: Is this correct? SystemClock.elapsedRealtimeNanos() otherwise..
|
||||
Double.toString(location.getLatitude()) + ";" +
|
||||
Double.toString(location.getLongitude()) + ";" +
|
||||
Double.toString(location.getAltitude()) + ";" +
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.fhws.indoor.sensorreadout.sensors;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.SystemClock;
|
||||
|
||||
/**
|
||||
* Created by Toni on 02.06.2015.
|
||||
@@ -12,14 +13,14 @@ public class GroundTruth extends mySensor {
|
||||
}
|
||||
|
||||
public void writeGroundTruth(final int groundTruthCounter){
|
||||
if (listener != null){listener.onData(SensorType.GROUND_TRUTH,
|
||||
if (listener != null){listener.onData(SensorType.GROUND_TRUTH, SystemClock.elapsedRealtimeNanos(),
|
||||
Integer.toString(groundTruthCounter)
|
||||
);}
|
||||
}
|
||||
|
||||
public void writeInitData(int pathID, int numGroundTruthPoints){
|
||||
|
||||
if (listener != null){listener.onData(SensorType.GROUND_TRUTH_PATH,
|
||||
if (listener != null){listener.onData(SensorType.GROUND_TRUTH_PATH, SystemClock.elapsedRealtimeNanos(),
|
||||
Integer.toString(pathID) + ";" +
|
||||
Integer.toString(numGroundTruthPoints)
|
||||
);}
|
||||
|
||||
@@ -2,27 +2,41 @@ package de.fhws.indoor.sensorreadout.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
/**
|
||||
* log sensor data to file
|
||||
* Created by Frank on 25.03.2015.
|
||||
* Re-Written by Markus on 20.06.2019.
|
||||
*/
|
||||
public final class Logger {
|
||||
|
||||
private static final int FLUSH_LIMIT = 2*1024*1024;
|
||||
public static final long BEGINNING_TS = -1;
|
||||
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
private static final int CACHED_ENTRIES = 1000;
|
||||
private static final int FLUSH_BATCH_SIZE = 100;
|
||||
|
||||
private StringBuilder stringBuilder = new StringBuilder();
|
||||
private File file;
|
||||
private FileOutputStream fos;
|
||||
private Context context;
|
||||
|
||||
private int entries = 0;
|
||||
private int sizeCurrent = 0;
|
||||
private int sizeTotal = 0;
|
||||
private int currentSize = 0;
|
||||
|
||||
private volatile boolean addingStopped = false; // Just to be sure
|
||||
private PriorityQueue<LogEntry> reorderBuffer = new PriorityQueue<>(2 * CACHED_ENTRIES + FLUSH_BATCH_SIZE);
|
||||
private Semaphore flushSemaphore = new Semaphore(0);
|
||||
private WriteBackWorker writeBackWorker;
|
||||
|
||||
/** timestamp of logging start. all entries are relative to this one */
|
||||
private long startTS = 0;
|
||||
@@ -35,13 +49,15 @@ public final class Logger {
|
||||
public final void start() {
|
||||
|
||||
// start empty
|
||||
sb.setLength(0);
|
||||
stringBuilder.setLength(0);
|
||||
entries = 0;
|
||||
sizeTotal = 0;
|
||||
sizeCurrent = 0;
|
||||
addingStopped = false;
|
||||
flushSemaphore.drainPermits();
|
||||
writeBackWorker = new WriteBackWorker();
|
||||
|
||||
// starting timestamp
|
||||
startTS = System.currentTimeMillis();
|
||||
startTS = SystemClock.elapsedRealtimeNanos();
|
||||
|
||||
// open the output-file immeditaly (to get permission errors)
|
||||
// but do NOT yet write anything to the file
|
||||
@@ -54,88 +70,68 @@ public final class Logger {
|
||||
} catch (final Exception e) {
|
||||
throw new MyException("error while opening log-file", e);
|
||||
}
|
||||
|
||||
writeBackWorker.start();
|
||||
}
|
||||
|
||||
/** stop logging and flush RAM-data to the flash-chip */
|
||||
public final void stop() {
|
||||
synchronized (this) {
|
||||
flush(true);
|
||||
close();
|
||||
debug(true);
|
||||
synchronized (reorderBuffer) {
|
||||
addingStopped = true;
|
||||
// Unblock WriteBackThread for all remaining log-lines (+1)
|
||||
// some elements in reorderBuffer could already have been released for flushing -> this might release more than necessary.
|
||||
flushSemaphore.release(reorderBuffer.size() + 1);
|
||||
}
|
||||
// wait for flushing to succeed
|
||||
try {
|
||||
writeBackWorker.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
debug(true);
|
||||
close();
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public int getCurrentSize() {return sizeCurrent;}
|
||||
public int getCurrentBufferSize() {return currentSize;}
|
||||
public int getTotalSize() {return sizeTotal;}
|
||||
|
||||
public int getNumEntries() {return entries;}
|
||||
|
||||
/** add a new CSV entry for the given sensor number to the internal buffer */
|
||||
public final void addCSV(final SensorType sensorNr, final String csv) {
|
||||
synchronized (this) {
|
||||
final long relTS = System.currentTimeMillis() - startTS;
|
||||
sb.append(relTS); // relative timestamp (uses less space)
|
||||
sb.append(';');
|
||||
sb.append(sensorNr.id());
|
||||
sb.append(';');
|
||||
sb.append(csv);
|
||||
sb.append('\n');
|
||||
public final void addCSV(final SensorType sensorNr, final long timestamp, final String csv) {
|
||||
final long relTS = (timestamp == BEGINNING_TS) ? 0 : (timestamp - startTS);
|
||||
if(relTS >= 0) { // drop pre startTS logs (at the beginning, sensors sometimes deliver old values)
|
||||
synchronized (reorderBuffer) {
|
||||
if(addingStopped) {
|
||||
// addCSV was called after calling stop();
|
||||
return;
|
||||
}
|
||||
|
||||
stringBuilder.append(relTS); // relative timestamp (uses less space)
|
||||
stringBuilder.append(';');
|
||||
stringBuilder.append(sensorNr.id());
|
||||
stringBuilder.append(';');
|
||||
stringBuilder.append(csv);
|
||||
stringBuilder.append('\n');
|
||||
++entries;
|
||||
sizeTotal += csv.length() + 10; // approx!
|
||||
sizeCurrent = sb.length();
|
||||
if (sb.length() > FLUSH_LIMIT) {flush(false);}
|
||||
}
|
||||
LogEntry logEntry = new LogEntry(relTS, stringBuilder.toString());
|
||||
sizeTotal += logEntry.csv.length();
|
||||
currentSize += logEntry.csv.length();
|
||||
stringBuilder.setLength(0);
|
||||
|
||||
debug();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** helper method for exception-less writing. DO NOT CALL DIRECTLY! */
|
||||
private final void _write(final byte[] data) {
|
||||
try {
|
||||
fos.write(data);
|
||||
Log.d("logger", "flushed " + data.length + " bytes to disk");
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("error while writing log-file", e);
|
||||
// commit to reorder-buffer and start flush (if necessary)
|
||||
reorderBuffer.add(logEntry);
|
||||
if(flushSemaphore.availablePermits() == 0 && reorderBuffer.size() > (CACHED_ENTRIES + FLUSH_BATCH_SIZE)) {
|
||||
// Unblock WriteBackThread and allow it to flush FLUSH_BATCH_SIZE csv-lines.
|
||||
flushSemaphore.release(reorderBuffer.size() - CACHED_ENTRIES);
|
||||
}
|
||||
}
|
||||
|
||||
/** helper-class for background writing */
|
||||
class FlushAsync extends AsyncTask<byte[], Integer, Integer> {
|
||||
@Override
|
||||
protected final Integer doInBackground(byte[][] data) {
|
||||
_write(data[0]);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/** flush current buffer-contents to disk */
|
||||
private final void flush(boolean sync) {
|
||||
|
||||
// fetch current buffer contents to write and hereafter empty the buffer
|
||||
// this action MUST be atomic, just like the add-method
|
||||
byte[] data = null;
|
||||
synchronized (this) {
|
||||
data = sb.toString().getBytes(); // fetch data to write
|
||||
sb.setLength(0); // reset the buffer
|
||||
sizeCurrent = 0;
|
||||
}
|
||||
|
||||
// write
|
||||
if (sync) {
|
||||
// write to disk using the current thread
|
||||
_write(data);
|
||||
} else {
|
||||
// write to disk using a background-thread
|
||||
new FlushAsync().execute(new byte[][] {data});
|
||||
}
|
||||
|
||||
|
||||
debug(false);
|
||||
}
|
||||
|
||||
private final void close() {
|
||||
@@ -151,10 +147,67 @@ public final class Logger {
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
private final void debug() {
|
||||
if (++cnt % 1000 == 0) {
|
||||
Log.d("buffer", "size: " + sizeCurrent);
|
||||
private final void debug(boolean force) {
|
||||
if (++cnt % 1000 == 0 || force) {
|
||||
Log.d("buffer", "size: " + reorderBuffer.size() + " lines");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class LogEntry implements Comparable<LogEntry> {
|
||||
public long timestamp;
|
||||
public String csv;
|
||||
|
||||
public LogEntry(long timestamp, String csv) {
|
||||
this.timestamp = timestamp;
|
||||
this.csv = csv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull LogEntry another) {
|
||||
return (timestamp < another.timestamp) ? (-1) : (+1);
|
||||
}
|
||||
}
|
||||
|
||||
private class WriteBackWorker extends Thread {
|
||||
|
||||
public WriteBackWorker() {
|
||||
setName("WriteBackWorker");
|
||||
setPriority(Thread.MIN_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean stop = false;
|
||||
while(!stop) {
|
||||
flushSemaphore.acquireUninterruptibly();
|
||||
|
||||
LogEntry[] entriesToFlush = null;
|
||||
synchronized (reorderBuffer) {
|
||||
int flushBatchSize = 1 + flushSemaphore.drainPermits(); // might contain extra-permit for stop-unblocking
|
||||
if(flushBatchSize > reorderBuffer.size()) { // We were unblocked more than there are available lines to fush -> request to flush all & stop
|
||||
stop = true;
|
||||
flushBatchSize = reorderBuffer.size();
|
||||
}
|
||||
entriesToFlush = new LogEntry[flushBatchSize];
|
||||
|
||||
for(int i = 0; i < flushBatchSize; ++i) {
|
||||
entriesToFlush[i] = reorderBuffer.poll();
|
||||
currentSize -= entriesToFlush[i].csv.length();
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < entriesToFlush.length; ++i) {
|
||||
fos.write(entriesToFlush[i].csv.getBytes());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
package de.fhws.indoor.sensorreadout.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* log sensor data to RAM
|
||||
* only flush to file when finished
|
||||
*/
|
||||
public final class LoggerRAM {
|
||||
|
||||
public static final long BEGINNING_TS = -1;
|
||||
|
||||
|
||||
private StringBuilder stringBuilder = new StringBuilder();
|
||||
private File file;
|
||||
private FileOutputStream fos;
|
||||
private Context context;
|
||||
|
||||
private boolean addingStopped = false;
|
||||
private int entries = 0;
|
||||
private int sizeTotal = 0;
|
||||
private int currentSize = 0;
|
||||
|
||||
private ArrayList<LogEntry> buffer = new ArrayList<>();
|
||||
|
||||
/** timestamp of logging start. all entries are relative to this one */
|
||||
private long startTS = 0;
|
||||
|
||||
public LoggerRAM(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/** start logging (into RAM) */
|
||||
public final void start() {
|
||||
|
||||
// start empty
|
||||
stringBuilder.setLength(0);
|
||||
entries = 0;
|
||||
sizeTotal = 0;
|
||||
currentSize = 0;
|
||||
buffer.clear();
|
||||
addingStopped = false;
|
||||
|
||||
// starting timestamp
|
||||
startTS = SystemClock.elapsedRealtimeNanos();
|
||||
|
||||
// open the output-file immeditaly (to get permission errors)
|
||||
// but do NOT yet write anything to the file
|
||||
final DataFolder folder = new DataFolder(context, "sensorOutFiles");
|
||||
file = new File(folder.getFolder(), startTS + ".csv");
|
||||
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
Log.d("logger", "will write to: " + file.toString());
|
||||
} catch (final Exception e) {
|
||||
throw new MyException("error while opening log-file", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** stop logging and flush RAM-data to the flash-chip */
|
||||
public final void stop() {
|
||||
|
||||
addingStopped = true;
|
||||
|
||||
synchronized (buffer) {
|
||||
|
||||
// sort by TS (ensure strict ordering)
|
||||
Collections.sort(buffer);
|
||||
|
||||
// export each entry
|
||||
for (LogEntry e : buffer) {
|
||||
try {
|
||||
fos.write(e.csv.getBytes());
|
||||
} catch (final Exception ex) {
|
||||
ex.printStackTrace();;
|
||||
}
|
||||
}
|
||||
|
||||
// done
|
||||
buffer.clear();
|
||||
|
||||
}
|
||||
|
||||
// done
|
||||
close();
|
||||
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public int getCurrentBufferSize() {return currentSize;}
|
||||
public int getTotalSize() {return sizeTotal;}
|
||||
|
||||
public int getNumEntries() {return entries;}
|
||||
|
||||
/** add a new CSV entry for the given sensor number to the internal buffer */
|
||||
public final void addCSV(final SensorType sensorNr, final long timestamp, final String csv) {
|
||||
|
||||
if (addingStopped) {return;}
|
||||
|
||||
final long relTS = (timestamp == BEGINNING_TS) ? 0 : (timestamp - startTS);
|
||||
if(relTS >= 0) { // drop pre startTS logs (at the beginning, sensors sometimes deliver old values)
|
||||
|
||||
stringBuilder.setLength(0);
|
||||
stringBuilder.append(relTS); // relative timestamp (uses less space)
|
||||
stringBuilder.append(';');
|
||||
stringBuilder.append(sensorNr.id());
|
||||
stringBuilder.append(';');
|
||||
stringBuilder.append(csv);
|
||||
stringBuilder.append('\n');
|
||||
++entries;
|
||||
LogEntry logEntry = new LogEntry(relTS, stringBuilder.toString());
|
||||
sizeTotal += logEntry.csv.length();
|
||||
currentSize += logEntry.csv.length();
|
||||
|
||||
synchronized (buffer) {
|
||||
buffer.add(logEntry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final void close() {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (final Exception e) {
|
||||
throw new MyException("error while writing log-file", e);
|
||||
}
|
||||
}
|
||||
|
||||
public final long getStartTS() {
|
||||
return startTS;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
private final void debug(boolean force) {
|
||||
if (++cnt % 1000 == 0 || force) {
|
||||
Log.d("buffer", "size: " + buffer.size() + " lines");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class LogEntry implements Comparable<LogEntry> {
|
||||
public long timestamp;
|
||||
public String csv;
|
||||
|
||||
public LogEntry(long timestamp, String csv) {
|
||||
this.timestamp = timestamp;
|
||||
this.csv = csv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull LogEntry another) {
|
||||
return (timestamp < another.timestamp) ? (-1) : (+1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ public enum PedestrianActivity {
|
||||
STAIRS_DOWN(3),
|
||||
ELEVATOR_UP(4),
|
||||
ELEVATOR_DOWN(5),
|
||||
MESS_AROUND(6),
|
||||
;
|
||||
|
||||
private int id;
|
||||
|
||||
@@ -1,35 +1,45 @@
|
||||
package de.fhws.indoor.sensorreadout.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.fhws.indoor.sensorreadout.R;
|
||||
|
||||
/**
|
||||
* Created by toni on 10/01/18.
|
||||
* Extended by Markus on 19/06/19
|
||||
*/
|
||||
|
||||
public class PedestrianActivityButton {
|
||||
public class PedestrianActivityButton extends LinearLayout {
|
||||
|
||||
private LinearLayout btn;
|
||||
private boolean isActivated = false;
|
||||
private PedestrianActivity whatActivity;
|
||||
private LinearLayout innerBtn;
|
||||
private boolean isActive = false;
|
||||
private PedestrianActivity activity;
|
||||
|
||||
public PedestrianActivityButton(LinearLayout btn, PedestrianActivity act){
|
||||
this.btn = btn;
|
||||
this.whatActivity = act;
|
||||
public PedestrianActivityButton(Context context, PedestrianActivity activity, @DrawableRes int imageId) {
|
||||
super(context);
|
||||
inflate(getContext(), R.layout.pedestrian_activity_button, this);
|
||||
this.activity = activity;
|
||||
// setup ui
|
||||
ImageView imageView = (ImageView)this.findViewById(R.id.activityButtonImage);
|
||||
imageView.setImageResource(imageId);
|
||||
TextView textView = (TextView)this.findViewById(R.id.activityButtonText);
|
||||
textView.setText(activity.toString());
|
||||
innerBtn = (LinearLayout)getChildAt(0);
|
||||
setActivity(false);
|
||||
}
|
||||
|
||||
public void toggleActivity(){
|
||||
isActivated = !isActivated;
|
||||
|
||||
if(isActivated){
|
||||
btn.setBackgroundColor(Color.parseColor("#F9D737"));
|
||||
} else {
|
||||
btn.setBackgroundColor(Color.parseColor("#B2B2B2"));
|
||||
}
|
||||
public void setActivity(boolean active) {
|
||||
this.isActive = active;
|
||||
innerBtn.setBackgroundColor(Color.parseColor(
|
||||
(isActive) ? "#F9D737" : "#B2B2B2"
|
||||
));
|
||||
}
|
||||
|
||||
public LinearLayout getLayout(){
|
||||
return btn;
|
||||
}
|
||||
public PedestrianActivity getPedestrianActivity() { return this.activity; }
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
private Sensor rotationVector;
|
||||
private Sensor light;
|
||||
private Sensor temperature;
|
||||
private Sensor gameRotationVector;
|
||||
|
||||
/** local gravity copy (needed for orientation matrix) */
|
||||
private float[] mGravity = new float[3];
|
||||
@@ -65,6 +66,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
rotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
|
||||
light = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||
temperature = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
|
||||
gameRotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
|
||||
|
||||
// dump sensor-vendor info to file
|
||||
dumpVendors(act);
|
||||
@@ -102,6 +104,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
dumpSensor(sb, SensorType.LIGHT, light);
|
||||
dumpSensor(sb, SensorType.AMBIENT_TEMPERATURE, temperature);
|
||||
dumpSensor(sb, SensorType.HEART_RATE, heart);
|
||||
dumpSensor(sb, SensorType.GAME_ROTATION_VECTOR, gameRotationVector);
|
||||
|
||||
// write
|
||||
fos.write(sb.toString().getBytes());
|
||||
@@ -139,13 +142,12 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
|
||||
/*
|
||||
// to compare with the other orientation
|
||||
if(event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.ORIENTATION_OLD,
|
||||
listener.onData(SensorType.ORIENTATION_OLD, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -153,13 +155,12 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
if(event.sensor.getType() == Sensor.TYPE_HEART_RATE) {
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.HEART_RATE,
|
||||
listener.onData(SensorType.HEART_RATE, event.timestamp,
|
||||
Float.toString(event.values[0])
|
||||
);
|
||||
}
|
||||
@@ -170,7 +171,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.LIGHT,
|
||||
listener.onData(SensorType.LIGHT, event.timestamp,
|
||||
Float.toString(event.values[0])
|
||||
);
|
||||
}
|
||||
@@ -181,7 +182,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.AMBIENT_TEMPERATURE,
|
||||
listener.onData(SensorType.AMBIENT_TEMPERATURE, event.timestamp,
|
||||
Float.toString(event.values[0])
|
||||
);
|
||||
}
|
||||
@@ -192,7 +193,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.RELATIVE_HUMIDITY,
|
||||
listener.onData(SensorType.RELATIVE_HUMIDITY, event.timestamp,
|
||||
Float.toString(event.values[0])
|
||||
);
|
||||
}
|
||||
@@ -205,14 +206,14 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
if (listener != null){
|
||||
|
||||
if(event.values.length > 3){
|
||||
listener.onData(SensorType.ROTATION_VECTOR,
|
||||
listener.onData(SensorType.ROTATION_VECTOR, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2]) + ";" +
|
||||
Float.toString(event.values[3])
|
||||
);
|
||||
} else {
|
||||
listener.onData(SensorType.ROTATION_VECTOR,
|
||||
listener.onData(SensorType.ROTATION_VECTOR, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -227,7 +228,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.GYROSCOPE,
|
||||
listener.onData(SensorType.GYROSCOPE, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -240,7 +241,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.PRESSURE,
|
||||
listener.onData(SensorType.PRESSURE, event.timestamp,
|
||||
Float.toString(event.values[0])
|
||||
);
|
||||
}
|
||||
@@ -251,10 +252,10 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.LINEAR_ACCELERATION,
|
||||
listener.onData(SensorType.LINEAR_ACCELERATION, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2]) + ";"
|
||||
Float.toString(event.values[2])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,7 +265,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.GRAVITY,
|
||||
listener.onData(SensorType.GRAVITY, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -277,7 +278,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.ACCELEROMETER,
|
||||
listener.onData(SensorType.ACCELEROMETER, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -297,7 +298,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
|
||||
// inform listeners
|
||||
if (listener != null){
|
||||
listener.onData(SensorType.MAGNETIC_FIELD,
|
||||
listener.onData(SensorType.MAGNETIC_FIELD, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
@@ -310,14 +311,25 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
// NOTE
|
||||
// @see TYPE_ACCELEROMETER
|
||||
// only MAG updates the current orientation as MAG is usually slower than ACC and this reduces the file-footprint
|
||||
updateOrientation();
|
||||
updateOrientation(event.timestamp);
|
||||
|
||||
}
|
||||
|
||||
else if(event.sensor.getType() == Sensor.TYPE_GAME_ROTATION_VECTOR) {
|
||||
// inform listeners
|
||||
if (listener != null) {
|
||||
listener.onData(SensorType.GAME_ROTATION_VECTOR, event.timestamp,
|
||||
Float.toString(event.values[0]) + ";" +
|
||||
Float.toString(event.values[1]) + ";" +
|
||||
Float.toString(event.values[2])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** calculate orientation from acc and mag */
|
||||
private void updateOrientation() {
|
||||
private void updateOrientation(long timestamp) {
|
||||
|
||||
// skip orientation update if either grav or geo is missing
|
||||
if (mGravity == null) {return;}
|
||||
@@ -339,7 +351,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
if (listener != null) {
|
||||
|
||||
// orientation vector
|
||||
listener.onData(SensorType.ORIENTATION_NEW,
|
||||
listener.onData(SensorType.ORIENTATION_NEW, timestamp,
|
||||
Float.toString(orientationNew[0]) + ";" +
|
||||
Float.toString(orientationNew[1]) + ";" +
|
||||
Float.toString(orientationNew[2])
|
||||
@@ -358,7 +370,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
sb.append(R[8]);
|
||||
|
||||
//Write the whole rotationMatrix R into the Listener.
|
||||
listener.onData(SensorType.ROTATION_MATRIX, sb.toString());
|
||||
listener.onData(SensorType.ROTATION_MATRIX, timestamp, sb.toString());
|
||||
|
||||
// Float.toString(R[0]) + ";" +
|
||||
// Float.toString(R[1]) + ";" +
|
||||
@@ -403,6 +415,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
|
||||
registerIfPresent(rotationVector, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
registerIfPresent(light, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
registerIfPresent(temperature, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
registerIfPresent(gameRotationVector, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ public enum SensorType {
|
||||
HEART_RATE(15),
|
||||
GPS(16),
|
||||
WIFIRTT(17),
|
||||
GAME_ROTATION_VECTOR(18),
|
||||
|
||||
PEDESTRIAN_ACTIVITY(50),
|
||||
GROUND_TRUTH(99),
|
||||
|
||||
@@ -23,6 +23,7 @@ public class WiFi extends mySensor {
|
||||
private final WifiManager wifi;
|
||||
private BroadcastReceiver receiver;
|
||||
private boolean isReceiverRegistered;
|
||||
private boolean isFirstMeasurement = true;
|
||||
|
||||
public WiFi(final Activity act) {
|
||||
|
||||
@@ -40,15 +41,29 @@ public class WiFi extends mySensor {
|
||||
this.receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
// ignore the first measurement
|
||||
if (isFirstMeasurement) {
|
||||
isFirstMeasurement = false;
|
||||
} else {
|
||||
final StringBuilder sb = new StringBuilder(1024);
|
||||
final List<ScanResult> res = wifi.getScanResults();
|
||||
long timestamp = 0;
|
||||
for (final ScanResult sr : res) {
|
||||
sb.append(Helper.stripMAC(sr.BSSID)).append(';');
|
||||
sb.append(sr.frequency).append(';');
|
||||
sb.append(sr.level).append(';');
|
||||
|
||||
// export with oldest timestamp among all contained measurements
|
||||
final long nanos = sr.timestamp * 1000;
|
||||
if (nanos > timestamp) {
|
||||
timestamp = nanos;
|
||||
}
|
||||
|
||||
}
|
||||
if (listener != null && isReceiverRegistered) {
|
||||
listener.onData(sb.toString());
|
||||
listener.onData(timestamp, sb.toString());
|
||||
}
|
||||
}
|
||||
startScan();
|
||||
//Log.d("wifi", sb.toString());
|
||||
|
||||
@@ -152,7 +152,7 @@ public class WiFiRTT extends mySensor {
|
||||
sb.append(numSuccessfulMeas);
|
||||
|
||||
|
||||
listener.onData(SensorType.WIFIRTT, sb.toString());
|
||||
listener.onData(SensorType.WIFIRTT,res.getRangingTimestampMillis()*1000, sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class iBeacon extends mySensor {
|
||||
private static final int REQUEST_ENABLE_BT = 1;
|
||||
private ScanCallback mLeScanCallback;
|
||||
|
||||
/** ctor */
|
||||
// ctor
|
||||
public iBeacon(final Activity act) {
|
||||
|
||||
// sanity check
|
||||
@@ -48,7 +48,7 @@ public class iBeacon extends mySensor {
|
||||
@Override public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
|
||||
//Log.d("BT", device + " " + rssi);
|
||||
if (listener != null) {
|
||||
listener.onData(Helper.stripMAC(result.getDevice().getAddress()) + ";" + result.getRssi() + ";" + result.getScanRecord().getTxPowerLevel());
|
||||
listener.onData(result.getTimestampNanos(), Helper.stripMAC(result.getDevice().getAddress()) + ";" + result.getRssi() + ";" + result.getScanRecord().getTxPowerLevel());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,19 +8,20 @@ import android.bluetooth.BluetoothManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.SystemClock;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Created by toni on 02/06/16.
|
||||
*/
|
||||
|
||||
/*
|
||||
public class iBeaconOld extends mySensor {
|
||||
|
||||
private BluetoothAdapter bt = null;
|
||||
private static final int REQUEST_ENABLE_BT = 1;
|
||||
private BluetoothAdapter.LeScanCallback mLeScanCallback;
|
||||
|
||||
/** ctor */
|
||||
// ctor
|
||||
public iBeaconOld(final Activity act) {
|
||||
|
||||
// sanity check
|
||||
@@ -45,7 +46,7 @@ public class iBeaconOld extends mySensor {
|
||||
@Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
|
||||
//Log.d("BT", device + " " + rssi);
|
||||
if (listener != null) {
|
||||
listener.onData(Helper.stripMAC(device.getAddress()) + ";" + rssi);
|
||||
listener.onData(SystemClock.elapsedRealtimeNanos(), Helper.stripMAC(device.getAddress()) + ";" + rssi);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -69,3 +70,4 @@ public class iBeaconOld extends mySensor {
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -12,10 +12,10 @@ public abstract class mySensor {
|
||||
/** listen for sensor events */
|
||||
public interface SensorListener {
|
||||
|
||||
public void onData(final String csv);
|
||||
public void onData(final long timestamp, final String csv);
|
||||
|
||||
/** received data from the given sensor */
|
||||
public void onData(final SensorType id, final String csv);
|
||||
public void onData(final SensorType id, final long timestamp, final String csv);
|
||||
|
||||
}
|
||||
|
||||
|
||||
9
app/src/main/res/drawable/ic_mess_around.xml
Normal file
9
app/src/main/res/drawable/ic_mess_around.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32zM8.41,14.96c-0.19,0 -0.37,-0.03 -0.52,-0.08 -0.16,-0.06 -0.29,-0.13 -0.4,-0.24 -0.11,-0.1 -0.2,-0.22 -0.26,-0.37 -0.06,-0.14 -0.09,-0.3 -0.09,-0.47h-1.3c0,0.36 0.07,0.68 0.21,0.95 0.14,0.27 0.33,0.5 0.56,0.69 0.24,0.18 0.51,0.32 0.82,0.41 0.3,0.1 0.62,0.15 0.96,0.15 0.37,0 0.72,-0.05 1.03,-0.15 0.32,-0.1 0.6,-0.25 0.83,-0.44s0.42,-0.43 0.55,-0.72c0.13,-0.29 0.2,-0.61 0.2,-0.97 0,-0.19 -0.02,-0.38 -0.07,-0.56 -0.05,-0.18 -0.12,-0.35 -0.23,-0.51 -0.1,-0.16 -0.24,-0.3 -0.4,-0.43 -0.17,-0.13 -0.37,-0.23 -0.61,-0.31 0.2,-0.09 0.37,-0.2 0.52,-0.33 0.15,-0.13 0.27,-0.27 0.37,-0.42 0.1,-0.15 0.17,-0.3 0.22,-0.46 0.05,-0.16 0.07,-0.32 0.07,-0.48 0,-0.36 -0.06,-0.68 -0.18,-0.96 -0.12,-0.28 -0.29,-0.51 -0.51,-0.69 -0.2,-0.19 -0.47,-0.33 -0.77,-0.43C9.1,8.05 8.76,8 8.39,8c-0.36,0 -0.69,0.05 -1,0.16 -0.3,0.11 -0.57,0.26 -0.79,0.45 -0.21,0.19 -0.38,0.41 -0.51,0.67 -0.12,0.26 -0.18,0.54 -0.18,0.85h1.3c0,-0.17 0.03,-0.32 0.09,-0.45s0.14,-0.25 0.25,-0.34c0.11,-0.09 0.23,-0.17 0.38,-0.22 0.15,-0.05 0.3,-0.08 0.48,-0.08 0.4,0 0.7,0.1 0.89,0.31 0.19,0.2 0.29,0.49 0.29,0.86 0,0.18 -0.03,0.34 -0.08,0.49 -0.05,0.15 -0.14,0.27 -0.25,0.37 -0.11,0.1 -0.25,0.18 -0.41,0.24 -0.16,0.06 -0.36,0.09 -0.58,0.09L7.5,11.4v1.03h0.77c0.22,0 0.42,0.02 0.6,0.07s0.33,0.13 0.45,0.23c0.12,0.11 0.22,0.24 0.29,0.4 0.07,0.16 0.1,0.35 0.1,0.57 0,0.41 -0.12,0.72 -0.35,0.93 -0.23,0.23 -0.55,0.33 -0.95,0.33zM16.96,9.04c-0.32,-0.33 -0.7,-0.59 -1.14,-0.77 -0.43,-0.18 -0.92,-0.27 -1.46,-0.27L12,8v8h2.3c0.55,0 1.06,-0.09 1.51,-0.27 0.45,-0.18 0.84,-0.43 1.16,-0.76 0.32,-0.33 0.57,-0.73 0.74,-1.19 0.17,-0.47 0.26,-0.99 0.26,-1.57v-0.4c0,-0.58 -0.09,-1.1 -0.26,-1.57 -0.18,-0.47 -0.43,-0.87 -0.75,-1.2zM16.57,12.2c0,0.42 -0.05,0.79 -0.14,1.13 -0.1,0.33 -0.24,0.62 -0.43,0.85 -0.19,0.23 -0.43,0.41 -0.71,0.53 -0.29,0.12 -0.62,0.18 -0.99,0.18h-0.91L13.39,9.12h0.97c0.72,0 1.27,0.23 1.64,0.69 0.38,0.46 0.57,1.12 0.57,1.99v0.4zM12,0l-0.66,0.03 3.81,3.81 1.33,-1.33c3.27,1.55 5.61,4.72 5.96,8.48h1.5C23.44,4.84 18.29,0 12,0z"/>
|
||||
</vector>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -63,7 +64,6 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtFile"
|
||||
android:layout_width="match_parent"
|
||||
@@ -117,189 +117,15 @@
|
||||
android:textColor="#ffffff" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutActivity1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_above="@+id/layoutGround"
|
||||
android:layout_marginEnd="10dip"
|
||||
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3">
|
||||
<TableLayout
|
||||
android:id="@+id/pedestrianActivityButtonContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnWalk"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_walk" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Laufen" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnStairsUp"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_stairs_up" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Treppe rauf" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnStairsDown"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_stairs_down" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Treppe runter" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutActivity2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_above="@+id/layoutGround"
|
||||
android:layout_marginEnd="10dip"
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnStanding"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_standing" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Stehen" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnElevatorUp"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_elevator_up" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Aufzug rauf" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnElevatorDown"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="10dip"
|
||||
android:layout_weight="1"
|
||||
android:background="#B2B2B2"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2"
|
||||
android:src="@drawable/ic_elevator_down" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Aufzug runter" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layoutGround"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
@@ -309,9 +135,17 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnGround"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#64bbe5"
|
||||
android:text="Ground Truth" />
|
||||
</RelativeLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSettings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#bbb"
|
||||
android:text="Settings" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
21
app/src/main/res/layout/activity_settings.xml
Normal file
21
app/src/main/res/layout/activity_settings.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SettingsActivity"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||
app:title="Settings" />
|
||||
|
||||
</LinearLayout>
|
||||
26
app/src/main/res/layout/pedestrian_activity_button.xml
Normal file
26
app/src/main/res/layout/pedestrian_activity_button.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:weightSum="3">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/activityButtonImage"
|
||||
android:layout_marginTop="10dip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/activityButtonText"
|
||||
android:layout_width="match_parent"
|
||||
android:textStyle="bold"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -2,4 +2,5 @@
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -5,4 +5,46 @@
|
||||
<string name="hello_world">Hello world!</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
<string name="prefActiveSensors">Active Sensors</string>
|
||||
<string name="prefActiveSensorsSummary">Choose the sensors included in the recording</string>
|
||||
<string-array name="prefActiveSensorsEntries">
|
||||
<item>GPS</item>
|
||||
<item>WiFi</item>
|
||||
<item>Bluetooth</item>
|
||||
<item>Phone (Accel, Gyro, Magnet)</item>
|
||||
</string-array>
|
||||
<string-array name="prefActiveSensorsValues">
|
||||
<item>GPS</item>
|
||||
<item>WIFI</item>
|
||||
<item>BLUETOOTH</item>
|
||||
<item>PHONE</item>
|
||||
</string-array>
|
||||
<string-array name="prefActiveSensorsDefault">
|
||||
<item>GPS</item>
|
||||
<item>WIFI</item>
|
||||
<item>BLUETOOTH</item>
|
||||
<item>PHONE</item>
|
||||
</string-array>
|
||||
|
||||
<string name="prefActiveActions">Active Pedestrian-Actions</string>
|
||||
<string name="prefActiveActionsSummary">Choose which Pedestrian-Actions should be available to choose from during recording.</string>
|
||||
<string-array name="prefActiveActionsEntries">
|
||||
<item>Walk</item>
|
||||
<item>Elevator Up/Down</item>
|
||||
<item>Stairs Up/Down</item>
|
||||
<item>Messing Around</item>
|
||||
</string-array>
|
||||
<string-array name="prefActiveActionsValues">
|
||||
<item>WALK</item>
|
||||
<item>ELEVATOR</item>
|
||||
<item>STAIRS</item>
|
||||
<item>MESS_AROUND</item>
|
||||
</string-array>
|
||||
<string-array name="prefActiveActionsDefault">
|
||||
<item>WALK</item>
|
||||
<item>ELEVATOR</item>
|
||||
<item>STAIRS</item>
|
||||
<item>MESS_AROUND</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -5,4 +5,13 @@
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
</resources>
|
||||
|
||||
19
app/src/main/res/xml/preferences.xml
Normal file
19
app/src/main/res/xml/preferences.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<MultiSelectListPreference
|
||||
android:entries="@array/prefActiveSensorsEntries"
|
||||
android:entryValues="@array/prefActiveSensorsValues"
|
||||
android:defaultValue="@array/prefActiveSensorsDefault"
|
||||
android:key="prefActiveSensors"
|
||||
android:summary="@string/prefActiveSensorsSummary"
|
||||
android:title="@string/prefActiveSensors" />
|
||||
<MultiSelectListPreference
|
||||
android:entries="@array/prefActiveActionsEntries"
|
||||
android:entryValues="@array/prefActiveActionsValues"
|
||||
android:defaultValue="@array/prefActiveActionsDefault"
|
||||
android:key="prefActiveActions"
|
||||
android:summary="@string/prefActiveActionsSummary"
|
||||
android:title="@string/prefActiveActions" />
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -8,9 +8,10 @@ buildscript {
|
||||
url 'https://maven.google.com/'
|
||||
name 'Google'
|
||||
}
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Mon Nov 13 09:30:52 CET 2017
|
||||
#Sun Aug 18 15:19:02 CEST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
|
||||
Reference in New Issue
Block a user