Created
April 12, 2020 16:59
-
-
Save s0lver/44f305f2e4567b23b9f91b914f17089b to your computer and use it in GitHub Desktop.
Part of a not-so-short tutorial on inertial sensors sampling in Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.s0lver.samplingtutorial.simpleaccelerometersampling; | |
import android.os.Environment; | |
import java.io.BufferedWriter; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.io.PrintWriter; | |
import java.util.List; | |
public class AccelerometerSamplesWriter { | |
private final String fileName; | |
public AccelerometerSamplesWriter(String fileName) { | |
this.fileName = fileName; | |
} | |
public void writeSamples(List<SensorAccess.AccelerometerSample> samples) { | |
String filepath = Environment.getExternalStorageDirectory().toString() + "/" + fileName; | |
try { | |
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(filepath, false))); | |
pw.println("x,y,z,t"); | |
for (SensorAccess.AccelerometerSample sample : samples) { | |
pw.println(sample.toString()); | |
} | |
pw.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity"> | |
<Button | |
android:id="@+id/btnStartSampling" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:onClick="onClickStartSampling" | |
android:text="Start sampling" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toTopOf="parent" /> | |
<Button | |
android:id="@+id/btnStopSampling" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:onClick="onClickStopSampling" | |
android:text="Stop sampling" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintTop_toTopOf="parent" /> | |
</androidx.constraintlayout.widget.ConstraintLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.s0lver.samplingtutorial.simpleaccelerometersampling"> | |
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |
<application | |
android:allowBackup="true" | |
android:icon="@mipmap/ic_launcher" | |
android:label="@string/app_name" | |
android:roundIcon="@mipmap/ic_launcher_round" | |
android:supportsRtl="true" | |
android:theme="@style/AppTheme"> | |
<activity android:name=".MainActivity"> | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
</application> | |
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.s0lver.samplingtutorial.simpleaccelerometersampling; | |
import android.os.Bundle; | |
import android.view.View; | |
import android.widget.Toast; | |
import androidx.appcompat.app.AppCompatActivity; | |
public class MainActivity extends AppCompatActivity { | |
private SensorAccess sensorAccess; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
this.sensorAccess = new SensorAccess(this); | |
} | |
public void onClickStartSampling(View view) { | |
if (!sensorAccess.startSampling()) { | |
Toast.makeText(this, "Could not start sampling (I am already sampling!)", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
public void onClickStopSampling(View view) { | |
if (!sensorAccess.stopSampling()) { | |
Toast.makeText(this, "Could not stop sampling (I am not sampling)", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.s0lver.samplingtutorial.simpleaccelerometersampling; | |
import android.content.Context; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.util.Log; | |
import androidx.annotation.NonNull; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Timer; | |
import java.util.TimerTask; | |
public class SensorAccess { | |
private final Context context; | |
private final SensorManager sensorManager; | |
private final Sensor accelerometer; | |
private final AccelerometerListener accelerometerListener; | |
private List<AccelerometerSample> samples; | |
private boolean isSampling; | |
private Timer samplingTimer; | |
public SensorAccess(Context context) { | |
this.context = context; | |
this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); | |
this.accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); | |
this.accelerometerListener = new AccelerometerListener(); | |
this.isSampling = false; | |
} | |
public boolean startSampling() { | |
if (isSampling) return false; | |
samples = new ArrayList<>(); | |
long delayInMilliseconds = 5 * 1000; | |
Log.i("SensorAccess", String.format("I will start reading in %s seconds", delayInMilliseconds / 1000)); | |
samplingTimer = new Timer(); | |
samplingTimer.schedule(new TimerTask() { | |
@Override | |
public void run() { | |
Log.i("SensorAccess", "Sampling started"); | |
sensorManager.registerListener( | |
accelerometerListener, | |
accelerometer, | |
SensorManager.SENSOR_DELAY_FASTEST); | |
} | |
}, delayInMilliseconds); | |
isSampling = true; | |
return true; | |
} | |
public boolean stopSampling() { | |
if (!isSampling) return false; | |
samplingTimer.cancel(); | |
Log.i("SensorAccess", "Sampling stopped"); | |
this.sensorManager.unregisterListener(this.accelerometerListener); | |
AccelerometerSamplesWriter writer = new AccelerometerSamplesWriter("samples.csv"); | |
writer.writeSamples(samples); | |
isSampling = false; | |
return true; | |
} | |
class AccelerometerListener implements SensorEventListener { | |
@Override | |
public void onSensorChanged(SensorEvent sensorEvent) { | |
float[] acc = sensorEvent.values; | |
long timestampMilliseconds = sensorEvent.timestamp / 1000; | |
Log.i("SensorAccess", String.format("ACC %s,%s,%s @%s", acc[0], acc[1], acc[2], timestampMilliseconds)); | |
samples.add(new AccelerometerSample(acc[0], acc[1], acc[2], timestampMilliseconds)); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int i) { | |
} | |
} | |
class AccelerometerSample { | |
float x, y, z; | |
long timestampMilliseconds; | |
AccelerometerSample(float x, float y, float z, long timestampMilliseconds) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.timestampMilliseconds = timestampMilliseconds; | |
} | |
@NonNull | |
@Override | |
public String toString() { | |
return String.format("%s,%s,%s,%s", x, y, z, timestampMilliseconds); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment