I am trying to make an Android app which takes the location data in certain intervals e.g:- 5 sec, 1 min,etc. Here is my code :-
public void onLocationChanged(Location loc) {
// TODO Auto-generated method stub
if(loc!=null)
{
//Required Interval
tInterval =(minInterval*60*1000) + (secInterval)*1000 - 1000;
//The app also supports interval mode
RadioButton sel = (RadioButton) findViewById(mode.getCheckedRadioButtonId());
//Code for Manual Functionality
if(sel.getText().equals(MANUAL_RADIO))
{
Time t = new Time();
t.setToNow();
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
locate.removeUpdates(this);
b.setText(MANUAL_BUTTON);
d.setEnabled(true);
}
//Code for Interval functionality
else if(sel.getText().equals(INTERVAL_RADIO))
{
//count is object of Countdown class which is a Thread object
if(count == null)
{
//t is a Time object
t.setToNow();
//SQLiteDatabase object for logging Location with Time
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
count = new CountDown( tInterval);
count.start();
}
else if(count.getState().toString().equals("TERMINATED"))
{
t.setToNow();
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
count = new CountDown(tInterval);
count.start();
}
}
}
}
Here is the code for the Countdown class:-
This class is used to add the interval to the app
public class CountDown extends Thread
{
long time;
public CountDown(long duration)
{
time = duration;
}
public void run()
{
long t1 = System.currentTimeMillis();
long t2 = 0;
do
{
t2 = System.currentTimeMillis();
}while(t2 - t1 < time);
}
}
The problem is that using the above code I am not getting accurate intervals. I am always getting 1 sec extra (due to which I subtracted 1000 in the formula) , but this 1 sec is not happening always. So can anyone please tell me what I am doing wrong ?
Look at LocationManager.requestLocationUpdates, just pass your time interval in parameter..
LocationManager mLocationManager = (LocationManager).getSystemService(mActivity.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, new GeoUpdateHandler());
i think here you need to use default features , no need to use Timer
NETWORK_PROVIDER
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkLocationListener);
GPS_PROVIDER
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, gpsLocationListener);
Here ,
minTime(2nd field) => minimum time interval between location updates, in milliseconds
minDistance(3rd field) => minimum distance between location updates, in meters
Documentation
I don't think the minTime param of the requestLocationUpdates(...) methods does anything at all. It does not seem to prevent distance-based updates from coming at shorter intervals, and it definitely does not cause updates to come at the specified interval, as many people seem to think. I've tried it on devices from Android 2.3.6 to 4.0.4.
Related
I try do indoor navigation android application using Estimote beacons. Here is the code which I used to get distance between android device and beacons. This code sections runs approximately in every 1 second.
I need to execute this in every 100 milliseconds.
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
runOnUiThread(new Runnable() {
#Override public void run() {
long time= System.currentTimeMillis();
Log.i("###################### ", " #################");
Log.i("Time Class ", " Time value in millisecinds "+time);
toolbar.setSubtitle("Found beacons: " + beacons.size());
ArrayList<Beacon> newBeacons = new ArrayList<>();
for (int x=0; x<beacons.size();x++) {
int major= beacons.get(x).getMajor();
int minor = beacons.get(x).getMinor();
if (major==3&&minor==3) {
newBeacons.add(beacons.get(x));
Dsi[0] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==4&&minor==4) {
newBeacons.add(beacons.get(x));
Dsi[1] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==2&&minor==2) {
newBeacons.add(beacons.get(x));
Dsi[2] = Utils.computeAccuracy(beacons.get(x));
}
}
double[][] positions = new double[][] { { -3.4, 0.8}, { 0, 7.5 }, { 6.7, 6.7 } };
double[] distances = new double[] { Dsi[0], Dsi[1], Dsi[2] };
TrilaterationFunction trilaterationFunction = new TrilaterationFunction(positions, distances);
LinearLeastSquaresSolver lSolver = new LinearLeastSquaresSolver(trilaterationFunction);
NonLinearLeastSquaresSolver nlSolver = new NonLinearLeastSquaresSolver(trilaterationFunction, new LevenbergMarquardtOptimizer());
double[] expectedPosition = new double[] { 3.3, 15.0 };
RealVector x = lSolver.solve();
Optimum optimum = nlSolver.solve();
testResults(expectedPosition, 1, optimum, x);
adapter.replaceWith(newBeacons);
time= System.currentTimeMillis();
Log.i("Time Class ", " Time value in millisecinds "+time);
Log.i("###################### ", " #################");
}
});
}
});
How do I do that?
I got the answer for this problem. Here is the answer and explanation for the Estimote Beacon users and lovers.
There is a method called setForegroundScanPeriod in the Estimote Android SDK. This method implemented in BeaconManager class. This can be used to increase or decrease scanning time period.
This is the method definition
setForegroundScanPeriod(long scanPeriodMillis,long waitTimeMillis)
First parameter for the change the scan period and second parameter for the waiting time between two scanning period. Values of all parameters are taken as milliseconds. Example as follows.
setForegroundScanPeriod(200,5)
If you called like this, Then code section is executing in every 200 milliseconds with 5 milliseconds time interval.
Default values of the method is 1s for the scan time period and 0s for the waiting period. 200ms is minimum scan time period and 0ms is minimum waiting period. (if you reduce the scanning period scanning period, Broadcasting interval of your Estimote Beacon should be reduced. Broadcasting interval should less than scan time period and also minimum Broadcasting interval is 100ms)
Reducing Broadcast interval is negatively effect for Battery life of Beacon and Reducing scan time period is negatively effect for Battery life of Android device.
Here is the full example which I used to scan Beacons.
BeaconManager beaconManager = new BeaconManager(this);
beaconManager.setForegroundScanPeriod(200,0);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
runOnUiThread(new Runnable() {
#Override public void run() {
toolbar.setSubtitle("Found beacons: " + beacons.size());
ArrayList<Beacon> newBeacons = new ArrayList<>();
for (int x=0; x<beacons.size();x++) {
int major= beacons.get(x).getMajor();
int minor = beacons.get(x).getMinor();
if (major==3&&minor==3) {
newBeacons.add(beacons.get(x));
Dsi[0] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==4&&minor==4) {
newBeacons.add(beacons.get(x));
Dsi[1] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==2&&minor==2) {
newBeacons.add(beacons.get(x));
Dsi[2] = Utils.computeAccuracy(beacons.get(x));
}
}
adapter.replaceWith(newBeacons);
}
});
}
});
I don't know why this count down counter shows a random number at the end?
I mean that it sometimes shows 60:15, sometimes 60:07, so on this way
min=sec=0;
new Thread(new Runnable() {
#Override
public void run() {
while (min < 60 && flagTime) {
try {
Thread.sleep(1);
G.HANDLER.post(new Runnable() {
#Override
public void run() {
String preSec="";
String preMin="";
if (sec < 59) {
sec += 1;
}
if (sec < 10) {
preSec = "0";
}
if (min < 10) {
preMin = "0";
}
score =preMin + min + ":"
+ preSec + sec;
txt[elementNumber + 1].setText(score);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
Please someone tell me why it works so weird?
Timing in ALL OSes is NOT precise, unless you use a framework or tools that is already designed for this task. You can however work with Thread.Sleep with a reasonable uncertainty. But for "reasonable" and "precise" timing, it depends on the problem you are trying to solve.
In threads, sleep(1000) does not mean that the thread will sleep exactly 1 second, so that the thread will sleep less or more every time you run your app. that is why you get random results.
This has many things else to consider like the priority of the thread.
so a better way to count down is to use other ways which is provided by android:
CountDownTimer
Timer
you may check on google and you will find many examples about how to use them.
those are more reliable and more precise.
hope this helps.
The likely reason that you're getting weird results in your TextView is that you're updating it from a thread that is not the main UI thread.
But you're making this harder than it needs to be. An easier approach would be to use a simple CountDownTimer object like this:
final long SECS_IN_1_MIN = 60;
final long MILLIS_IN_1_SEC = 1000;
final long MILLIS_IN_60_MINS = 3600000;
final TextView timer = (TextView) findViewById(R.id.timer);
new CountDownTimer(MILLIS_IN_60_MINS, MILLIS_IN_1_SEC) {
public void onTick(long millisUntilFinished) {
if (flagTime) {
long secs = (MILLIS_IN_60_MINS - millisUntilFinished) / MILLIS_IN_1_SEC;
timer.setText(String.format("%02d:%02d", secs / SECS_IN_1_MIN, secs % SECS_IN_1_MIN));
} else {
timer.setText("cancelled");
cancel();
}
}
public void onFinish() {
timer.setText("time expired");
}
}.start();
Edit: It uses a CountDownTimer to handle the timing, while using its millisUntilFinished value to calculate and display what appears to be an increasing seconds count. I threw in some symbolic names to make the code clearer and a String.format to handle single digit values in a more elegant fashion. Enjoy!
I have the following code in my main activity (Note: GPSTracker in this application works):
double latitude, longitude;
gps = new GPSTracker(MainActivity.this);
if(gps.canGetLocation()){
latitude = gps.getLatitude();
longitude = gps.getLongitude();
Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
}
else{
gps.showSettingsAlert();
}
I want to create a loop, which would display in some time intervals Toast with my current position. I´ve tried this:
double latitude, longitude;
long currentTime = System.currentTimeMillis();
long myTimestamp = currentTime;
int i = 0;
gps = new GPSTracker(MainActivity.this);
while(i < 5)
{
myTimestamp = System.currentTimeMillis();
if((myTimestamp - currentTime) > 5000)
{
i++;
currentTime = System.currentTimeMillis();
if(gps.canGetLocation()){
latitude = gps.getLatitude();
longitude = gps.getLongitude();
Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
}else{
gps.showSettingsAlert();
}
}
}
With this code, Toast is shown only one time (the last iteration). Could you help me with this? Thanks in advance.
I want it to be shown every iteration (for example every 5 seconds).
The code above doesn't loop every five seconds, it loops continuously but only increments your counter every five seconds... This is a very inefficient way of creating a time delay because nothing else can happen while the loop runs. (Even if you run this on a separate thread it is still not good tactic.)
Instead use LocationManager's requestLocationUpdates which will use callbacks so your app can do things between updates. A couple quick notes:
Understand that the GPS may not be able to get a fix every five seconds and that this interval is really short so use it sparingly or you'll run the battery down.
Some pre-Jelly Bean devices may not observe the minTime parameter, but you can enforce your time parameter yourself as I describe in Android Location Listener call very often.
All that aside, you use your existing code but I recommend a Handler and Runnable, like this:
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Fetch your location here
// Run the code again in about 5 seconds
handler.postDelayed(this, 5000);
}
}, 5000);
One problem is that this method does a 'busy-wait', which, I suspect, prevents the toast from being displayed. Try doing a sleep() to wait until it's time for the next Toast:
public void sleepForMs(long sleepTimeMs) {
Date now = new Date();
Date wakeAt = new Date(now.getTime() + sleepTimeMs);
while (now.before(wakeAt)) {
try {
long msToSleep = wakeAt.getTime() - now.getTime();
Thread.sleep(msToSleep);
} catch (InterruptedException e) {
}
now = new Date();
}
}
I am trying to run AsyncTask every 1 minute, by using handler,but it doesn't work:(
In AsyncTask I am reading data from Sqlite DB and drawing result in mapview, aim of doing like that is another service updating my Sqlite every 1 min by taking real data from server and i want keep mapview updated too.
Is there any possible way of calling AsyncTask every minute rather than using Handler?
public Runnable getData;
private final Handler _handler = new Handler();
private static int DATA_INTERVAL = 60 * 1000;
getData = new Runnable()
{
public void run()
{
getDataFrame();
}
private void getDataFrame() {
// TODO Auto-generated method stub
_handler.postDelayed(MapViewActivity.this.getData, DATA_INTERVAL);
new DrawFromDataTask();
}
};
DrawFromDataTask is described below:
private class DrawFromDataTask extends AsyncTask<Void, Integer, FriendItemizedOverlay> {
#Override
protected FriendItemizedOverlay doInBackground(Void... params) {
// TODO Auto-generated method stub
mDbAdapter.open();
List<Refresher> nearFriends = mDbAdapter.getAllRecords();
for(Refresher friend : nearFriends)
{
double lat = Double.parseDouble(friend.Latitude);
double lon = Double.parseDouble(friend.Longitude);
OverlayItem item = new OverlayItem(new GeoPoint((int)(lat * 1000000),
(int)(lon* 1000000)),
"" + friend.name,
"" + friend.type);
mFriendOverlay.addOverlay(item);
}
return mFriendOverlay;
}
protected void onProgressUpdate(Integer... progress) {
setProgress(progress[0]);
}
protected void onPostExecute(FriendItemizedOverlay result) {
System.out.println("in AsyncTask execution!");
Location loc = get_location();
final double mLatitude = loc.getLatitude();
final double mLongitude = loc.getLongitude();
// get the last location from the database
GeoPoint lastLocation = new GeoPoint(
(int) (mLatitude * 1E6),
(int) (mLongitude * 1E6));
Drawable marker = getResources().getDrawable(R.drawable.arrow);
int amountOFplayers = result.size()-1;
for (int j=0; j<amountOFplayers; j++) {
result.getItem(amountOFplayers).setMarker(marker);
}
//System.out.println("Number of overlays -- "+amountOFplayers);
mMapView.postInvalidate();
//mMapView.invalidate();
// animate to last location
mMapController.animateTo(lastLocation);
// zoom to the required level
mMapController.setZoom(ZOOM_LEVEL);
}
}
Use the broadcast intent that runs on minute tick and then just execute the Async task. It is more accurate.
http://developer.android.com/reference/android/content/Intent.html#ACTION_TIME_TICK
Make sure you create new instance every time, since the thread object cannot be reused/relaunched unless you create new instance.
http://developer.android.com/guide/components/processes-and-threads.html
Just use a Timer, TimerTask and run in a fixed rate scheduleAtFixedRate()
Instead of using a service to poll the server every one minute, why dont you use Google Cloud Messaging for android(previously C2DM).. In that way you can send some notification to your app that yes data is changed on the server, which then leads you to change some data in your db if needed ,and then start the thread.
But yes I sincerely dont have any idea about your actual requirements
i have a situation where i need to use GPS technique.
i need to find the distance between two points when the person is walking.
When the person starts walking he will click on Start button and when he stops he clicks on stop button
after this it should show him
1.time taken
2.Distance travelled in Kms.
3.from where to where(places name) eg: a to b
Do i need to have google maps for this?
I saw the code here link to get the current location which gives me latitude longitude.
please help how to go with this
**
Edited:
**
This is the code i am using
private EditText editTextShowLocation;
private Button buttonGetLocation;
private ProgressBar progress;
private LocationManager locManager;
private LocationListener locListener = new MyLocationListener();
private boolean gps_enabled = false;
private boolean network_enabled = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
editTextShowLocation = (EditText) findViewById(R.id.editTextShowLocation);
progress = (ProgressBar) findViewById(R.id.progressBar1);
progress.setVisibility(View.GONE);
buttonGetLocation = (Button) findViewById(R.id.buttonGetLocation);
buttonGetLocation.setOnClickListener(this);
locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
}
#Override
public void onClick(View v) {
progress.setVisibility(View.VISIBLE);
// exceptions will be thrown if provider is not permitted.
try {
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
// don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled) {
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("Attention!");
builder.setMessage("Sorry, location is not determined. Please enable location providers");
builder.setPositiveButton("OK", this);
builder.setNeutralButton("Cancel", this);
builder.create().show();
progress.setVisibility(View.GONE);
}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
}
}
class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
// This needs to stop getting the location data and save the battery power.
locManager.removeUpdates(locListener);
String londitude = "Londitude: " + location.getLongitude();
String latitude = "Latitude: " + location.getLatitude();
String altitiude = "Altitiude: " + location.getAltitude();
String accuracy = "Accuracy: " + location.getAccuracy();
String time = "Time: " + location.getTime();
editTextShowLocation.setText(londitude + "\n" + latitude + "\n" + altitiude + "\n" + accuracy + "\n" + time);
progress.setVisibility(View.GONE);
}
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == DialogInterface.BUTTON_NEUTRAL){
editTextShowLocation.setText("Sorry, location is not determined. To fix this please enable location providers");
}else if (which == DialogInterface.BUTTON_POSITIVE) {
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
}
It is showing the Logitude Latitude which i am entering from emulator control.
In this i am manually entering the details of longitude and latitude
by going to window->showview->other->emulator control for testing in the emulator
but what i need is i will have two edittext where i enter the place name(A) and (B)
it should give me the distance
please help
try using Google Distance Matrix Api
https://developers.google.com/maps/documentation/distancematrix/
You can use currentTimeinMillis() to get your start and end time for your journey.
You can then use the formulas explained here to find the distance and lastly you will have to use a reverse geocoding service such as Nominatim to be able to get the address of a place from your GPS coordinates.
That being said, the distance formula will get you the distance between one point and the next, not the actual displacement. If this is not what you need, but rather you want the actual distance travelled you will need to calculate this value at a shorter interval.
You can find out the distance between two locations(in terms of latitude and longitude) by making use of Spherical Trigonometry
Coming to time make use of simple date objects and compare the startTime and endTime.
(OR)
You can get approximate distance using below code
double distance;
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
For getting the distance between 2points(A to B) there is a function called distanceTo in android.
For e.g.
double distance = startLocation.distanceTo(finishLocation)/1000;
For time taken as npinti said you can use currentTimeinMillis() or you can also use Timer and show it to user when he clicks on start button. Its just like stopwatch.
Edited
Place A - New York
Place B - Paris
In this case you first need to convert the string into Location(i.e you need latitude & longitude). For that you have use the concept of Geocoding.
List<Address> foundGeocode = null;
foundGeocode = new Geocoder(this).getFromLocationName("address here", 1);
foundGeocode.get(0).getLatitude(); //getting latitude
foundGeocode.get(0).getLongitude();//getting longitude
After that you can calculate the distance from the distanceTo method.
Hope this will help....
I suppose the question is one of walking..
Are you walking on the streets, or as the crow flies?
If it's streets, and your connected to the net, use google's api.. It calculates routing based on two points and returns XML.. Should be easy enough to figure out.
If it's crow flies.. well then, just do (a*a) + (b*b) = (c*c) this is by far the easier..
You could have your user tap for major turns.. Or you could keep a runnable running every 10 seconds from when they hit start, and plot the points. Still a*a+b*b=c*c but just a bunch of steps.
Of course you'd have to run it in a service.. And given the choice I'd go with that option. You could adjust the cycle time based on speed traveled. Faster would be smaller pauses.
It requires less on your dataplan.
EDIT
Ah.. I see what you're looking for. Tis not what I thought you were asking for.
Simplify.. convert lat/long to GPS. and then do simple math on the last point stored
void addDistance()
{
newX = ...
newY = ...
deltaX = absolute(m_oldX - newX)
deltaY = absolute(m_oldY = newY)
m_distance += sqrt(deltaX^2 + deltaY^2);
m_oldX = newX;
m_oldY = newY;
}
void startOver()
{
newX = ...
newY = ...
m_distance = 0;
m_oldX = newX;
m_oldY = newY;
}