I'm trying to have GPS coordinates sent to a text message. This code works, but every time the GPS updates location, it tries to send a new text message. I can't figure out how to stop the location updates. This is what I have currently...I realize it may not be the most efficient way to do it.
Any help would be appreciated!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}
public void GPSDisable() {
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.removeUpdates(mlocListener);
}
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
double latitude = loc.getLatitude();
double longitude = loc.getLongitude();
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", "5555555555");
smsIntent.putExtra("sms_body", "Location:"+latitude+","+longitude);
GPSDisable();
startActivity(smsIntent);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
#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 onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#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
}
}
I would set two global variables latitude and longitude.
This variables would be updated every onLocationChanged. You cannot change this comportament, but you can get out from there the sending of sms.
I would send the sms on a timer after 5 seconds let's say.
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", "5555555555");
smsIntent.putExtra("sms_body", "Location:"+latitude+","+longitude);
startActivity(smsIntent);
}
},
5000 );
And your onlocation changed could look like this
#Override
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
First I would advise you to have a look at this article.
Having said this, generally you should "unsubscribe" from the location manager when you do not need any more updates. Typically, you subscribe for location updates in "onCreate" and unsubscribe in "onDestroy" when you need updates for as long as your Activity is 'alive'.
Even better is to subscribe/unsubscribe when your activity is getting visible or hidden respectively (via "onResume"/"onPause" respectively). Have a look here for details on the Activity's lifecycle.
Now, about your specific problem, it is not clear what is your desired behavior. Do you want to send an SMS message every time the location changes? Or only when some time passes?
Assuming what you need is to send SMS whenever your location changes but not too often, I would suggest the following:
1. Register for location updates in "onResume" and unregister in "onPause".
2. Maintain some local variables that tell you which was the last time you sent an SMS message and what were the coordinates in it. These variables should probably persist Activity lifecycle events (e.g. when the Activity is destroyed, you should "store" these values, and restore them when you recreate it).
3. Whenever there is a new location update, check if it is too soon or too close (compared to the previous SMS) and if not send another message, updating the variables.
Having said these, please note that this will work for as long as your Activity is visible. If you need a similar functionality that does not require you to keep the Activity visible, I would suggest you use a BroadcastReceiver.
Related
I use the following code to get Current Location from a Network provider in my application:
LocationManager mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean network_enabled = mgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(network_enabled){
Location location = mgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
But it gives a location approximately 300-700 meters away from my actual location.
This is expected from a Network provider. But the problem is:
with only this Network provider enabled, and no GPS, I openned Foursquare
application where it shows my current location exactly where I am. Now
when I come back to my application, it shows the accurate current
location or say the same location which Foursquare showed.
Same thing happens with Google apps like Navigator, Maps etc..,
How can this be done? How are other apps able to get the exact location, based on just the Network provider?
Complete Code:
public class MyLocationActivity extends Activity implements LocationListener {
private LocationManager mgr;
private String best;
Location location;
public static double myLocationLatitude;
public static double myLocationLongitude;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
best = mgr.getBestProvider(criteria, true);
location = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
dumpLocation(location);
}
public void onLocationChanged(Location location) {
dumpLocation(location);
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
protected void onPause() {
super.onPause();
mgr.removeUpdates(this);
}
#Override
protected void onResume() {
super.onResume();
mgr.requestLocationUpdates(best, 15000, 10, this);
}
private void dumpLocation(Location l) {
if (l != null){
myLocationLatitude = l.getLatitude();
myLocationLongitude = l.getLongitude();
}
}
}
Thank You
You are getting just the last known location. You should request location updates from the LocationManager. Use LocationManager.getLocationUpdates.
On your LocationListener on the onLocationChanged(Location location) method, you can check on the Location object, how accurate this location is, like this :
float accuracy=location.getAccuracy();
then, if this Location is accurate enough for you, you can stop receiving location updates from the LocationManager using removeUpdates() , and use the received Location. If the Location is not accurate enough, you can wait for a more precise Location, and stop the updates latter on.
I am using the routine requestSingleUpdate() reoutine of the android LocationManager library with a LocationListener. The functionality I am trying to implement is that the user can press a button and the app will get their current location and perform reverse geocoding to get the approximate address.
My problem is that depending on the network situation of the device, getting a location fix may take a long time. How can I implement a timeout that will cause my 'requestSingleUpdate()' to give up and tell the user to find out their own bloody address?
my code:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
locationManager.requestSingleUpdate(criteria, new LocationListener(){
#Override
public void onLocationChanged(Location location) {
// reverse geo-code location
}
#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
}
}, null);
LocationManager doesn't seem to have a timeout mechanism. But LocationManager does have a method named removeUpdates(LocationListener listener) which you can use to cancel any callbacks on the specified LocationListener.
So, you could implement your own timeout with something like the following pseudo-code:
final LocationManager locationManager
= (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// ...
final LocationListener myListener = new LocationListener() {
//... your LocationListener's methods, as above
}
Looper myLooper = Looper.myLooper();
locationManager.requestSingleUpdate(criteria, myListener, myLooper);
final Handler myHandler = new Handler(myLooper);
myHandler.postDelayed(new Runnable() {
public void run() {
locationManager.removeUpdates(myListener);
}
}, MY_TIMEOUT_IN_MS);
I'm not certain what happens if you call locationManager.removeUpdates(myListener) after you get the Location. You might want to check for that before you call removeUpdates. Or, you could add something like this to the onLocationChanged method in your callback (and possibly to the other methods as well) :
myHandler.removeCallbacks(myRunnable); // where myRunnable == the above Runnable
I've an app that gets the user's location. I've registered the locationManager and listener in oncreate(). I've requested and removed updates in onResume() and onPause() respectively. The app finds the location and calls the getTime() on the loc object of onLocationChanged, this is to get an external time and then later compare to system time. This time is set in an applicationObject so that it's available app-wide. Everything works fine and i toast the time to the user from the applicationObject time setter method.
What i'm finding is that when i have found the time by getting a fix on the user's location, and i move to the next activity, the app continues to get the time for another 20 secs and sometimes more.
How can this be when i have unregistered the locaction listener in the first activity's onPause() method?
#Override
protected void onPause() {
mlocManager.removeUpdates(mlocListener);
super.onPause();
}
#Override
protected void onResume() {
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
super.onResume();
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
Log.e(TAG, "external time = " + loc.getTime());
DateTime dt = new DateTime(loc.getTime());
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "formatted ext time = " + formattedNowTime3);
nfcscannerapplication.setExternalTime(dt);
}
#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
}
}//end of MyLocationListener
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.entryscreen);
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
.
The onPause() may be called only after the new activity has started.
If you only want a single onLocationChange(), you can use requestSingleUpdate() and your problem is gone.
Regards.
Set mlocListener to null just after removeUpdates();
i'm new in java/android app and i'm creating an app that uses user-location. I want the location to be updated at the begining of the app.
The problem is that my location class is an activity and i don't want to show another contentview for this class.
Actually, i want the location thing to be done in background, without changing the UI, in a separated class.
Is it possible? How?
Thanks :P
There is no need to put the location in a different activity, the LocationManager already does it in the background:
public void getLocation(){
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
gpsLocationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
//do something with the new location
if (location != null)
gpsLocation = location;
}
};
gpsLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 0, gpsLocationListener);
}
Using the LocationManager you should be able to use what ever kind of activity (or service) you want.
i want to make application like this :
User clicks the button
The application show the user's coordinates (Latitude and Longitude)
i'm following the steps here
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
double glat = location.getLatitude();
double glong = location.getLongitude();
Toast.makeText(getApplicationContext(), "Your position\n"+glat+"\n"+glong, Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
how to implement it to button click event?
if the user clicks the button, the toast appear showing the position :)
UPDATE
I implement it using startActivityForResult() but the result is empty or null
here's my code :
this is the code on the button that i want to click
btn_obj_useKor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(getApplicationContext(), MyLocationListener.class);
startActivityForResult(intent, 0);
}
});
and this is my MyLocationListener class :
public class MyLocationListener extends Activity{
Intent intent;
String output = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
double glat = location.getLatitude();
double glong = location.getLongitude();
output = glat+","+glong;
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
intent.putExtra("returnedData", output);
setResult(RESULT_OK, intent);
finish();
}
}
When i click the button it showing WTF! that means the result is null or empty.
what's the problem and what should i do then?
It wont return a result immediately since it takes time for the GPS provider to start and find your location. This is why you listen for a callback event.
Currently your code is listening for the network location, which is not very accurate. Change the LocationManager to GPS_Provider (on your last line) to use GPS if it is enabled.
Responding to an onClick is a user event, the LocationListener onLocationChanged is also an event. If you trigger the user event before the LocationListener event, there will be no position available to display.
My suggestion is to call startActivityForResult on another activity in the button onClick handler, the 2nd activity has all the LocationManager & LocationListener code in it, in the onLocationChanged event handler you pass the position back to the 1st activity.