Android - get location after some time - java

I can get location using LocationManager taking minDistance and minTime.
But how can I get location every 15 secs, for example? (even if an user didn't move)
if (Utils.hasProvider(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 15000, 100f, this);
}
if (Utils.hasProvider(LocationManager.NETWORK_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 15000, 100f, this);
}

Google docs say that
The minDistance parameter can also be used to control the frequency of
location updates. If it is greater than 0 then the location provider
will only send your application an update when the location has
changed by at least minDistance meters, AND at least minTime
milliseconds have passed. However it is more difficult for location
providers to save power using the minDistance parameter, so minTime
should be the primary tool to conserving battery life.
Thus there is an AND condition involved. So you should set your distance parameter to 0. In that case you will get location update every 15 seconds.

Use AlarmManager to do this.See this answer.Replace the time to 5 minutes.
Or else,you can use
Runnable runnable = new Runnable() {
public void run()
{
//Your code to fetch location
}
};
Handler handler1 = new Handler();
handler1.postDelayed(runnable, 15000);
Here 15000 is 15 seconds.

You can use IntentService and on onstartcommand call runnable to post you location, like this
Handler handler.postDelayed(postGpsRunnable, 15000);

Related

Fused location provider - Location.getSpeed() is very low

In my app I want to track the distance traveled.
I wanted to check whether the user is moving or not.
I tried to look at the speed values, but location.getSpeed() is always a lot lower than the real speed.
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000);
locationRequest.setSmallestDisplacement(0);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setWaitForAccurateLocation(true);
locationCallback = new LocationCallback()
{
#Override
public void onLocationResult(#NonNull LocationResult locationResult)
{
for (Location location : locationResult.getLocations())
{
//OTHER CODE
//...
System.out.println(location.getSpeed());
//OTHER CODE
//...
}
}
};
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
The values I get don't make any sense.
Of course, when I stand still I get really small values.
But when I walk I get values around 1.
And when I'm in a car I get values around 10-15 even though I'm actually going cca 50km/h.
Am I doing something wrong, or is this normal?
Android Location reports speed in m/sec. 15 m/sec = 54 kph.

Fetch firebase data in a runnable

I have an app in which when a user's post gets liked, I want the user to get a notification.
I can use the ChildValueEventListener but that is too fast.
I don't want the user to get bombarded with notifications every time a 'like' happens. Because if another user constantly keeps 'liking' and 'unliking' a post, the post author user will be bombarded with notifications.
My plan is to run the SingleValueEventListener inside a Runnable/Handler and check for notifications every 20 seconds. Something like this below:
Handler handler = new Handler();
int delay = 20000; // 20 seconds
handler.postDelayed(new Runnable(){
public void run(){
databaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("USER_NOTIFICATION") {
// new notification exists - alert user
}
handler.postDelayed(this, delay);
}
}, delay);
I have two questions. 1) Is it okay to do this? I mean, is it expensive fetch for data every x seconds? 2) Is it okay to run that piece of code inside a Service so that user can still get notifications even when the app is closed or killed?
You're in one go negating the biggest advantage of the Firebase Database (its realtime updates), and reintroducing a big disadvantage it solves (each time you will now download all data, instead of only getting incremental updating).
You're likely better off instead throttling the number of changes you surface to your users in the client-side code. So use a regular ChildValueEventListener and simply throttle the updates on the client.
E.g.
public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
if (System.currentTimeMillis() - lastShownTimestamp > 20000) {
// TODO: show latest data on screen
lastShownTimestamp = System.currentTimeMillis();
}
}

android: taking pictures in task or thread at regular interval?

I'm writing an android app which should take pictures in a user-defined interval (20 sec - 1 min). It should take the pictures even while it is running in background or while the device is sleeping. The app will run for a very long time period. If it is necessary to wake up the device, it should put back to sleep as soon as possible to save batterie life. After taking a picture the app will process some additional work (comparison of two pictures).
I read some stuff about sheduling alarms (http://developer.android.com/training/scheduling/alarms.htm), creating Services (also # android training) and Android AsyncTasks, Java threads (http://www.mergeconflict.net/2012/05/java-threads-vs-android-asynctask-which.html)
... but I'm still not sure what is the best way to achieve this.
My questions are:
Should I use thread or a task to take the pictures in background?
(the comparison of the two pictures might take longer than a few
milliseconds but i don't know anything about the cpu load of this
operation)
Should I use an alarm to wake the device up or are there any alternative solutions?
How can both (alarms and thread/task) work together? (Include the Alarm in the Task/Thread?)
Many thanks for your help in advance.
As to our question I know I can help get started with the aspect of repeating the picture taking task at a user defined time interval. For such a task you can user a Timer to achieve this. The code would look something like this:
mTmr = new Timer();
mTsk = new TimerTask() {
#Override
public void run() {
//Take picture or do whatever you want
}
};
mTmr.schedule(mTsk, 0, USER_DEFINED_EXECUTION_INTERVAL);
schedule begins the timer. The first parameter of schedule used here is the task to run which is mTsk. The second parameter is the delay until the first execution (in milliseconds), in this case no delay. The third parameter is what you'll want to manipulate which is the interval of executions. The parameter is the time between executions so if it were 20 seconds you'd pass in 20,000. If it were a minute it would be 60,000. You can get this value from the user using any method you'd like.
To keep the timer running make sure you don't call mTmr.cancel in onPause because for your case you want to keep the timer running while the user isn't on the app. Not calling cancel means the timer will hold it's resources until the app is closed by the user.
OR you can look at this How to schedule a periodic task in Java? If you'd like to use ScheduledExecutorService instead of a Timer.
I have made this app - Lenx. It uses Camera extensively and I am processing image in the background. I have used AsyncTask to process the image and it has never given any problems. The app also has a timer which starts the process after certain interval. The logic that I have used is very simple.
I have not used Camera2 API yet, so the code might be deprecated. I created CameraPreview class which implements Camera.PreivewCallback.
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (data == null) {
return;
}
int expectedBytes = previewWidth * previewHeight *
ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
if (expectedBytes != data.length) {
Log.e(TAG, "Mismatched size of buffer! Expected ");
mState = STATE_NO_CALLBACKS;
mCamera.setPreviewCallbackWithBuffer(null);
return;
}
if (mProcessInProgress || mState == STATE_PROCESS_IN_PROGRESS) {
mCamera.addCallbackBuffer(data);
return;
}
if (mState == STATE_PROCESS) {
mProcessInProgress = true;
processDataTask = new ProcessDataTask();
processDataTask.execute(data);
}
}
public void startProcessing() {
mState = STATE_PROCESS;
}
And my AsyncTask is something like this
private class ProcessDataTask
extends
AsyncTask<byte[], Void, Boolean> {
#Override
protected Boolean doInBackground(byte[]... datas) {
mState = STATE_PROCESS_IN_PROGRESS;
Log.i(TAG, "background process started");
byte[] data = datas[0];
long t1 = java.lang.System.currentTimeMillis();
// process your data
long t2 = java.lang.System.currentTimeMillis();
Log.i(TAG, "processing time = " + String.valueOf(t2 - t1));
mCamera.addCallbackBuffer(data);
mProcessInProgress = false;
return true;
}
#Override
protected void onPostExecute(Boolean result) {
mState = STATE_PROCESS_WAIT;
}
}
onPreviewFrame() will always get called as long as the camera preview is running. You need to take the data and process it only when you trigger something. So simply change the state of a variable, in this case, mState, and based on the state, call your AsyncTask.

Why android.os.Handler's method "postDelay" is delayed 1-3 ms every time

I done simple timer that count the difference between time of clicking of button, and current time. Every second (1000ms).
The main part is :
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
MainActivity.this.timerHandler.postDelayed(this,1000);
long mlSecondToGo;
mlSecondToGo = System.currentTimeMillis() - MainActivity.this.clickedButtonTime;
MainActivity.this.timerTextView.setText(Long.toString(mlSecondToGo));
}
};
Whole code : https://gist.github.com/anonymous/7830279
I wonder why it the "1000ms" delay of the handler:
MainActivity.this.timerHandler.postDelayed(this,1000);
is delayed of 1-3 every time I call it.
I mean the TextView shows:
1001 then 1002 then 3004 and so on.
I made the video of it (using of Android's 4.4 screenrecord command from ADB)
http://youtu.be/TyFyS6k5L5c
Thank you very much for an answer.

The minDistance parameter in requestLocationUpdates

I'm trying to find the optimal minDistance value for my application in the requestLocationUpdates method. I would like to generate 1 location every 10 minutes and when I'm moving something like 100 meters.
I tried to set the minDistance parameter to 100 but I keep getting locations while my phone doesn't move even 1 meter! I keep increasing it and I stoped in 500m as a parameter since it become useless.
My question is, how come I keep getting updates while my phone is moving in the wrost case 5 meters and my minDistance parameter is 500.
Here is some code:
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, TEN_SECONDS*6*5, TEN_METERS*50, listener);
if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, TEN_SECONDS*6*5, TEN_METERS*50, listener);
I'm using a timer task which ran every 10 minutes, here is the listener and the task:
...
#Override
public void onLocationChanged(Location location)
{
handleLocation(location);
}
...
private void handleLocation(Location location)
{
if(isUsable(location))
this.location = location;
}
public boolean isUsable(Location location)
{
return location!=null && location.hasAccuracy() && location.getAccuracy() < 800;
}
public void run()
{
if(location!=null)
{
Timestamp ts1 = new Timestamp(new java.util.Date().getTime());
if (mGeocoderAvailable)
address = reverseGeocode(LocationService.this.location);
if(address != "" && !address.equals(lastAddress))
{
lastAddress = address;
new SendLocation(LocationService.this.id,address,ts1);
}
}
}
I don't think that the task really matters in here, it includes some conditions that I care about and the starting a new thread that sends the information to the db.
The result is: same location provides me diffrent locations while my phone is not moving with 500m as minDistance parameter.
Its because the GPS is setting itself up to be used(During this period it tries to get exact location of you), Thereby few location updates will be noticed.
Try using this in your code:-
public boolean isUsable(Location location)
{
return location!=null && location.hasAccuracy() && location.getAccuracy() < 800 && location.getSpeed() > 0;
}
This one makes sure that the processing should be done only if the speed is > 0. Now your device won't bother if its in the same place and you can use mindistance upto 100m too.

Categories

Resources