安卓计步器

本文详细介绍了安卓计步器的实现,包括通过传感器获取步数,数据库存储,以及数据显示。讨论了ios健康软件的计步器功能,并解析了安卓计步器的传感器监听、服务注册和数据库操作。提到了两种计步方法,推荐使用Sensor.TYPE_STEP_DETECTOR,同时指出了跨天步数统计的挑战。文章提供了数据库操作、时间戳工具、步数获取和计步器服务的实现代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

针对计步器的基本需求功能如下:
1.通过传感器得到步数
2.通过数据库储存步数
3.从数据库调出相应数据显示步数

分析ios系统自带健康软件中的计步器,数据显示为:
1.步行+跑步距离
2.步数
3.已爬楼层
其中每项显示均包含日、周、月、年的数据柱形图显示和对应时长的平均值显示,并能显示所有数据的具体时间和数值。

当传感器的值发生变化时,会调用onSensorChanged方法。当传感器的精度变化时会调用onAccuracyChanged方法。onSensorChanged方法里根据stepSensor(计步传感器类型 0-counter 1-detector)的类型设置StepDcretor.CURRENT_SETP的值,然后调用updateNotification方法更新通知栏。在onCreate方法里看到,首先获取了当前的日期,然后初始化一个广播接收者,接着开启子线程执行startStepDetector方法。
先看addCountStepListener方法,API版本大于19执行这个方法,首先先拿到两种传感器,TYPE_STEP_COUNTER 计步传感器,用于记录激活后的步伐数。TYPE_STEP_DETECTOR 步行检测传感器,用户每走一步就触发一次事件。根据拿到的情况来注册监听,sensorManager.registerListener(StepService.this, countSensor, SensorManager.SENSOR_DELAY_UI);查资料后得知这里第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率 。如果两种传感器都没拿到,就还是执行addBasePedoListener方法。在addBasePedoListener方法里获得加速度传感器,注册监听,然后调stepDetector里的回调接口更新通知栏。
总结一下就是开启一个服务,在服务里注册一个广播接收者监听屏幕和电源情况保存数据,并且新建子线程,在子线程里开启计步检测,根据不同的API版本获取传感器管理器和传感器实例并注册监听,然后更具传感器返回的数据,然后更新界面。

代码主要包括:
1.数据库的实现
2.时间戳工具
3.获取步数信息
5.计步器服务器

计步器原理
实现计步器几步一般有2种方法:
1.利用加速传感器,通过计算二次波峰来确定每一步,这种方法误差比较大,但普适性好;
2.利用Android4.4之后的Sensor.TYPE_STEP_DETECTOR来计步,缺点是这个传感器只有4.4以后的版本才能使用而且手机要有三轴陀螺仪,限制比较大,鉴于微信运动也是使用的第二种方法,这里也放弃第一种方法的使用。(备注:可以找个方法一的算法对接到方法二上,因为Android自带的计步器太简陋了,一切都需要
自己实现,这个下文有说明)

关于TYPE_STEP_DETECTOR
通过TYPE_STEP_DETECTOR传感器我们只能获得2个数据:
1.时间戳(这个在开关机面前就废了,不做考虑);
2.从上次开机到现在的总步数(总步数会在开关机时清零),对,只是总步数……这样就不能确定某一天的步数了。

说明
关于跨天会想到Date_Changed这个系统广播,然而该广播不可信任,原因:该广播只会发出一次,
如:用户往后调整过时间,并在00:00(记此时为t)发送过该天的广播,那么当用户再次将时间拨回到正常时间时,再次经过t时刻,
系统不会发送Date_Changed广播;另外,开机广播也不可信任,原因:部分手机厂商会屏蔽掉该广播。

实现步骤
1.计步器步数数据库的实现
关于数据库这里没有使用第三方框架,已接入第三方框架的,请自行修改。数据库结构如下:

date:时间戳,表明是哪一天的数据
steps:修正步数,非真实步数,下面会解释(已DES加密)
sensor:修正传感器步数(该值非负,只有off为1或插入新数据时才为0),和上一天的sensor及off的状态有关(已des加密),之所以用修正结果,是为了监听异常关机
off:手机是否正常关机,1表示正常关机,0表示未关机,请无视这么命名,这得改啊

数据库操作代码:
/**
* 这里为了方便查看数据创建了2个表格一个DES加密,一个未加密,根据需要 自行修改
*/
public class Database extends SQLiteOpenHelper {

private final static String DB_NAME = "steps";
private final static String DB_NAME_ENCRYPT = "steps_encrypt";
private final static int DB_VERSION = 1;

private static Database instance;
private static final AtomicInteger openCounter = new AtomicInteger();

private Database(final Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

public static synchronized Database getInstance(final Context c) {
    if (instance == null) {
        instance = new Database(c.getApplicationContext());
    }
    openCounter.incrementAndGet();
    return instance;
}

@Override
public void close() {
    if (openCounter.decrementAndGet() == 0) {
        super.close();
    }
}

/**
 * date : 计步的日期
 * steps : 开关机后存储的步数
 * sensor : 虚拟传感器的步数(非真实值,和上一天是否关机有关),计步器传感器每次变化都会触发
 * off : 是否关机过,默认false(0);关机时置为true(1),待计步服务开启后将当天的off置为false(0) ;
 *
 * @param db
 */
@Override
public void onCreate(final SQLiteDatabase db) {
    db.execSQL("CREATE TABLE " + DB_NAME + " (date INTEGER, steps INTEGER , sensor INTEGER , off INTEGER)");
    db.execSQL("CREATE TABLE " + DB_NAME_ENCRYPT + " (date INTEGER, steps TEXT , sensor TEXT , off INTEGER)");
}

@Override
public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
    // 关于升级数据库,暂时不处理
}

/**
 * Query the 'steps' table. Remember to close the cursor!
 *
 * @param columns       the colums
 * @param selection     the selection
 * @param selectionArgs the selction arguments
 * @param groupBy       the group by statement
 * @param having        the having statement
 * @param orderBy       the order by statement
 * @return the cursor
 */
public Cursor query(final String[] columns, final String sele
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值