最近在做室内定位相关研究,希望通过手机传感器数据判断人的姿态和手机位置。之前很多研究只用到了加速度数据,但是判别的准确度偏低。本次我们的研究准备将加速度传感器、角速度传感器、方位传感器、压力传感器等数据结合起来,用于提高判别的准确度。
具体如何采集这些数据,网上并没有相关代码。在这里把自己的实现方法分享出来,供大家参考。
首先是建立加速度的类AccData(本文只涉及传感器数据采集相关代码,AccData类中从数据库获取数据的代码已经略去):

/*** Created by Maolin Liu on 2016/3/12.*/
public class AccData {public long timestamp;public double ax;public double ay;public double az;public static final String TABLE_NAME = "AccData";public static final String _ID = "_id";public static final String TIMESTAMP = "timestamp";public static final String AX = "ax";public static final String AY = "ay";public static final String AZ = "az";//生成表的sql语句public static String tableCreateSQL() {StringBuffer sql = new StringBuffer();sql.append("create table ");sql.append(TABLE_NAME);sql.append(" (");sql.append(_ID);sql.append(" integer primary key autoincrement,");sql.append(TIMESTAMP);sql.append(" long,");sql.append(AX);sql.append(" double,");sql.append(AY);sql.append(" double,");sql.append(AZ);sql.append(" double");sql.append(" )");return sql.toString();}public long insertDataBase(SQLiteDatabase sqLiteDatabase) {ContentValues values = new ContentValues();values.put(TIMESTAMP, timestamp);values.put(AX, ax);values.put(AY, ay);values.put(AZ, az);return(sqLiteDatabase.insert(TABLE_NAME, null, values));}public AccData clone() {AccData accData = new AccData();accData.timestamp = timestamp;accData.ax = ax;accData.ay = ay;accData.az = az;return accData;}
}

然后是加速度的SQLiteOpenHelper类,即AccDBOpenHelper:

/*** Created by Maolin Liu on 2016/3/12.*/
public class AccDBOpenHelper extends SQLiteOpenHelper {private static final String DBNAME = "Acc Data.db3";private static final int VERSION = 1;public AccDBOpenHelper(Context context){super(context,DBNAME,null,VERSION);}public AccDBOpenHelper(Context context, String name,SQLiteDatabase.CursorFactory factory, int version){super(context, name, factory, version);// TODO Auto-generated constructor stub}@Overridepublic void onCreate(SQLiteDatabase db){db.execSQL(AccData.tableCreateSQL());}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){System.out.println( "----------AccDBOpenHelper onUpdata Called----------" + oldVersion + "-->" + newVersion);}
}

按照和上面类似的方法为角速度数据、方位数据、压力数据建立数据类和对应的SQLiteOpenHelper类。
下面是具体的实现了。如果将采集数据的的代码放在Activity中,用户体验不是特别好。所以我们在后台Service中进行数据采集。需要注意几个地方,第一,往数据库中存储大量数据的时候最好添加事务,这样会提高存储效率;第二,方向数据要通过计算获得,而不是通过传感器直接获取,如果需要用到azimuth、pitch和roll数据需要特别注意这一点(详情点击:Android Orientation Sensor(方向传感器)详解与应用)。第三,API等级在19以上,可以自由设置传感器的采样频率,注意单位是微秒(10 -6秒)。
下面是Service具体代码:

/*** Created by Maolin Liu on 2016/3/12.  */
public class DataAcquireService extends Service {private SensorManager sensorManager;private MySensorBinder mySensorBinder;private Timer updateTimer;private AccDBOpenHelper accDBOpenHelper;private SQLiteDatabase accDB;private List<AccData> accDataList;private AccData accData;private float accValues[];private GyrDBOpenHelper gyrDBOpenHelper;private SQLiteDatabase gyrDB;private List<GyrData> gyrDataList;private GyrData gyrData;private float gyrValues[];private MagAndOriDBOpenHelper magAndOriDBOpenHelper;private SQLiteDatabase magAndOriDB;private List<MagAndOriData> magAndOriDataList;private MagAndOriData magAndOriData;private PreDBOpenHelper preDBOpenHelper;private SQLiteDatabase preDB;private List<PreData> preDataList;private PreData preData;private float preValue;private float magValues[];private boolean isRecord ;             //开始存储或者关闭存储的Boolean值public static final String ACTION_STATE_COLLECT_SERVICE = "edu.geosis.service.DATA_ACQUIRE_SERVICE";@Overridepublic IBinder onBind(Intent intent) {System.out.println("DataAcquireService is binded ! ");return mySensorBinder;}@Overridepublic void onCreate() {super.onCreate();initializeVariables();             }@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {System.out.println("DataAcquireService is started ! ");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {if (accDB != null && accDB.isOpen()) {accDB.close();}if (gyrDB != null && gyrDB.isOpen()) {gyrDB.close();}if (magAndOriDB != null && magAndOriDB.isOpen()) {magAndOriDB.close();}if (preDB != null && preDB.isOpen()) {preDB.close();}sensorManager.unregisterListener(mySensorListener);      System.out.println("DataAcquireService is destroyed ! ");super.onDestroy();}@Overridepublic boolean onUnbind(Intent intent) {System.out.println("DataAcquireService is onUnbinded ! ");return super.onUnbind(intent);}@Overridepublic void onRebind(Intent intent) {System.out.println("DataAcquireService is onRebinded ! ");super.onRebind(intent);}private void initializeVariables() {mySensorBinder = new MySensorBinder();sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);accDBOpenHelper = new AccDBOpenHelper(this, "Acc Data.db3", null, 1);       //存储在默认路径下accDB = accDBOpenHelper.getReadableDatabase();accDataList = new ArrayList<AccData>();accData = new AccData();gyrDBOpenHelper = new GyrDBOpenHelper(this, "Gyr Data.db3", null, 1);gyrDB = gyrDBOpenHelper.getReadableDatabase();gyrDataList = new ArrayList<GyrData>();gyrData = new GyrData();magAndOriDBOpenHelper = new MagAndOriDBOpenHelper(this, "MagAndOri Data.db3", null, 1);     magAndOriDB = magAndOriDBOpenHelper.getReadableDatabase();magAndOriDataList = new ArrayList<MagAndOriData>();magAndOriData = new MagAndOriData();preDBOpenHelper = new PreDBOpenHelper(this, "Pre Data.db3", null, 1);preDB = preDBOpenHelper.getReadableDatabase();preDataList = new ArrayList<PreData>();preData = new PreData();isRecord = false;}/*** Service对应的Activity通过下面的Binder类对采集数据的过程进行控制**/public class MySensorBinder extends Binder {public void startRecord() {isRecord = true;}public void stopRecord() {isRecord = false;}public void clearRecord() {accDataList.clear();gyrDataList.clear();magAndOriDataList.clear();preDataList.clear();}public boolean insertDB() {//make clear whether it is "||" or "&&"if (accDataList.isEmpty() && gyrDataList.isEmpty() && preDataList.isEmpty()&& magAndOriDataList.isEmpty()) {return false;} else {//存储时开启事务能大大加快存储速度,否则一条一条地存储特别费时accDB.beginTransaction();try {for (AccData accData: accDataList) {accData.insertDataBase(accDB);}accDB.setTransactionSuccessful();}catch(Exception e) {e.printStackTrace();System.out.println("accData cannot insert into the database !");}finally {accDB.endTransaction();}gyrDB.beginTransaction();try {for (GyrData gyrData: gyrDataList) {gyrData.insertDataBase(gyrDB);}gyrDB.setTransactionSuccessful();}catch(Exception e) {e.printStackTrace();}finally {gyrDB.endTransaction();}magAndOriDB.beginTransaction();try {for (MagAndOriData magAndOriData: magAndOriDataList) {magAndOriData.insertDataBase(magAndOriDB);}magAndOriDB.setTransactionSuccessful();}catch(Exception e) {e.printStackTrace();}finally {magAndOriDB.endTransaction();}preDB.beginTransaction();try {for (PreData preData: preDataList) {preData.insertDataBase(preDB);}preDB.setTransactionSuccessful();}catch(Exception e) {e.printStackTrace();}finally {preDB.endTransaction();}return true;}}public void registerListener() {boolean result =   sensorManager.registerListener(mySensorListener,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME);                              //最后一个参数用于控制传感器数据获取的频率,频率可以自由调整Log.d("maolin",""+result);   //LOG查看监听是否成功注册sensorManager.registerListener(mySensorListener,sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(mySensorListener,sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(mySensorListener,sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),SensorManager.SENSOR_DELAY_GAME);}public void unregisterListener() {sensorManager.unregisterListener(mySensorListener);System.out.println("StateCollectService listener is unregistered ! ");}}//下面是传感器变化监听的关键类private SensorEventListener mySensorListener = new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent event) {switch(event.sensor.getType()) {case Sensor.TYPE_ACCELEROMETER:accValues = event.values.clone();synchronized (accData) {accData.timestamp = System.currentTimeMillis();accData.ax = accValues[0];accData.ay = accValues[1];accData.az = accValues[2];if (isRecord) {accDataList.add(accData.clone());}}break;case Sensor.TYPE_GYROSCOPE:gyrValues = event.values.clone();synchronized (gyrData) {gyrData.timestamp = System.currentTimeMillis();gyrData.gx = gyrValues[0];gyrData.gy = gyrValues[1];gyrData.gz = gyrValues[2];if (isRecord) {gyrDataList.add(gyrData.clone());}}break;case Sensor.TYPE_PRESSURE:preValue = event.values[0];synchronized (preData) {preData.timestamp = System.currentTimeMillis();preData.pressure = preValue;if (isRecord) {preDataList.add(preData.clone());}}break;case Sensor.TYPE_MAGNETIC_FIELD:               //加速度、陀螺仪和气压计都可以直接获得,但是磁力计和方位角数据要通过计算才能得到magValues = event.values;break;}}@Overridepublic void onAccuracyChanged(Sensor sensor, int i) {}};
}

然后就是操作界面DataAcquireActivity :

/*** Created by GeoSIS on 2016/3/12.*/
public class DataAcquireActivity extends Activity {private Chronometer chronometer = null;    //添加一个计时器,知道采集的时长;private Button btnStart,btnEnd;private ServiceConnection dataAcquireConnection;private DataAcquireService.MySensorBinder mySensorBinder;private ArrayList<Long> savedTime;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_data_acquire);initializeVariables();initializeButton();}@Overrideprotected void onStart() {super.onStart();}@Overrideprotected void onRestart() {super.onRestart();}@Overrideprotected void onResume() {super.onResume();}@Overrideprotected void onPause() {super.onPause();}@Overrideprotected void onStop() {super.onStop();}@Overrideprotected void onDestroy() {unbindService(dataAcquireConnection);super.onDestroy();}private void initializeVariables() {// TODO Auto-generated method stubchronometer = (Chronometer)findViewById(R.id.chronometer);btnStart    = (Button)findViewById(R.id.start_pick_up);btnEnd      = (Button)findViewById(R.id.end_pick_up);}private void initializeButton() {// TODO Auto-generated method stubbtnStart.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubchronometer.setBase(SystemClock.elapsedRealtime());chronometer.start();mySensorBinder.registerListener();mySensorBinder.startRecord();btnStart.setClickable(false);                                                 btnStart.setBackgroundColor(getResources().getColor(R.color.yellow));}});btnEnd.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubchronometer.stop();mySensorBinder.stopRecord();mySensorBinder.insertDB();mySensorBinder.clearRecord();mySensorBinder.unregisterListener();finish();}});}
}

Activity对应的XML文件非常简单,上面只有一个计时器(Chronometer)、一个开始采集的按钮(Button)和一个结束采集的按钮(Button),这里就不列出来了。

Android开发:按一定频率同时获取多个传感器数据相关推荐

  1. android 获取wifi的ip地址吗,Android开发实现在Wifi下获取本地IP地址的方法

    本文实例讲述了Android开发实现在Wifi下获取本地IP地址的方法.分享给大家供大家参考,具体如下: 代码核心介绍: WifiManager类提供了对设备Wifi功能的管理,包括Wifi开关的打开 ...

  2. Android手机HC-05蓝牙连接Arduino nano获取DHT-11温湿度传感器数据

    如果您觉得本文对您有用,希望您点赞,收藏并且把它分享出去,不明白的可以在评论区留言,我会一一解答,感谢您的支持!! 目标 Android手机HC-05蓝牙连接Arduino nano获取DHT-11温 ...

  3. Android使用高德和风天气Sdk获取定位实况天气数据(二)

    Android使用高德和风天气Sdk获取定位实况天气数据(二) 先看一下效果 关于 实现 第一步,引用高德api与和风天气 第二步,修改AndroidManifest.xml 第三步,修改activi ...

  4. pixhawk/px4如何获取及使用传感器数据

    pixhawk/px4如何获取及使用传感器数据 第一步:读取传感器数据 上一篇博文已经介绍了如何给pixhawk/px4创建一个应用程序,现在我们在上一个应用程序的基础上使用传感器数据. 应用程序为了 ...

  5. Android开发 Intent传递参数,获取数据为null

    android开发 Activity通过Intent传递参数,获取失败的原因 启动一个有返回值的activity (MapActivity) Intent intent = new Intent(Up ...

  6. Android开发中根据图片名称获取在drawable中的ID

    在Android开发中图片资源是必不可少的,如ImageView需要图片资源的ID,ImageButton需要资源的ID等等,我们可以用R.drawable.XXX可以获取图片资源的ID,但是,在某些 ...

  7. ROS节点获取TIA_go机器人传感器数据,并上传到指定服务器做深度学习处理

    Brief 正如标题所言,该小项目包括三部分,如下 ROS节点获取机器人数据 socket和服务器数据传输,包括了数据上传和获取 服务器深度学习处理数据 1 ROS节点获取机器人数据 1.1 数据结构 ...

  8. postek二次开发_使用PX4的ECL进行多传感器数据融合的后处理

    写在前边ecl是开源无人机项目PX4使用的算法库,使用ekf(扩展卡尔曼滤波)进行imu等多种传感器的数据融合 然而ecl不提供数据后处理功能 能使用ecl进行多传感器数据融合的后处理是很有必要的,这 ...

  9. Android开发之监听或获取手机短信内容

    最近开始学习安卓,要做一个可以监听手机短信的内容,做个笔记,方便以后查看 有两种方式: 方式一:通过广播监听短信信息 注册一个广播接收器 <receiver android:name=" ...

最新文章

  1. 星梦缘陈彦妃_还记得《星梦缘》的女主吗,她现在变成这样了
  2. 深入浅出classloader
  3. orm2 中文文档 6. 查找记录
  4. 一道有意思的找规律题目 --- CodeForces - 964A
  5. Acwing第 21 场周赛【完结】
  6. 信息系统项目管理师-项目集、项目组合管理考点笔记
  7. 【Leetcode】大神总结的所有TopK问题模板(基于快速排序)
  8. @Url cannot be used with @GET URL (parameter #1)
  9. lr0文法分析表示例_详解自然语言处理(NLP)5大语义分析技术及14类应用(建议收藏)...
  10. 证监会:对贾跃亭、杨丽杰采取终身证券市场禁入措施
  11. mysql 语句 not_mysql sql语句 is not 用法是
  12. 【直播预告】“CCF-NLP走进高校”系列之“走进郑州大学”
  13. css面试题之Flex布局
  14. 第二章注解深入浅出(三、插桩)
  15. 【win10 专业版】 重装系统、激活
  16. 【Unity3D】IK动画
  17. PyG 中Message Passing机制详解
  18. WordPress教程网站
  19. c语言 100匹马 编程,编程,百马百担有关问题,有100匹马,驮100担货,大马驮三担,中马驮2担,两匹小马驮一担,求大、中、小各多少匹...
  20. 通信设备选cat1还是选nbiot

热门文章

  1. Java异常的根类似_Java异常(Exception)类型及处理
  2. 刘强东的“百亿补贴” 被指“雷”声大雨点小
  3. python 个例程序
  4. C语言中的if、else if 的用法和区别
  5. 【Flask】 Not Found: /favicon.ico 项目logo图标加载
  6. Wayland协议解析 一 什么是Wayland
  7. 如何在服务器上编辑配置文件
  8. linux中的wget命令
  9. 增加mysql表一个字段+注释
  10. J2EE三层架构概述