I am building a tracking app that requires regular updates from the step counter. I have been working on this for a couple of months and have not faced any problems with the step counter so far. Now from one day to the next, the step counter is counting up to a certain number, then stops increasing the step number.
I am initializing the sensor from a foreground service like this:
float steps = 0;
mStepSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
mStepSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
mSensorManager.registerListener(this, mStepSensor, SensorManager.SENSOR_DELAY_NORMAL);
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
System.out.println("TrackingService/onSensorChanged", "Steps: " + sensorEvent.values[0]);
mSteps = sensorEvent.values[0];
}
After a reboot, the steps count up properly. Some time after a couple of thousand steps, the sensor just stops to emit any events. I haven't had that problem with exactly the same code in the past, but wanted to hear: Has anyone experienced a similar issue and can recommend a solution?
Related
I am create a demo from receive step from reboot like this.
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager sensorManager;
#Override
public void onCreate(Bundle savedInstanceState) {
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
Log.i("TAG","step from reboot" + String.valueOf(event.values[0]));
}
}
}
But when I test on my device (SamSung Galaxy S4), the STEP_COUNTER sometime not work well :(. I figure out it by compare with SHealth
After many many test I found
Almost time, STEP_COUNTER return the step equals SHealth BUT sometime different. Therefore I think SHealth may use another sensor for counting step but I don't know which sensor? I think it is not STEP_DETECTOR because STEP_DETECTOR return very few step when turn off the screen.
Sometime, STEP_COUNTER stop working while SHealth still return the step, for example, I walk about 100 steps => SHealth display 110 and demo app display 100, then I continue walk about 200 steps => SHealth display 305 and demo app display 121 (seem like it stop work)
I also receive the report from many user with different device (with low rating :( ) but I can only reproduce it on my device.
I don't know how to fix this problem. I think STEP_COUNTER is the best sensor for receive step (compare with STEP_DETECTOR)
Any help or suggestion would be great appreciated.
We've also encountered in this problem, when using the default steps sensors of the phone. However, we're using TYPE_STEP_DETECTOR - and we don't have the issue you have(more than 100000 users), so perhaps something is wrong there?
This issue is quite resemble in the way that you can't rely on such mechanism. For our case, we've received a lot of steps in a short amount of time. Even if you're a tiger, you can't make that many steps.
Here's the thing, Samsung manipulates the OS and there are a lot of stuff that works well on say, nexus devices, BUT not on Samsung devices.
After trying to fix the behaviour of the step sensor, we've figured out we need an alternative for Samsung phones, or, for phones that do not support it.
FYI, We've encountered that some phones (mostly Motorola) doesn't have the steps sensors in the device, so trying to find the sensors, returns null.
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor stepDetector = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
if (stepsDetector != null) {
//Do something
}
You could implement your own mechanism, using wakelock and accelerometer(which has a huge battery consumption, watch out).
Do you unregister the sensor when you leave the app? According to the SDK documentation :
"If you want to continuously track the number of steps over a long period of time, do NOT unregister for this sensor, so that it keeps counting steps in the background even when the AP is in suspend mode and report the aggregate count when the AP is awake".
Hope this will help...
The problem I'm having is that my count is totally off, from any pedometers, fitbit, or the Samsung Step Counter.
It appears to shut down, and not add any steps after awhile.
If I enter that I'm starting at 3000 for example, it calculates an offset and it stores as a shared preference. It tries to remain registered for the the Sensor. I also store the current steps, so that if the activity that is listening for Step Broadcasts is resumed, it will request for the steps to be output.
I have tried making the service provide notifications and be a foreground service, but the accuracy does not improve, and it uses a ton of power, I have tried a wakelock, with similiar results, not accurate, and uses too much power.
As it stands, my app does not show up in the power usage statistics, so it is hardly using power at all. The hardware sensor should be capturing steps from the accelerometers, and when it does wake up, it should output the newest steps. When it does update, it is closer to the value that I set as the step count.
I am using the Step Counter which was made available in kitkat or above, on some devices. The following code registers for the sensor.
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (null != sensor)
{
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
This is within the OnCreate Method of a Service, that I have constructed.
The Service is created as sticky. And uses a broadcast receiver to receive starting steps from an activity, to compute an offset. It also broadcasts the steps that have happened. Here is more of the code.
class MyBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_REQUEST_STEPS))
{
SendStepBroadcast(currentSteps);
}
else if (intent.getAction().equals(ACTION_SET_STEPS))
{
setSteps = intent.getFloatExtra(
STEPS_OCCURRED, -1);
SendStepBroadcast(setSteps);
}
}
}
#Override
public void onSensorChanged(SensorEvent event) {
if (setSteps > -1) {
offset = setSteps - event.values[0] + 1;
SharedPreferences prefs = getSharedPreferences("com.halfwaythere",
MODE_PRIVATE);
prefs.edit().putFloat("offset", offset).apply();
setSteps = -1;
}
currentSteps = event.values[0] + offset;
SharedPreferences prefs = getSharedPreferences("com.halfwaythere",
MODE_PRIVATE);
prefs.edit().putFloat("currentSteps", currentSteps).apply();
SendStepBroadcast(currentSteps);
}
private void SendStepBroadcast(float steps) {
Intent broadcastSteps = new Intent();
broadcastSteps.setAction(ACTION_STEPS_OCCURRED);
broadcastSteps.putExtra(STEPS_OCCURRED, steps);
this.sendBroadcast(broadcastSteps);
}
In the Activity the following code is used to start the service:
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, StepService.class);
startService(intent);
}
My most recent set of attempts to fix this, I tried the following:
Use android:process=":background" to start the service in it's own process. I will try this tomorrow in a field test, and see how it works.
I tried setting the count to zero, and found out my code would not allow, so in the above code I used > -1. Since -1 shouldn't be a valid step count.
All of the code above has test wrapped around it, and I've tried to find any edge cases, and have looked over stack overflow for pedometer problems with Step Counter on Samsung Galaxy S4. Or anything about best practices.
Thanks, and if you need any additional info, please let me know.
From my research:
When the screen is locked, the Hardware Sensor waits before outputting steps. It does count steps, but once you press the button on the side it wakes up, and it receives a SensorEvent.
Service was occasionally having Start Command being called. Was very important that I only register once, so I added a boolean that would be flipped once the initialization was called, and flip off after that. Service was paused, but not killed, and Start Command would run upon it being awoken.
Setting Service to Foreground, seems to be getting closer to the value from other pedometers. Uses more battery, but is keeping it going more, so that makes sense.
Did not require wakelock, it was only on for several milliseconds, but that did not cause the hardware sensor to send results.
Will have my Service run till goal is achieved, or offer the option to stop tracking at half way point. I really just wanted something to tell me that I would get my goal if I turned around, anything else will be equivalent to extra steps.
So I will apply what I found and continue on with my app, should be on the App Store by mid July.
I developed a Data collector which collects data from Accelerometer, Gyroscope, Magnetometer and it worked fine for a while. Then I added Linear Acceleration to it as well (After 4 months, this week). Now both the version are behaving very strangely. Sometime they log the data perfectly when I do some physical activities like walking etc. However, sometimes it doesn't update sensors values and just repeat old values i.e each sensor value is updated lets after 5 seconds, 2 sec etc randomly and I need a sampling rate of 50 samples per second. I experimented with 10-15 participants and all my data was invalid because of this. The strange things is that the same app has worked perfectly before. I can't find any problem in it. I am placing some of the snapshots here. May be if someone can point to any bug or something ?
The buffered Writter:
FileWriter fow;
BufferedWriter bow;
extfile = new File(extfilepath, message + ".csv");
fow = new FileWriter(extfile);
bow = new BufferedWriter(fow);
This bow.writer is then being used in timertask thread to log data every 20 milliseconds.
Can anyone please comment or help me with this ? This weird behavior of this app is beyond my understanding.
Check that you have a wake lock acquired if your application goes to background. I've used PowerManager.PARTIAL_WAKE_LOCK successfully in a data collection application.
When your display turns off, your application is at least paused (and system might even stop it). The partial wake lock "Ensures that the CPU is running; the screen and keyboard backlight will be allowed to go off." So reading between the lines it means that otherwise your CPU might go to sleep for small periods of time in order to save power.
Did you forget to paste in:
else if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){} ?
Are you using the accelerometer data, then subtracting gravity?
OK. What's your code look like to call the timer?? Something like this?
Timer updateTimer = new Timer("linear accel");
updateTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
updateGUI();
}
}, 0, 100);
}
private void updateGUI() {
runOnUiThread(new Runnable() {
public void run() {} } ?
Couple of days back, I made my first app on Android. The basic concept is to monitor the proximity sensor, if there is an obstacle at the sensor I will increment a counter. If the counter crosses the threshold I will trigger an action.
I have implemented the sensor monitoring SW in a service, this service is called from an Activity in every 10 Min so as awake the cpu and start the service if it is stopped.
Everything was perfect, got few thousands of downloads in market with good ratings. This was fine until Android 2.3.3. Recently my mobile got upgraded to Android 2.3.6 and unfortunately the app is not working as expected.
Sensor listener does not trigger when the screen is OFF. Some times it works fine, most of the times it is not working. After giving several inputs at the sensor, after a while if I switch ON the screen, automatically all the triggers at the sensor are called at once and the counter increments and triggers the action.
To summarize, sensor listener does not work when screen goes OFF (in Android 2.3.6), this was working fine until Android 2.3.3. If I connect the debugger, phone does not go to sleep and everything works fine so I am not able to find the problem. Please help me .
Here is my code .
Calling the service at every 10 min ..
Thread trd = new Thread(){
public void run(){
int sec = 1000;
int min = 60 * sec;
Calendar cal = Calendar.getInstance();
alarmMngr.setRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(),
10 * min,
PendInt);
}
};
trd.start();
In the service ..
// On sensor change
public void onSensorChanged(SensorEvent event){
if(event.sensor == SnsrProx){
if(event.values[0] <= 5){
IncProxCntr(1);
}else{
IncProxCntr(0);
}
}
}
private void IncProxCntr(int x){
if( x == 1){
FakeCall_SnsrCnt++;
vibrate(VIBRATE_SHORT);
}
if(FakeCall_SnsrCnt >= Settings.getMaxSnsrCnts(this)){
Trig_IncominCall();
}
}
Acquire wakelock in the service also
Im working on an Android project and met the situation below:
Now we are needing the accelerometer value on a regular frequency, such as 20ms, 40ms or 60ms
Now we are SENSOR_DELAY_GAME right now but we found different devices are having different intervals for this parameter. For instance, the G2 is using 40ms, G7 is using 60ms and Nexus S is using 20ms.
I tried to set timer or used thread.sleep but because of the GC problem of Java, they can not let the system to get the value on a regular frequency.
This is very annoying and if any one has any idea to say if inside Android SDK there is a proper method to allow me get the accelerometer values on a regular frequency, that will be very helpful!
Thanks a lot!
I've done this by simply throwing away values that are sooner than I want them. Not ideal from a battery consumption standpoint as I need to have the sensors feed me more often than I need but at least then I can control that they come in on a regular interval.
Something like:
static final int ACCEL_SENSOR_DELAY = 100; // the number of milisecs to wait before accepting another reading from accelerometer sensor
long lastAccelSensorChange = 0; // the last time an accelerometer reading was processed
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) return;
long now = System.currentTimeMillis();
if (now-ACCEL_SENSOR_DELAY > lastAccelSensorChange) {
lastAccelSensorChange = now;
mCompassValues = event.values.clone();
//... do your stuff
}
I have built a code that allows you to get the exact frequency on any device.
You can download here the project and get some explanations.
In the code, you can try the different rates. For example, the normal mode on my Galaxy S2 is 5Hz.
Use registerListener by setting the sampling period as below:
boolean registerListener (SensorEventListener listener, Sensor sensor, int samplingPeriodUs)
Source
Word of caution: The samplingPeriodUs argument is only a hint to the system. Test it before using this.