最近在做室内定位相关研究,希望通过手机传感器数据判断人的姿态和手机位置。之前很多研究只用到了加速度数据,但是判别的准确度偏低。本次我们的研究准备将加速度传感器、角速度传感器、方位传感器、压力传感器等数据结合起来,用于提高判别的准确度。
具体如何采集这些数据,网上并没有相关代码。在这里把自己的实现方法分享出来,供大家参考。
首先是建立加速度的类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. Python可以调用Gpu吗_加快Python算法的四个方法:Numba篇
  2. 【 MATLAB 】gallery 中的 uniformdata
  3. 毕加索发布轻量化转化引擎及BIMSOP协作云平台
  4. 谈一下对绩效和自身技能发展的理解
  5. linux alsa 录音程序,Linux下alsa直接录音代码
  6. HDU 1159 Common Subsequence
  7. 因子分析——matlab
  8. c/c++读取txt文件中指定行的内容_和尧名大叔一起从0开始学Python编程-简单读写文件
  9. php函数前面加符号 和 变量前面加符号的意义
  10. 只需6步,教你从零开发一个签到小程序
  11. html保存table并刷新,js操作 添加删除table行,并进行刷新
  12. ICMP报文类型和代码
  13. 如何在Eclipse配置Tomcat
  14. 拓端tecdat|matlab对MCMC贝叶斯方法用于加筋复合板的冲击载荷识别
  15. pandas读取与存储操作详解
  16. centos上TURN服务器搭建及测试
  17. that being said
  18. 软键盘遮挡edittext_Android软键盘遮挡的四种解决方案
  19. 2021-2027全球与中国自动卡车卸货系统 (ATLS)市场现状及未来发展趋势
  20. 结合环境专业计算机思维论文,环境艺术设计思维的表达论文范文

热门文章

  1. java组成_java是由什么组成的?
  2. 在CMD上运行javac前应该这样做
  3. 学网络安全到什么程度才能找到工作?
  4. 在vue项目中使用favicon.ico
  5. libvirt介绍和使用
  6. 量子计算与量子信息之量子信息概述
  7. 神经网络在通信中的应用,神经网络技术及其应用
  8. BGP协议详解及工作原理
  9. jdk api 1.8 -中文版
  10. 【C语言】判断输入是否能被5整除