Android 计步器应用中50Hz时的加速度计频率

Android 计步器应用中50Hz时的加速度计频率,android,notifications,frequency,android-sensors,Android,Notifications,Frequency,Android Sensors,我是一个编程新手,这实际上是我在android上的第一个项目。 我正在开发一个计步器应用程序。为此,我需要以恰好50 Hz的频率收集数据。所有可用选项都不允许我获得令人满意的结果: SensorManager.SENSOR_DELAY_FASTES SensorManager.SENSOR_DELAY_GAME SensorManager.SENSOR_DELAY_NORMAL SensorManager.SENSOR_DELAY_UI 所以我试着这样: sm.registerListe

我是一个编程新手,这实际上是我在android上的第一个项目。 我正在开发一个计步器应用程序。为此,我需要以恰好50 Hz的频率收集数据。所有可用选项都不允许我获得令人满意的结果:

SensorManager.SENSOR_DELAY_FASTES

SensorManager.SENSOR_DELAY_GAME

SensorManager.SENSOR_DELAY_NORMAL

SensorManager.SENSOR_DELAY_UI
所以我试着这样:

sm.registerListener(this, accelerometer, 20000);
这就产生了问题。尽管频率给定,但系统不会每隔20毫秒返回一次样本。我做了一些测量来告诉你我的意思:

  • ms x y z

  • 71048-0.0059945136 7.981956 E-4-0.17364979

  • 71068-0.024843872 0.0054850876-0.22273922

  • 71086 0.016724974 0.0061867684-0.12516594

  • 71106 0.008605644 0.0050877184-0.15809155

  • 71127-0.016088352 0.0035609156-0.19820023

  • 711507.1662664E-4 0.010106161-0.14373398

  • 71167 0.007880032 0.0055761486-0.15989017

  • 71187 0.016164377 7.1927905E-4-0.1634798

  • 71209-0.0028537065-0.0033412725-0.17127609

  • 71227 0.0044119656-0.0018739849-0.16169643

  • 正如您在提供的数据中所看到的,采样之间的间隔并不总是20ms

    在这里,我找到了如何处理它的想法:

    “不幸的是,正如其他答案所建议的那样,您设置的延迟(或采样率)只是您的应用程序所需的最小值的建议(对于系统而言)。然而,这可能会因其他正在运行的应用程序或您的设备进入节能模式(关闭cpu等)而发生巨大变化。”。我能够获得较好的采样率的一种方法是记录来自某个服务的数据,使该服务成为前台服务,并使用带有标志PARTIAL_WAKE_lock的电源锁。“

    但是,我无法实现此方法。这给了我一个错误:

    Caused by: java.lang.NullPointerException: class name is null
    
    这就引出了这条线:

    startForeground(notificationId, notification);
    
    这是我的代码(我知道有点乱,很抱歉):

    和方法OnStart命令:

    public int onStartCommand(Intent intent, int flags, int startId) {
        //Power management
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); //Uzyskujemy dostęp do PowerManager'a.
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");  //PARTIAL_WAKE_LOCK zapewnia że CPU pracuje.
        wl.acquire();
        Log.d(TAG,"onStartCommand");
        return START_STICKY;
    }
    
    上述代码属于传感器服务类:

    public class SensorService extends Service implements SensorEventListener{
    ....
    }
    
    传感器服务类的名称如下:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pedometer_test);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    
        xText = (TextView)findViewById(R.id.xText);
        yText = (TextView)findViewById(R.id.yText);
        zText = (TextView)findViewById(R.id.zText);
        textViewSteps = (TextView)findViewById(R.id.textViewSteps);
    
        this.stepCounter = new StepCounter(textViewSteps);  
    
        this.filterValues = new FilterValues(stepCounter, filteredFileWriter);  
        this.sensorService = new SensorService(xText, yText, zText, textViewSteps, stepCounter, filterValues, getApplicationContext());
    
    }
    
    你们对如何修复这个错误有什么想法吗?也许有另一种更简单的方法来设定这个均匀采样率?或者我正在尝试实现一种根本不起作用的方法? 我将感谢任何形式的帮助

    PS:这是我在StacOverFlow上的第一篇文章,所以我为错误的格式和糟糕的英语提前道歉。我已经有一段时间没有用这种语言写任何东西了

    编辑:计步器算法的整体思想基于:


    Android传感器采样频率无处不在。我见过Android设备无法在50Hz下对加速度传感器进行采样。。。有些可以超过300Hz。如果您需要精确的50Hz,我唯一想到的是使用SensorManager.Sensor\u DELAY\u最快设置传感器管理器的加速度,然后使用thread.Sleep()或PostDelay()从线程或处理程序中以精确的50Hz采样该值。然而,我怀疑你可以通过查看算法来解决50Hz的问题,但这是不同的问题。Android传感器采样频率到处都是。我见过Android设备无法在50Hz下对加速度传感器进行采样。。。有些可以超过300Hz。如果您需要精确的50Hz,我唯一想到的是使用SensorManager.Sensor\u DELAY\u最快设置传感器管理器的加速度,然后使用thread.Sleep()或PostDelay()从线程或处理程序中以精确的50Hz采样该值。然而,我怀疑您可以通过查看算法来解决50Hz问题,但这是另一个问题。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pedometer_test);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    
        xText = (TextView)findViewById(R.id.xText);
        yText = (TextView)findViewById(R.id.yText);
        zText = (TextView)findViewById(R.id.zText);
        textViewSteps = (TextView)findViewById(R.id.textViewSteps);
    
        this.stepCounter = new StepCounter(textViewSteps);  
    
        this.filterValues = new FilterValues(stepCounter, filteredFileWriter);  
        this.sensorService = new SensorService(xText, yText, zText, textViewSteps, stepCounter, filterValues, getApplicationContext());
    
    }