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.
Related
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));
in my model I have 9 different service blocks and each service can produce 9 different features. Each combination has a different delay time and standard deviation. For example feature 3 need 5 minutes in service block 8 with a deviation of 0.05, but only needs 3 minutes with a deviation of 0.1 in service block 4.
How can I permanently track the last 5 needed times of each combination and calculate the average (like a moving average)? I want to use the average to let the products decide which service block to choose for the respective feature according to the shortes time comparing the past times of all of the machines for the respective feature. The product agents already have a parameter for the time entering the service and one calculating the processing time by subtracting the entering time from the time leaving the service block.
Thank you for your support!
I am not sure if I understand what you are asking, but this may be an answer:
to track the last 5 needed times you can use a dataset from the analysis palette, limiting the number of samples to 5...
you will update the dataset using dataset.add(yourTimeVariable); so you can leave the vertical axis value of the dataset empty.
I assume you would need 1 dataset per feature
Then you can calculate your moving average doing:
dataset.getYMean();
If you need 81 datasets, then you can create a collection as an ArrayList with element type DataSet
And on Main properties, in On Startup you can add the following code and it will have the same effect.
for(int i=0;i<81;i++){
collection.add(new DataSet( 5, new DataUpdater_xjal() {
double _lastUpdateX = Double.NaN;
#Override
public void update( DataSet _d ) {
if ( time() == _lastUpdateX ) { return; }
_d.add( time(), 0 );
_lastUpdateX = time();
}
#Override
public double getDataXValue() {
return time();
}
} )
);
}
you will only need to remember what corresponds to what serviceblock and feature and then you can just do
collection.get(4).getYMean();
and to add a new value to the dataset:
collection.get(2).add(yourTimeVariable);
It takes UTC + 0 for the application to work, but the exact minutes and seconds are needed.
Since access to the network is not permanent, The exact time can not always be determined. If the method is still like that, determine the exact time.
If your application is dependent on the network time, what you can do is the following.
When network becomes available:
use the network to get the time
get system time
calculate the difference
store the difference
use the network time
When network is not available:
get the stored difference
get system time
calculate the needed time
use the calculated time
use System.currentTimeMillis() to get current timestamp and then convert it to minutes with following method
public long getCurrentMinOfHour()
{
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
return (long)((c.get(Calendar.MINUTE) * 60 * 1000)) ;
}
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 am trying to plot availability of node (machine). In order to save storage on data collected, instead of recording data on fixed interval, I record them based on events (ADDED, REMOVED). ADDED means "up", REMOVED means "down/unreachable"
Here's the sample data I have:
2012-11-25 11:11:11.1234 - node added.
2012-11-25 15:01:20.1234 - node removed.
2012-11-25 18:12:12.1234 - node added.
Let's say, I want to plot a graph from time range: 2012-11-24 to 2012-11-25 (x-axis), Up/Down (y-axis) , how do I plot the graph?
i think there are some examples (i cant remember which one) in the d3 tools (http://d3js.org)
If you look through the examples you can choose the type of visualisation you want to use.
I think the data set you have would match to what you are trying to do (you may need to write a small operator to convert to the up/down comment to an integer).
If you have all your data stored in an array, simply use JavaScript's built in Array.filter method, and use JavaScript's Date object to convert the timestamp into milliseconds (note that it'll round to the nearest thousandth of a second - only 3 decimal places).
var startTime = Date.parse("2012-11-24"),
endTime = Date.parse("2012-11-25") + 86400000; /* Add one day */
filteredData = data.filter(function(d) {
var time = Date.parse(d.time);
return (time >= startTime && time < endTime);
});
You'll may need to play around with the date ranges, I'm assuming you mean that you want data which is on between 2012-11-24 and 2012-11-25 inclusive.
If your data is in a database, another way would be just to simply query the database to only display data which exists within the time range (you could call some PHP script - using d3.text - which outputs JSON and accepts two GET parameters, startTime and endTime).
d3.text("getNodes.php?startTime=" + startTime + "&endTime=" + endTime, function(json) {
filteredData = JSON.parse(json);
});