声明:本文作为自己的学习笔记,欢迎大家于本人学习交流。未经本人许可,文章不得用于商业用途。转载请注明出处
开发一个 Andorid APP,使其可以用手机传感器读取手机的实时加速度、角速度和方向角,并将数据保存,测试完成后可以导出。APP 全部代码已经提交至 Github
目录
实验环境
- 操作系统:win10 64
- 软件环境:Android Studio 3.5.3
- 编程语言:Java 13
传感器开发
在 onCreate 方法中,获取传感器管理对象
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
获取传感器类型,分别为加速度传感器、方向传感器、角速度传感器
Sensor sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor sensor2 = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
Sensor sensor3 = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
注册传感器监听器
sensorManager.registerListener(listener1, sensor1, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener2, sensor2, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener3, sensor3, SensorManager.SENSOR_DELAY_GAME);
重写 onDestroy 方法,取消监听
@Override
protected void onDestroy() {
super.onDestroy();
if (sensorManager != null) {
sensorManager.unregisterListener(listener1);
sensorManager.unregisterListener(listener2);
sensorManager.unregisterListener(listener3);
}
}
获取传感器监听数据,这里只写了加速度传感器
private SensorEventListener listener1 = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float xValue = event.values[0];
float yValue = event.values[1];
float zValue = event.values[2];
accelerateX.setText("加速度X: " + xValue);
accelerateY.setText("加速度Y: " + yValue);
accelerateZ.setText("加速度Z: " + zValue);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
完整代码
MainActivity.java
package com.example.myapplication;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView accelerateX;
private TextView accelerateY;
private TextView accelerateZ;
private TextView angulX;
private TextView angulY;
private TextView angulZ;
private TextView orientationX;
private TextView orientationY;
private TextView orientationZ;
private SensorManager sensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
accelerateX = (TextView) findViewById(R.id.accelerateX);
accelerateY = (TextView) findViewById(R.id.accelerateY);
accelerateZ = (TextView) findViewById(R.id.accelerateZ);
angulX = (TextView) findViewById(R.id.angulX);
angulY = (TextView) findViewById(R.id.angulY);
angulZ = (TextView) findViewById(R.id.angulZ);
orientationX = (TextView) findViewById(R.id.orientationX);
orientationY = (TextView) findViewById(R.id.orientationY);
orientationZ = (TextView) findViewById(R.id.orientationZ);
//获取传感器管理对象
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//获取传感器类型,三个传感器分别为加速度传感器、方向传感器、角速度传感器
Sensor sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor sensor2 = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
Sensor sensor3 = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
//注册传感器监听器
sensorManager.registerListener(listener1, sensor1, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener2, sensor2, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener3, sensor3, SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (sensorManager != null) {
sensorManager.unregisterListener(listener1);
sensorManager.unregisterListener(listener2);
sensorManager.unregisterListener(listener3);
}
}
private SensorEventListener listener1 = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float xValue = event.values[0];
float yValue = event.values[1];
float zValue = event.values[2];
accelerateX.setText("加速度X: " + xValue);
accelerateY.setText("加速度Y: " + yValue);
accelerateZ.setText("加速度Z: " + zValue);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
private SensorEventListener listener2 = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float xValue = event.values[0];
float yValue = event.values[1];
float zValue = event.values[2];
angulX.setText("角速度X: " + xValue);
angulY.setText("角速度Y: " + yValue);
angulZ.setText("角速度Z: " + zValue);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
private SensorEventListener listener3 = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float xValue = event.values[0];
float yValue = event.values[1];
float zValue = event.values[2];
orientationX.setText("方向X: " + xValue);
orientationY.setText("方向Y: " + yValue);
orientationZ.setText("方向Z: " + zValue);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/TextView0"
android:layout_width="fill_parent"
android:layout_height="180dp"
android:gravity="center" />
<TextView
android:id="@+id/myTime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/accelerateX"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/accelerateY"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/accelerateZ"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/angulX"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/angulY"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/angulZ"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/orientationX"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/orientationY"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<TextView
android:id="@+id/orientationZ"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<Button
android:id="@+id/addData_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="START"/>
<Button
android:id="@+id/addData_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="END"/>
<Button
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="CLEAR" />
</LinearLayout>
数据库开发
新建 MyDatabaseHelper 类
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Sensor1("
+"id integer primary key autoincrement,"
+"time text,"
+"accelerateX real,"
+"accelerateY real,"
+"accelerateZ real,"
+"angulX real,"
+"angulY real,"
+"angulZ real,"
+"orientationX real,"
+"orientationY real,"
+"orientationZ real)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
super(context,name,factory,version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db){
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,"Create succeeded",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
}
}
向数据库中添加数据
private void addData(){
dbHelper = new MyDatabaseHelper(this,"SQLite1.db",null,1);
dbHelper.getWritableDatabase();
Button start = (Button)findViewById(R.id.addData_start);
Button end = (Button)findViewById(R.id.addData_end);
Button clear = (Button)findViewById(R.id.clear);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"开始保存",Toast.LENGTH_SHORT).show();
isRecord = true;
if (isRecord = true) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("time", time_value);
values.put("accelerateX", accelerateX_value);
values.put("accelerateY", accelerateY_value);
values.put("accelerateZ", accelerateZ_value);
values.put("angulX", angulX_value);
values.put("angulY", angulY_value);
values.put("angulZ", angulZ_value);
values.put("orientationX", orientationX_value);
values.put("orientationY", orientationY_value);
values.put("orientationZ", orientationZ_value);
db.insert("Sensor1", null, values);
}
}, 0, 200);
}
}
});
end.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isRecord = false;
Toast.makeText(MainActivity.this,"结束保存",Toast.LENGTH_SHORT).show();
}
});
clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Sensor1","id > ?",new String[]{"0"});
Toast.makeText(MainActivity.this,"清除完成",Toast.LENGTH_SHORT).show();
}
});
}
运行软件
点击 START 按钮开始记录数据,点击 END 按钮结束记录数据,点击 CLEAR 清除之前记录的数据
数据导出
数据的导出主要分为两个步骤,一是将 .db 文件从手机中导出,二是将导出的 .db 文件转为 csv 文件
从手机中导出 .db 文件
这里直接使用 Android Studio 中的 Device File Explorer 工具,这个工具在 Android Studio 界面的右下角,如图所示
按照路径 /data/data/com.example.XXX(包名)/database 找到 .db 文件,如图所示
然后将 .db 文件另存至电脑中,这里为了方便,直接将其存至 D:/
将 .db 文件转为 csv 文件
关于将 .db 文件转为 csv 文件,参考了这篇文章:将SQLite数据库中的数据导出到CSV文件
感谢这篇文章的原创作者,如果本文有侵犯您的知识产权和版权问题,请通知本人,本人会立即做出处理并删除文章
使用 Windows 上提供了一个名为 sqlite3 工具
首先,打开 WIndows 命令行:Win + R,输出 cmd,然后把目录切换到 .db 文件的路径下**(一定要把目录切换到 .db 文件的路径下,否则会找不到 table)**,输入命令
D:\>sqlite3 SQLite1.db
sqlite> .headers on
sqlite> .mode csv
sqlite> .output data.csv
sqlite> SELECT * FROM Sensor1;
sqlite> .output stdout
sqlite>
其中 data.csv 是将要输出的文件名,SQLite1.db 为 .db 文件的名称,Sensor1 为 .db 中的 table_name,运行结果如图所示