I am writing an android app in java which uses Android phone's Step Counter sensor event values to record walking steps taken by the user.
Basically my java code to display current Steps is as follows:
if (running) {
totalSteps = event.values[0];
currentSteps = totalSteps - previousTotalSteps;
tv_stepsTaken.setText(String.valueOf(currentSteps));
}
I am using SharedPreferences to load, save and reset previousTotalSteps on a daily basis.
My problem is that when phone reboots, the totalSteps event value from Step Counter Sensor is reset automatically to zero, hence it turns my currentSteps value to negative as previousTotalSteps value is then being subtracted from zero. Only solution that is coming to my mind is to set previousTotalSteps to zero too. But it will defeat the purpose of recording daily steps. If the user reboots the phone in the middle of the day, then half day's data will be lost or otherwise turn negative in display. I am also recording this daily steps value to sqlite database as daily history to be shown graphically to user. So, this negative value goes to sqlite databse too and ruins the historical graph. I need suggestions to solve this problem. My reset data code is as follows:
previousTotalSteps = totalSteps;
tv_stepsTaken.setText("0");
saveStepsData();
return true;
So, I have solved this problem by myself. I am posting this solution for anyone else who find themselves in this situation, so that it might help them solve it.
For this, currentSteps as well as previousSteps need to be saved to SharedPreferences after each step. Earlier only previousSteps was being saved and that too once daily.
Thus, totalSteps-previousSteps will give an increment of one step to be added to currentSteps.
In case, the phone reboots, totalSteps value is reset to zero. If that happens(or by any chance, if totalSteps is less than previousSteps), then the previousSteps value will also be set equal to totalSteps for that condition before applying both variables for current steps calculation.
if (running) {
totalSteps = event.values[0];
loadCurrentStepsData();
loadPreviousStepsData();
if (totalSteps == 0 || totalSteps<previousSteps) {
previousSteps = totalSteps;
savePreviousStepsData();
}
currentSteps = currentSteps + (totalSteps - previousSteps);
previousSteps = totalSteps;
saveCurrentStepsData();
savePreviousStepsData();
}
tv_stepsTaken.setText(String.valueOf(currentSteps));
Related
My question might be really simple but i will appreciate any help, am using java and firebase and i have a variable in the database called count == 0, i need to increment this value every day by 1, so after 30 days the variable count should be count == 30, the only trouble is making that increment programmaticaly.
Any suggestions will be highly appreciated.
A scheduled Cloud Function deployed with the Firebase CLI will be the proper way to update your data in firebase. Your can run a scheduled function which can be triggered at a specific time (everyday or week however you want) and you can update your variable in the database inside the function. Here is a sample from firebase official documentation :
exports.scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
.timeZone('America/New_York') // Users can choose timezone - default is America/Los_Angeles
.onRun((context) => {
console.log('This will be run every day at 11:05 AM Eastern!');
return null;
});
Read documentation here : https://firebase.google.com/docs/functions/schedule-functions#write_a_scheduled_function
Is it possible to start a particle effect mid way through? I have tried many variations of updating the particle effect/emitters upon initialisation. None of them seem to work. Has anyone managed to do this before? Thanks a lot!
ParticleEffectPool.PooledEffect effect = particleEffectPool.obtain();
effect.setPosition(posnX,posnY);
float value = 1.5f;
for(ParticleEmitter e: effect.getEmitters()){
e.update(value);
value+=1.5f;
}
The above code doesn't draw all of the particles, but it does seem to update the them somewhat. Once the initial effect is over, it resets and then it looks fine
EDIT: I've found a little bit of a hack by doing the following code snippet 5 times upon initialisation of the particle effect. Still interested to see if someone has a better solution
p.getEmitters().get(0).addParticle();
p.update(1);
I assume, that all emitters in your ParticleEffect have the same duration:
ParticleEffectPool.PooledEffect effect = particleEffectPool.obtain();
effect.reset();
effect.setPosition(posnX,posnY);
//divide by 1000 to convert from ms to seconds
float effectDuration = effect.getEmitters().first().duration / 1000f;
float skipProgress = 0.5f;
effect.update(skipProgress * effectDuration);
Note, that if emitters have different duration, you probably would want to pick the max duration. Also, if your emitters have delays, you should take them into account too.
Update
This approach will not work as expected in case, when some of effect's properties change over time. So if you skip half of its duration, you don't take in account all changes that happened before. You just start from some state.
For example, let's say effect has duration = 10, and its velocity is 100 for the first 4 seconds, and after that velocity is 0. If you call effect.update(5), i.e. just skip first 5 seconds, particles will have velocity = 0, they just won't "know", that they had to move for the first 4 seconds.
So, I guess the only workaround here, is to update the effect with small steps in a loop, instead of just updating for half of its duration in one call:
ParticleEffectPool.PooledEffect effect = particleEffectPool.obtain();
effect.reset();
effect.setPosition(posnX,posnY);
//divide by 1000 to convert from ms to seconds
float skipDuration = 0.5f * effect.getEmitters().first().duration / 1000f;
//I guess, to reduce number of iterations in a loop, you can safely use
//a bit bigger stepDeltaTime, like 1 / 10f or bigger, but it depends on you effect;
//here I just use standard frame duration
final float stepDeltaTime = 1 / 60f;
while (skipDuration > 0) {
float dt = skipDuration < stepDeltaTime ? skipDuration : stepDeltaTime;
effect.update(dt);
skipDuration -= stepDeltaTime;
}
I have a step counter app in which I am running a service which counts steps taken and then sends a broadcast to the fragment which is then updated on the fragment. The step counting is working fine but I want to calculate speed based on the steps. Here is what I am trying right now.
The receiver to get step count:
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int steps = intent.getIntExtra(StepCounterService.STEP_INCREMENT_KEY, 0);
if (firstStepTime.equals("0")) {
firstStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
} else if (secondStepTime.equals("0")) {
secondStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
} else {
firstStepTime = secondStepTime;
secondStepTime = intent.getStringExtra(StepCounterService.TIME_STAMP_KEY);
}
updateAllUI(steps);
}
};
So what I am doing is as soon as I start getting steps, I see if the variable firstStepTime is empty. If it is, I save the time in firstStepTime variable. The in the next step I see if secondStepTime is empty, and if it is, I save that time in secondStepTime variable.
Now for the next steps both these are updated.
public void updateAllUI(int numberOfSteps) {
if (!(firstStepTime.equals("0")) && !(secondStepTime.equals("0"))) {
try {
Calendar c = Calendar.getInstance();
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
timeDifference = timeFormat.parse(secondStepTime).getTime() - timeFormat.parse(firstStepTime).getTime();
speed = (float) ((0.0254 / (timeDifference * 0.001)) * 3.6);
} catch (Exception e) {
timeDifference = 0;
speed = 0;
}
textview.settext(speed +"Km/h);
}
}
So in this I just check if both are not empty, I take the values and calculate the difference in times. The problem here is sometimes it doesn't count speed properly. And a bigger problem is if the user stops, the speed remains constant and doesn't drop to zero.
Is there any better way to do the speed calculation?
As you're only counting steps and would like to calculate speed with steps taken only i am assuming that you would not like to use GPS for counting speed or you would like to provide backup speed counter if GPS is not there.
You can start a new thread by doing
int interval=1*1000; //specifying interval to check steps
Handler.postDelayed(mySpeedChecker(),1000);
You'll need to do this for every step taken
public void mySpeedChecker(){
// assuming steps taken stored in a global variable
// and there is one more variable which is updated by this function
// to store number of steps before as global variable to calculate number of steps in time interval.
// this should check if another step has been taken in the interval to check
// if stepsTaken>0 then speed is not zero and you'll know how much steps are taken
// if zero steps are taken then speed is zero
// also it will tell you number of steps taken in last second
// so you can use this to calculate and update speed
// increase the interval for high accuracy but lower frequency of updates
}
Also, it's a good idea to calculate user stride length when GPS is available so, whenever user is using GPS the step length can be calculated by finding out the distance covered/number of steps taken with the help of GPS, this will help your system calculate accurately the distance covered by user with the help of number of steps taken.
The usual way to calculate speed ideally would be using Location.getSpeed(), or some analysis on Accelerometer values. but I'm assuming you want to get it based on steps counted.
To solve one of the problems: " if the user stops, the speed remains constant and doesn't drop to zero."
You can use the Android Activity Recognition Api to see the users current activity. Use
ActivityRecognition.getMostProbableActivity()
If the DetectedActivity is type STILL, you can set your speed to be zero.
You can also get the confidence DetectedActivity.getConfidence() to be sure.
For the other problem when you said it doesn't count speed properly, could you elaborate more on that question?
Every information coming from the sensors has an amount of error and even loose of data.
You should store the information received in a queue or database including the time stamp.
Periodically, you will pick the data and analyze it, including filtering to get a more accurate information.
Hope it helps.
I'm using google maps android to get current location:
LatLng currentLocation = new LatLng(location.getLatitude(), location.getLongitude());
How would I construct a simple loop to produce only say every 4th currentLocation instead of every point being fed through the locationManager?
Rather than using a loop to ignore location updates, I think you should only request location updates at the frequency you would like to receive them, otherwise the device is using all the power to get the location only to have it ignored.
You should be using the LocationClient rather than LocationManager
See the following links for how to use LocationClient
http://developer.android.com/training/location/retrieve-current.html
http://developer.android.com/reference/com/google/android/gms/location/LocationClient.html#requestLocationUpdates(com.google.android.gms.location.LocationRequest, android.app.PendingIntent)
vs LocationManager
http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent)
but both provide methods to request location updates at a specific frequency via a
requestLocationUpdates()
Option 1 - the right one - limit location provider querying
This should somewhat optimize battery life and is how the API was intended to be used.
Assuming you use LocationManager#requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) for obtaining current location, if you increase minTime four times you will effectively receive every fourth location update.
Option 2 - the lazy one - only update map every n seconds
This will allow you to process every location received from location provider but update map only every n seconds.
You want to keep track of when you last updated map and only update if n seconds have passed.
Declarations:
long lastTime = -1; // no location update yet
final long delta = 15 * 1000; // fifteen seconds apart
In your onLocationChanged:
// common code here, do this for every location received ...
Log.d(TAG, location + "");
// this gets executed only after fifteen seconds
if (location.getTime() > lastTime + delta) {
// update map here
lastTime = location.getTime();
}
Note that this will not ensure that you get a map update precisely every fifteen seconds. You will get the first update after fifteen seconds have passed.
I have updated this question(found last question not clear, if you want to refer to it check out the reversion history). The current answers so far do not work because I failed to explain my question clearly(sorry, second attempt).
Goal:
Trying to take a set of numbers(pos or neg, thus needs bounds to limit growth of specific variable) and find their linear combinations that can be used to get to a specific sum. For example, to get to a sum of 10 using [2,4,5] we get:
5*2 + 0*4 + 0*5 = 10
3*2 + 1*4 + 0*5 = 10
1*2 + 2*4 + 0*5 = 10
0*2 + 0*4 + 2*5 = 10
How can I create an algo that is scalable for large number of variables and target_sums? I can write the code on my own if an algo is given, but if there's a library avail, I'm fine with any library but prefer to use java.
One idea would be to break out of the loop once you set T[z][i] to true, since you are only basically modifying T[z][i] here, and if it does become true, it won't ever be modified again.
for i = 1 to k
for z = 0 to sum:
for j = z-x_i to 0:
if(T[j][i-1]):
T[z][i]=true;
break;
EDIT2: Additionally, if I am getting it right, T[z][i] depends on the array T[z-x_i..0][i-1]. T[z+1][i] depends on T[z+1-x_i..0][i-1]. So once you know if T[z][i] is true, you only need to check one additional element (T[z+1-x_i][i-1]) to know if T[z+1][i-1] will be true.
Let's say you represent the fact whether T[z][i] was updated by a variable changed. Then, you can simply say that T[z][i] = changed && T[z-1][i]. So you should be done in two loops instead of three. This should make it much faster.
Now, to scale it - Now that T[z,i] depends only on T[z-1,i] and T[z-1-x_i,i-1], so to populate T[z,i], you do not need to wait until the whole (i-1)th column is populated. You can start working on T[z,i] as soon as the required values are populated. I can't implement it without knowing the details, but you can try this approach.
I take it this is something like unbounded knapsack? You can dispense with the loop over c entirely.
for i = 1 to k
for z = 0 to sum
T[z][i] = z >= x_i cand (T[z - x_i][i - 1] or T[z - x_i][i])
Based on the original example data you gave (linear combination of terms) and your answer to my question in the comments section (there are bounds), would a brute force approach not work?
c0x0 + c1x1 + c2x2 +...+ cnxn = SUM
I'm guessing I'm missing something important but here it is anyway:
Brute Force Divide and Conquer:
main controller generates coefficients for say, half of the terms (or however many may make sense)
it then sends each partial set of fixed coefficients to a work queue
a worker picks up a partial set of fixed coefficients and proceeds to brute force its own way through the remaining combinations
it doesn't use much memory at all as it works sequentially on each valid set of coefficients
could be optimized to ignore equivalent combinations and probably many other ways
Pseudocode for Multiprocessing
class Controller
work_queue = Queue
solution_queue = Queue
solution_sets = []
create x number of workers with access to work_queue and solution_queue
#say for 2000 terms:
for partial_set in coefficient_generator(start_term=0, end_term=999):
if worker_available(): #generate just in time
push partial set onto work_queue
while solution_queue:
add any solutions to solution_sets
#there is an efficient way to do this type of polling but I forget
class Worker
while true: #actually stops when a stop work token is received
get partial_set from the work queue
for remaining_set in coefficient_generator(start_term=1000, end_term=1999):
combine the two sets (partial_set.extend(remaining_set))
if is_solution(full_set):
push full_set onto the solution queue