From 79e0acf7ede0fa1c5c90ee6b2428433526dc10e6 Mon Sep 17 00:00:00 2001 From: kazu Date: Mon, 6 Jun 2016 16:02:25 +0200 Subject: [PATCH] fixed several potential nullptrs code cleanups logging enhancements (memory/cpu) reduced log footprint (diskspace) fixed some potential layout issues added comments --- .idea/.name | 1 - .idea/encodings.xml | 6 - .idea/gradle.xml | 9 +- .idea/runConfigurations.xml | 12 - .idea/vcs.xml | 2 +- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 3 + .../indoor/sensorreadout/MainActivity.java | 69 ++-- .../sensorreadout/sensors/DataFolder.java | 15 +- .../sensorreadout/sensors/GroundTruth.java | 11 +- .../indoor/sensorreadout/sensors/Helper.java | 17 + .../indoor/sensorreadout/sensors/Limiter.java | 46 +-- .../indoor/sensorreadout/sensors/Logger.java | 73 ++-- .../sensorreadout/sensors/MyException.java | 24 ++ .../sensorreadout/sensors/PhoneSensors.java | 389 +++++++++--------- .../sensorreadout/sensors/SensorType.java | 47 ++- .../indoor/sensorreadout/sensors/WiFi.java | 16 +- .../indoor/sensorreadout/sensors/iBeacon.java | 31 +- .../sensorreadout/sensors/iBeaconOld.java | 9 +- .../sensorreadout/sensors/mySensor.java | 14 +- app/src/main/res/layout/activity_main.xml | 55 ++- build.gradle | 2 +- 22 files changed, 456 insertions(+), 401 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/runConfigurations.xml create mode 100644 app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Helper.java create mode 100644 app/src/main/java/de/fhws/indoor/sensorreadout/sensors/MyException.java diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 9a50ac8..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SensorReadout \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 2ab1e27..440c1d7 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -5,20 +5,13 @@ - diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 8cff616..27ac1f0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "23.0.2" + buildToolsVersion '23.0.3' defaultConfig { applicationId "de.fhws.indoor.sensorreadout" @@ -20,10 +20,10 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.google.android.support:wearable:1.3.0' - compile 'com.google.android.gms:play-services-wearable:8.4.0' + //compile 'com.google.android.gms:play-services-wearable:8.4.0' //provided 'com.google.android.wearable:wearable:1.0.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a01c63..6eabe13 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,10 @@ > + + diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java index 71cf86c..e1f987f 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java @@ -1,15 +1,14 @@ package de.fhws.indoor.sensorreadout; import android.Manifest; +import android.app.Activity; +import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.media.MediaPlayer; import android.os.Build; import android.os.Bundle; -import android.provider.Settings; import android.support.v4.app.ActivityCompat; -import android.support.v7.app.AppCompatActivity; -import android.support.wearable.activity.WearableActivity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; @@ -32,7 +31,7 @@ import de.fhws.indoor.sensorreadout.sensors.mySensor; import de.fhws.indoor.sensorreadout.sensors.SensorType; -public class MainActivity extends WearableActivity { +public class MainActivity extends Activity { private final ArrayList sensors = new ArrayList(); private final ArrayList txtFields = new ArrayList(); @@ -41,17 +40,21 @@ public class MainActivity extends WearableActivity { private Button btnStop; private Button btnGround; private int groundTruthCounter = 0; - private int loadCounterWifi = 0; - private int loadCounterBeacon = 0; private boolean isInitialized = false; final private int MY_PERMISSIONS_REQUEST_READ_BT = 123; final private int MY_PERMISSIONS_REQUEST_READ_HEART = 321; + // static context access + private static Context context; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + // context access + MainActivity.context = getApplicationContext(); + //init Path spinner final Spinner pathSpinner = (Spinner) findViewById(R.id.pathspinner); List pathList = new ArrayList(); @@ -90,7 +93,7 @@ public class MainActivity extends WearableActivity { sensors.add(grndTruth); grndTruth.setListener(new mySensor.SensorListener() { @Override public void onData(final String csv) { return; } - @Override public void onData(int id, final String csv) {add(id, csv); } + @Override public void onData(SensorType id, final String csv) {add(id, csv); } }); @@ -167,15 +170,15 @@ public class MainActivity extends WearableActivity { sensors.add(phoneSensors); phoneSensors.setListener(new mySensor.SensorListener(){ @Override public void onData(final String csv) { return; } - @Override public void onData(int id, final String csv) {add(id, csv); } + @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.ordinal(), csv); } - @Override public void onData(int id, final String csv) {return; } + @Override public void onData(final String csv) { add(SensorType.WIFI, csv); } + @Override public void onData(final SensorType id, final String csv) {return; } }); // log iBeacons using sensor number 9 @@ -188,8 +191,8 @@ public class MainActivity extends WearableActivity { sensors.add(beacon); beacon.setListener(new mySensor.SensorListener() { - @Override public void onData(final String csv) { add(SensorType.IBEACON.ordinal(), csv); } - @Override public void onData(int id, final String csv) {return; } + @Override public void onData(final String csv) { add(SensorType.IBEACON, csv); } + @Override public void onData(final SensorType id, final String csv) {return; } }); final LinearLayout lay = (LinearLayout) findViewById(R.id.layoutMain); @@ -197,7 +200,8 @@ public class MainActivity extends WearableActivity { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); params.setMargins(10,10,10,10); - for (int i = 0; i < sensors.size(); ++i) { + // fixed number of textfields + for (int i = 0; i < 16; ++i) { final TextView tv = new TextView(this); //Set margin and color @@ -239,39 +243,33 @@ public class MainActivity extends WearableActivity { private void stop() { logger.stop(); - for(int i = 0; i < txtFields.size(); i++) - { + for(int i = 0; i < txtFields.size(); i++) { txtFields.get(i).setText(""); } for (final mySensor s : sensors) {s.onPause(this);} } /** new sensor data */ - private void add(final int nr, final String csv) { - logger.addCSV(nr, csv); + private int loadCounterWifi = 0; + private int loadCounterBeacon = 0; + private int loadCounterAny = 0; + private void add(final SensorType id, final String csv) { + + logger.addCSV(id, csv); runOnUiThread(new Runnable() { @Override public void run() { - if (nr == 8) { - if (loadCounterWifi % 2 == 0) { - txtFields.get(0).setText("wifi"); - ++loadCounterWifi; - } else { - txtFields.get(0).setText("WIFI"); - ++loadCounterWifi; - } + if (id == SensorType.WIFI) { + txtFields.get(0).setText( ((++loadCounterWifi % 2) == 0) ? "wi" : "WI"); + } else if (id == SensorType.IBEACON){ + txtFields.get(1).setText( ((++loadCounterBeacon % 2) == 0) ? "ib" : "IB"); } - if (nr == 9){ - if(loadCounterBeacon % 2 == 0){ - txtFields.get(1).setText("beacon"); - ++loadCounterBeacon; - } else { - txtFields.get(1).setText("BEACON"); - ++loadCounterBeacon; - } + if (++loadCounterAny % 10 == 0) { + txtFields.get(2).setText( (logger.getSize() / 1024) + " kb - " + logger.getNumEntries()); } + } }); @@ -300,4 +298,9 @@ public class MainActivity extends WearableActivity { } } + /** static context access */ + public static Context getAppContext() { + return MainActivity.context; + } + } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java index d1e5a83..90047d6 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java @@ -26,15 +26,22 @@ public class DataFolder { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { folder = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), folderName); - } else { + } else if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { folder = new File(Environment.getExternalStorageDirectory() + "/" + folderName); + } else { + folder = new File(context.getApplicationInfo().dataDir); } + // build folders folder.mkdirs(); - boolean isExtistingFolder = folder.exists(); - boolean isDirectory = folder.isDirectory(); - Log.d("DataFolder", String.valueOf(isExtistingFolder)); + // sanity check: + if (!folder.exists() || !folder.isDirectory()) { + throw new MyException("failed to create/access storage folder: " + folder.getAbsolutePath()); + } else { + Log.d("dataFolder", "using: " + folder); + } + } public File getFolder(){ diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java index b44c7f7..e1e7143 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java @@ -11,18 +11,17 @@ public class GroundTruth extends mySensor { //empty as my soul } - public void writeGroundTruth(int groundTruthCounter){ - - if (listener != null){listener.onData(99, - Integer.toString(groundTruthCounter) + ";" + public void writeGroundTruth(final int groundTruthCounter){ + if (listener != null){listener.onData(SensorType.GROUND_TRUTH, + Integer.toString(groundTruthCounter) );} } public void writeInitData(int pathID, int numGroundTruthPoints){ - if (listener != null){listener.onData(-1, + if (listener != null){listener.onData(SensorType.GROUND_TRUTH_PATH, Integer.toString(pathID) + ";" + - Integer.toString(numGroundTruthPoints) + ";" + Integer.toString(numGroundTruthPoints) );} } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Helper.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Helper.java new file mode 100644 index 0000000..89d816f --- /dev/null +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Helper.java @@ -0,0 +1,17 @@ +package de.fhws.indoor.sensorreadout.sensors; + +/** + * Created by Frank on 05.06.2016. + */ + +public class Helper { + + /** remove all ":" within the MAC to reduce file footprint */ + public static final String stripMAC(final String mac) { + return mac.replaceAll(":", ""); + } + +} + + + diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Limiter.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Limiter.java index e4beae5..3d4184a 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Limiter.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Limiter.java @@ -1,25 +1,25 @@ package de.fhws.indoor.sensorreadout.sensors; -/** - * Created by Frank on 04.02.2016. - */ -public class Limiter { - - long last_ms = 0; - final int limit_ms; - - /** ctor */ - Limiter(final int limit_ms) { - this.limit_ms = limit_ms; - } - - /** limit reached? */ - boolean isOK() { - final long cur_ms = System.currentTimeMillis(); - final long diff = cur_ms - last_ms; - final boolean ok = diff > limit_ms; - if (ok) {last_ms = cur_ms;} - return ok; - } - -} +///** +// * Created by Frank on 04.02.2016. +// */ +//public class Limiter { +// +// long last_ms = 0; +// final int limit_ms; +// +// /** ctor */ +// Limiter(final int limit_ms) { +// this.limit_ms = limit_ms; +// } +// +// /** limit reached? */ +// boolean isOK() { +// final long cur_ms = System.currentTimeMillis(); +// final long diff = cur_ms - last_ms; +// final boolean ok = diff > limit_ms; +// if (ok) {last_ms = cur_ms;} +// return ok; +// } +// +//} diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java index 5d66281..3fb957c 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java @@ -13,44 +13,47 @@ import java.io.OutputStreamWriter; * log sensor data to file * Created by Frank on 25.03.2015. */ -public class Logger { +public final class Logger { - //private BufferedWriter bw; - private ByteArrayOutputStream baos; - private OutputStreamWriter osw; + private StringBuilder sb = new StringBuilder(); private File file; + private FileOutputStream fos; private Context context; + private int entries = 0; public Logger(Context context) { this.context = context; } /** start logging (into RAM) */ - public void start() { + public final void start() { + // start empty + sb.setLength(0); + entries = 0; + + // open the output-file immeditaly (to get permission errors) + // but do NOT yet write anything to the file DataFolder folder = new DataFolder(context, "sensorOutFiles"); - file = new File(folder.getFolder(), System.currentTimeMillis() + ".csv"); - Log.d("logger", file.toString()); - baos = new ByteArrayOutputStream(); - osw = new OutputStreamWriter(baos); + Log.d("logger", "will write to: " + file.toString()); + + try { + fos = new FileOutputStream(file); + } catch (final Exception e) { + throw new MyException("error while opening log-file", e); + } + } /** stop logging and flush RAM-data to the flash-chip */ - public void stop() { + public final void stop() { synchronized (this) { try { - try { - // finally write the ram data to disk - osw.close(); - final FileOutputStream fos = new FileOutputStream(file); - fos.write(baos.toByteArray()); - fos.close(); - } catch (final Exception e) { - throw new RuntimeException(e); - } + fos.write(sb.toString().getBytes()); + fos.close(); } catch (final Exception e) { - throw new RuntimeException(e); + throw new MyException("error while writing log-file", e); } } } @@ -59,23 +62,29 @@ public class Logger { return file; } + public int getSize() {return sb.length();} + public int getNumEntries() {return entries;} - /** add a new CSV entry for the given sensor number */ - public void addCSV(final int sensorNr, final String csv) { - - final String s = System.currentTimeMillis() + ";" + sensorNr + ";" + csv; - - // log to RAM + /** 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) { - try { - osw.write(s); - osw.write("\r\n"); - } catch (final Exception e) { - throw new RuntimeException(e); - } + sb.append(System.currentTimeMillis()); + sb.append(';'); + sb.append(sensorNr.id()); + sb.append(';'); + sb.append(csv); + sb.append("\n"); + ++entries; } + debug(); + } + int cnt = 0; + private final void debug() { + if (++cnt % 10 == 0) { + Log.d("buffer", "size: " + sb.length()); + } } } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/MyException.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/MyException.java new file mode 100644 index 0000000..9f4f9c8 --- /dev/null +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/MyException.java @@ -0,0 +1,24 @@ +package de.fhws.indoor.sensorreadout.sensors; + +import android.widget.Toast; + +import de.fhws.indoor.sensorreadout.MainActivity; +import de.fhws.indoor.sensorreadout.R; + +/** + * Created by Frank on 05.06.2016. + */ + +public class MyException extends RuntimeException { + + MyException(final String err, final Throwable t) { + super(err, t); + Toast.makeText(MainActivity.getAppContext(), err, Toast.LENGTH_LONG); + } + + MyException(final String err) { + super(err); + Toast.makeText(MainActivity.getAppContext(), err, Toast.LENGTH_LONG); + } + +} diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java index 2a295a8..266efbc 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java @@ -7,20 +7,25 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Build; - -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.wearable.Wearable; +import android.util.Log; import java.io.BufferedWriter; import java.io.File; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; /** + * all available sensors + * and what to do within one class + * + * * Created by Toni on 25.03.2015. */ public class PhoneSensors extends mySensor implements SensorEventListener{ + private static final int SENSOR_TYPE_HEARTRATE = 65562; + private SensorManager sensorManager; private Sensor acc; private Sensor grav; @@ -35,20 +40,19 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ private Sensor light; private Sensor temperature; - private static final int SENSOR_TYPE_HEARTRATE = 65562; - + /** local gravity copy (needed for orientation matrix) */ private float[] mGravity = new float[3]; + /** local geomagnetic copy (needed for orientation matrix) */ private float[] mGeomagnetic = new float[3]; - //Limiter limitGyro = new Limiter(10); - //Limiter limitMag = new Limiter(10); - //Limiter limitAcc = new Limiter(10); - Limiter limitAOri = new Limiter(10); + /** ctor */ public PhoneSensors(final Activity act){ + // fetch the sensor manager from the activity sensorManager = (SensorManager) act.getSystemService(Context.SENSOR_SERVICE); + // try to get each sensor acc = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); grav = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); lin_acc = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); @@ -62,265 +66,237 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ light = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); temperature = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE); - //Write Vendor to file + // dump sensor-vendor info to file + dumpVendors(act); - DataFolder folder = new DataFolder(act, "sensorOutFiles"); - File file = new File(folder.getFolder(), "vendors.txt"); + } + + final char NL = '\n'; + + /** Write Vendors to file */ + private void dumpVendors(final Activity act) { + + final DataFolder folder = new DataFolder(act, "sensorOutFiles"); + final File file = new File(folder.getFolder(), "vendors.txt"); try { - FileWriter fw = new FileWriter(file.getAbsoluteFile()); - BufferedWriter bw = new BufferedWriter(fw); - //write sensor vendor information - bw.write("Device: " + android.os.Build.MODEL); - bw.newLine(); - bw.write("Android: " + Build.VERSION.RELEASE); - bw.newLine(); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.ACCELEROMETER.ordinal()) + " Accelerometer: " + getSensorName(acc)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.GRAVITY.ordinal()) + " Gravity: " + getSensorName(grav)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.LINEAR_ACCELERATION.ordinal()) + " Linear Acceleration: " + getSensorName(lin_acc)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.GYROSCOPE.ordinal()) + " Gyroscope: " + getSensorName(gyro)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.MAGNETIC_FIELD.ordinal()) + " Magnetic Field: " + getSensorName(magnet)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.PRESSURE.ordinal()) + " Pressure: " + getSensorName(press)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.RELATIVE_HUMIDITY.ordinal()) + " Humidity: " + getSensorName(humidity)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.ORIENTATION_OLD.ordinal()) + " Orientation Old: " + getSensorName(ori)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.LIGHT.ordinal()) + " Light: " + getSensorName(light)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.AMBIENT_TEMPERATURE.ordinal()) + " Temperature: " + getSensorName(temperature)); - bw.newLine(); - bw.write("id" + String.valueOf(SensorType.HEART_RATE.ordinal()) + " Heart Rate: " + getSensorName(heart)); - bw.newLine(); + final FileOutputStream fos = new FileOutputStream(file); + final StringBuilder sb = new StringBuilder(); - bw.close(); - fw.close(); + // constructor smartphone details + sb.append("Device: " + android.os.Build.MODEL).append(NL); + sb.append("Android: " + Build.VERSION.RELEASE).append(NL); - }catch (IOException e) { - e.printStackTrace(); + // construct sensor details + dumpSensor(sb, SensorType.ACCELEROMETER, acc); + dumpSensor(sb, SensorType.GRAVITY, grav); + dumpSensor(sb, SensorType.LINEAR_ACCELERATION, lin_acc); + dumpSensor(sb, SensorType.GYROSCOPE, gyro); + dumpSensor(sb, SensorType.MAGNETIC_FIELD, magnet); + dumpSensor(sb, SensorType.PRESSURE, press); + dumpSensor(sb, SensorType.RELATIVE_HUMIDITY, humidity); + dumpSensor(sb, SensorType.ORIENTATION_OLD, ori); + dumpSensor(sb, SensorType.LIGHT, light); + dumpSensor(sb, SensorType.AMBIENT_TEMPERATURE, temperature); + dumpSensor(sb, SensorType.HEART_RATE, heart); + + // write + fos.write(sb.toString().getBytes()); + fos.close(); + + }catch (final IOException e) { + throw new RuntimeException(e); } + } - private String getSensorName(Sensor sensor){ - - if(sensor != null){ - - StringBuilder message = new StringBuilder(2048); - message.append("\nVendor: " + sensor.getVendor() + "\n"); - message.append("Version: " + sensor.getVersion() + "\n"); - message.append("MinDelay: " + sensor.getMinDelay() + "\n"); - //message.append("MaxDelay: " + sensor.getMaxDelay() + "\n"); - message.append("MaxRange: " + sensor.getMaximumRange() + "\n"); - message.append("Power: " + sensor.getPower() + "\n"); - //message.append("ReportingMode: " + sensor.getReportingMode() + "\n"); - message.append("Resolution: " + sensor.getResolution() + "\n"); - message.append("Type: " + sensor.getType() + "\n\n"); - //message.append("FifoMaxEventCount: " + sensor.getFifoMaxEventCount() + "\n"); - //message.append("FifoReservedEventCount: " + sensor.getFifoReservedEventCount() + "\n"); - - return message.toString(); - } else{ - return "\nSensor not in device\n"; + /** dump all details of the given sensor into the provided stringbuilder */ + private void dumpSensor(final StringBuilder sb, final SensorType type, final Sensor sensor) { + sb.append("Sensor").append(NL); + sb.append("id: ").append(type.ordinal()).append(NL); + sb.append("type: ").append(type).append(NL); + if (sensor != null) { + sb.append("\tVendor: ").append(sensor.getVendor()).append(NL); + sb.append("\tVersion: ").append(sensor.getVersion()).append(NL); + sb.append("\tMinDelay: ").append(sensor.getMinDelay()).append(NL); + //sb.append("\tMaxDelay: ").append(sensor.getMaxDelay()).append(NL); + sb.append("\tMaxRange: ").append(sensor.getMaximumRange()).append(NL); + sb.append("\tPower: ").append(sensor.getPower()).append(NL); + //sb.append("ReportingMode: ").append(sensor.getReportingMode()).append(NL); + sb.append("\tResolution: ").append(sensor.getResolution()).append(NL); + sb.append("\tType: ").append(sensor.getType()).append(NL); + } else { + sb.append("\tnot available!\n"); } + sb.append("\n"); } - @Override public void onSensorChanged(SensorEvent event) { // to compare with the other orientation if(event.sensor.getType() == Sensor.TYPE_ORIENTATION) { - if (listener != null){ - listener.onData(SensorType.ORIENTATION_OLD.ordinal(), + // inform listeners + if (listener != null){ + listener.onData(SensorType.ORIENTATION_OLD, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + - Float.toString(event.values[2]) + ";" + Float.toString(event.values[2]) ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_HEART_RATE) { + else if(event.sensor.getType() == Sensor.TYPE_HEART_RATE) { + // inform listeners if (listener != null){ - listener.onData(SensorType.HEART_RATE.ordinal(), - Float.toString(event.values[0]) + ";" + listener.onData(SensorType.HEART_RATE, + Float.toString(event.values[0]) ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_LIGHT) { + else if(event.sensor.getType() == Sensor.TYPE_LIGHT) { + // inform listeners if (listener != null){ - listener.onData(SensorType.LIGHT.ordinal(), - Float.toString(event.values[0]) + ";" + listener.onData(SensorType.LIGHT, + Float.toString(event.values[0]) ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) { + else if(event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) { + // inform listeners if (listener != null){ - listener.onData(SensorType.AMBIENT_TEMPERATURE.ordinal(), - Float.toString(event.values[0]) + ";" + listener.onData(SensorType.AMBIENT_TEMPERATURE, + Float.toString(event.values[0]) ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_RELATIVE_HUMIDITY) { + else if(event.sensor.getType() == Sensor.TYPE_RELATIVE_HUMIDITY) { + // inform listeners if (listener != null){ - listener.onData(SensorType.RELATIVE_HUMIDITY.ordinal(), - Float.toString(event.values[0]) + ";" + listener.onData(SensorType.RELATIVE_HUMIDITY, + Float.toString(event.values[0]) ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { + else if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { + // inform listeners if (listener != null){ if(event.values.length > 3){ - listener.onData(SensorType.ROTATION_VECTOR.ordinal(), + listener.onData(SensorType.ROTATION_VECTOR, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + Float.toString(event.values[2]) + ";" + - Float.toString(event.values[3]) + ";" + Float.toString(event.values[3]) ); } else { - listener.onData(SensorType.ROTATION_VECTOR.ordinal(), + listener.onData(SensorType.ROTATION_VECTOR, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + - Float.toString(event.values[2]) + ";" + Float.toString(event.values[2]) ); } - } - return; - } - if(event.sensor.getType() == Sensor.TYPE_GYROSCOPE) { - - // skip? - //if (!limitGyro.isOK()) {return;} + else if(event.sensor.getType() == Sensor.TYPE_GYROSCOPE) { + // inform listeners if (listener != null){ - listener.onData(SensorType.GYROSCOPE.ordinal(), + listener.onData(SensorType.GYROSCOPE, + Float.toString(event.values[0]) + ";" + + Float.toString(event.values[1]) + ";" + + Float.toString(event.values[2]) + ); + } + + } + + else if(event.sensor.getType() == Sensor.TYPE_PRESSURE) { + + // inform listeners + if (listener != null){ + listener.onData(SensorType.PRESSURE, + Float.toString(event.values[0]) + ); + } + + } + + else if(event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) { + + // inform listeners + if (listener != null){ + listener.onData(SensorType.LINEAR_ACCELERATION, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + Float.toString(event.values[2]) + ";" ); } - return; - } - if(event.sensor.getType() == Sensor.TYPE_PRESSURE) { - - if (listener != null){ - listener.onData(SensorType.PRESSURE.ordinal(), - Float.toString(event.values[0]) + ";" - ); - } - - return; - - } - - if(event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) { - - if (listener != null){ - listener.onData(SensorType.LINEAR_ACCELERATION.ordinal(), - Float.toString(event.values[0]) + ";" + - Float.toString(event.values[1]) + ";" + - Float.toString(event.values[2]) + ";" - ); - } - - return; - - } - - - - if(event.sensor.getType() == Sensor.TYPE_GRAVITY) { - - float gravity_X = event.values[0]; - float gravity_Y = event.values[1]; - float gravity_Z = event.values[2]; + else if(event.sensor.getType() == Sensor.TYPE_GRAVITY) { + // inform listeners if (listener != null){ - listener.onData(SensorType.GRAVITY.ordinal(), - Float.toString(gravity_X) + ";" + - Float.toString(gravity_Y) + ";" + - Float.toString(gravity_Z) + ";" + listener.onData(SensorType.GRAVITY, + Float.toString(event.values[0]) + ";" + + Float.toString(event.values[1]) + ";" + + Float.toString(event.values[2]) ); } } + else if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { - - if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { - - // skip? - //if (!limitAcc.isOK()) {return;} - - System.arraycopy(event.values, 0, mGravity, 0, 3); - + // inform listeners if (listener != null){ - listener.onData(SensorType.ACCELEROMETER.ordinal(), + listener.onData(SensorType.ACCELEROMETER, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + - Float.toString(event.values[2]) + ";" + Float.toString(event.values[2]) ); } + // keep a local copy (needed for orientation matrix) + System.arraycopy(event.values, 0, mGravity, 0, 3); updateOrientation(); } - if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { - - // skip? - //if (!limitMag.isOK()) {return;} - - System.arraycopy(event.values, 0, mGeomagnetic, 0, 3); + else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { + // inform listeners if (listener != null){ - listener.onData(SensorType.MAGNETIC_FIELD.ordinal(), + listener.onData(SensorType.MAGNETIC_FIELD, Float.toString(event.values[0]) + ";" + Float.toString(event.values[1]) + ";" + - Float.toString(event.values[2]) + ";" + Float.toString(event.values[2]) ); } + // keep a local copy (needed for orientation matrix) + System.arraycopy(event.values, 0, mGeomagnetic, 0, 3); updateOrientation(); } @@ -330,34 +306,33 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ /** calculate orientation from acc and mag */ private void updateOrientation() { - // skip? - if (!limitAOri.isOK()) {return;} - + // skip orientation update if either grav or geo is missing if (mGravity == null) {return;} if (mGeomagnetic == null) {return;} - //rotationMatrix and orientation - + // calculate rotationMatrix and orientation float R[] = new float[16]; float I[] = new float[16]; + // derive rotation matrix from grav and geo sensors boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic); if (!success) {return;} - + // derive orientation-vector using the rotation matrix float orientation[] = new float[3]; SensorManager.getOrientation(R, orientation); - if (listener != null){ + // inform listeners + if (listener != null) { - listener.onData(SensorType.ORIENTATION_NEW.ordinal(), + listener.onData(SensorType.ORIENTATION_NEW, Float.toString(orientation[0]) + ";" + Float.toString(orientation[1]) + ";" + - Float.toString(orientation[2]) + ";" + Float.toString(orientation[2]) ); //Write the whole rotationMatrix R into the Listener. - listener.onData(SensorType.ROTATION_MATRIX.ordinal(), + listener.onData(SensorType.ROTATION_MATRIX, Float.toString(R[0]) + ";" + Float.toString(R[1]) + ";" + Float.toString(R[2]) + ";" + @@ -366,53 +341,59 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ Float.toString(R[5]) + ";" + Float.toString(R[6]) + ";" + Float.toString(R[7]) + ";" + - Float.toString(R[8]) + ";" + - Float.toString(R[9]) + ";" + - Float.toString(R[10]) + ";" + - Float.toString(R[11]) + ";" + - Float.toString(R[12]) + ";" + - Float.toString(R[13]) + ";" + - Float.toString(R[14]) + ";" + - Float.toString(R[15]) + ";" + Float.toString(R[8]) +// Float.toString(R[9]) + ";" + +// Float.toString(R[10]) + ";" + +// Float.toString(R[11]) + ";" + +// Float.toString(R[12]) + ";" + +// Float.toString(R[13]) + ";" + +// Float.toString(R[14]) + ";" + +// Float.toString(R[15]) ); + } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { + // nothing to-do here + } + + @Override + public void onResume(final Activity act) { + + // attach as listener to each of the available sensors + registerIfPresent(acc, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(grav, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(gyro, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(lin_acc, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(magnet, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(press, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(ori, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(heart, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(humidity, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(rotationVector, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(light, SensorManager.SENSOR_DELAY_FASTEST); + registerIfPresent(temperature, SensorManager.SENSOR_DELAY_FASTEST); } - private void applyLowPassFilter(float[] input, float[] output) { - float alpha = 0.90f; - for (int i = 0; i < input.length; ++i) { - //output[i] = (output[i] * (alpha)) + (input[i] * (1-alpha)); - output[i] = input[i]; // disabled + private void registerIfPresent(final Sensor sens, final int delay) { + if (sens != null) { + sensorManager.registerListener(this, sens, delay); + Log.d("PhoneSensors", "added sensor " + sens.toString()); + } else { + Log.d("PhoneSensors", "sensor not present. skipping"); } } @Override - public void onResume(Activity act) { - // Register a listener for the sensor. - sensorManager.registerListener(this, acc, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, grav, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, gyro, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, lin_acc, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, magnet, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, press, SensorManager.SENSOR_DELAY_FASTEST); // speed OK - sensorManager.registerListener(this, ori, SensorManager.SENSOR_DELAY_FASTEST); // speed OK + public void onPause(final Activity act) { + + // detach from all events + sensorManager.unregisterListener(this); - sensorManager.unregisterListener(this, heart); - sensorManager.registerListener(this, heart, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, humidity, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, rotationVector, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_FASTEST); - sensorManager.registerListener(this, temperature, SensorManager.SENSOR_DELAY_FASTEST); } - @Override - public void onPause(Activity act) { - sensorManager.unregisterListener(this); - } } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java index d7b273b..114d641 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java @@ -4,20 +4,35 @@ package de.fhws.indoor.sensorreadout.sensors; * Created by toni on 02/06/16. */ public enum SensorType { - ACCELEROMETER, // 0 - GRAVITY, // 1 - LINEAR_ACCELERATION, // 2 - GYROSCOPE, // 3 - MAGNETIC_FIELD, // 4 - PRESSURE, // 5 - ORIENTATION_NEW, // 6 - ROTATION_MATRIX, // 7 - WIFI, // 8 - IBEACON, // 9 - RELATIVE_HUMIDITY, // 10 - ORIENTATION_OLD, // 11 - ROTATION_VECTOR, // 12 - LIGHT, // 13 - AMBIENT_TEMPERATURE, // 14 - HEART_RATE // 15 + + ACCELEROMETER(0), + GRAVITY(1), + LINEAR_ACCELERATION(2), + GYROSCOPE(3), + MAGNETIC_FIELD(4), + PRESSURE(5), + ORIENTATION_NEW(6), + ROTATION_MATRIX(7), + WIFI(8), + IBEACON(9), + RELATIVE_HUMIDITY(10), + ORIENTATION_OLD(11), + ROTATION_VECTOR(12), + LIGHT(13), + AMBIENT_TEMPERATURE(14), + HEART_RATE(15), + + GROUND_TRUTH(99), + GROUND_TRUTH_PATH(-1), + + ; + + private int id; + + SensorType(final int id) { + this.id = id; + } + + public final int id() {return id;} + } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java index a576ec2..2269dd0 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java @@ -33,9 +33,9 @@ public class WiFi extends mySensor { final StringBuilder sb = new StringBuilder(); final List res = wifi.getScanResults(); for(final ScanResult sr : res) { - sb.append(sr.BSSID).append(";"); + sb.append(Helper.stripMAC(sr.BSSID)).append(";"); sb.append(sr.frequency).append(";"); - sb.append(sr.level).append(";"); + sb.append(sr.level); } startScan(); if (listener != null && isReceiverRegistered) {listener.onData(sb.toString());} @@ -45,14 +45,18 @@ public class WiFi extends mySensor { } + + + /** exception-safe scanning start */ private void startScan() { try { //Method startScanActiveMethod = wifi.getClass().getMethod("startScanActive"); //startScanActiveMethod.invoke(wifi); wifi.startScan(); - Log.e("start", "wifi"); + Log.d("wifi", "start scan"); }catch (final Exception e) { - throw new RuntimeException(e);} + throw new RuntimeException(e); + } } @Override @@ -69,8 +73,8 @@ public class WiFi extends mySensor { if (isReceiverRegistered) { try { act.unregisterReceiver(this.receiver); - } catch (Exception e) { - // Do nothing + } catch (final Exception e) { + e.printStackTrace(); } isReceiverRegistered = false; } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java index e4a7797..7ab7d55 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java @@ -15,8 +15,8 @@ import android.widget.Toast; */ public class iBeacon extends mySensor { - private final BluetoothAdapter bt; - private final BluetoothLeScanner scanner; + private BluetoothAdapter bt = null; + private BluetoothLeScanner scanner = null; private static final int REQUEST_ENABLE_BT = 1; private ScanCallback mLeScanCallback; @@ -26,6 +26,7 @@ public class iBeacon extends mySensor { // sanity check if (!act.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(act, "Bluetooth-LE not supported!", Toast.LENGTH_SHORT).show(); + return; } // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to @@ -36,33 +37,41 @@ public class iBeacon extends mySensor { // bluetooth supported? if (bt == null) { Toast.makeText(act, "Bluetooth not supported!", Toast.LENGTH_SHORT).show(); + return; } + // create the scanner scanner = bt.getBluetoothLeScanner(); + // and attach the callback mLeScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) { //Log.d("BT", device + " " + rssi); - if (listener != null) {listener.onData(result.getDevice().getAddress() + ";" + result.getRssi());} + if (listener != null) { + listener.onData(Helper.stripMAC(result.getDevice().getAddress()) + ";" + result.getRssi() + ";" + result.getScanRecord().getTxPowerLevel()); + } } }; } - void enableBT(final Activity act) { - if (!bt.isEnabled()) { - Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - act.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); - } + private final void enableBT(final Activity act) { + if (bt == null) {throw new RuntimeException("BT not supported!");} + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + act.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } @Override public void onResume(final Activity act) { - enableBT(act); - scanner.startScan(mLeScanCallback); + if (bt != null) { + enableBT(act); + scanner.startScan(mLeScanCallback); + } } @Override public void onPause(final Activity act) { - scanner.stopScan(mLeScanCallback); + if (bt != null) { + scanner.stopScan(mLeScanCallback); + } } } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java index 40a002a..725c9fd 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java @@ -16,7 +16,7 @@ import android.widget.Toast; public class iBeaconOld extends mySensor { - private final BluetoothAdapter bt; + private BluetoothAdapter bt = null; private static final int REQUEST_ENABLE_BT = 1; private BluetoothAdapter.LeScanCallback mLeScanCallback; @@ -26,6 +26,7 @@ public class iBeaconOld extends mySensor { // sanity check if (!act.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(act, "Bluetooth-LE not supported!", Toast.LENGTH_SHORT).show(); + return; } // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to @@ -36,12 +37,16 @@ public class iBeaconOld extends mySensor { // bluetooth supported? if (bt == null) { Toast.makeText(act, "Bluetooth not supported!", Toast.LENGTH_SHORT).show(); + return; } + // attach scan callback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { //Log.d("BT", device + " " + rssi); - if (listener != null) {listener.onData(device + ";" + rssi);} + if (listener != null) { + listener.onData(Helper.stripMAC(device.getAddress()) + ";" + rssi); + } } }; diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java index 2d9e090..f3c8381 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java @@ -3,21 +3,33 @@ package de.fhws.indoor.sensorreadout.sensors; import android.app.Activity; /** + * base-class for all Sensors + * * Created by Frank on 25.03.2015. */ public abstract class mySensor { + /** listen for sensor events */ public interface SensorListener { + public void onData(final String csv); - public void onData(int id, final String csv); + + /** received data from the given sensor */ + public void onData(final SensorType id, final String csv); + } + /** the listener to inform (if any) */ protected SensorListener listener = null; + + /** start the sensor */ public abstract void onResume(final Activity act); + /** stop the sensor */ public abstract void onPause(final Activity act); + /** attach the given listener to the sensor */ public void setListener(final SensorListener listener) {this.listener = listener;} } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 57073a4..ee33be3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -18,62 +18,55 @@ tools:context="de.fhws.indoor.sensorreadout.MainActivity"> tools:context=".MainActivity" android:background="#333"> - - + +