LocationListener InSide AsyncTask - android

Hi I am New to android programming and currently developing an application that uses location manager to get user location and place a marker on a map. i am attempting to use AsyncTask to run the LocationListener and Constantly update the marker when the user location has changed.
this is the class i am working on...
public class IncidentActivity extends MapActivity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
this.setContentView(R.layout.incidentactivity);
mapView = (MapView)findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
mapView.setTraffic(true);
mapController = mapView.getController();
String coordinates[] = {"-26.167004","27.965505"};
double lat = Double.parseDouble(coordinates[0]);
double lng = Double.parseDouble(coordinates[1]);
geoPoint = new GeoPoint((int)(lat*1E6), (int)(lng*1E6));
mapController.animateTo(geoPoint);
mapController.setZoom(16);
mapView.invalidate();
new MyLocationAsyncTask().execute();
}
private class MyLocationAsyncTask extends AsyncTask<Void, Location, Void> implements LocationListener{
private double latLocation;
private Location l;
//location management variables to track and maintain user location
protected LocationManager locationManager;
protected LocationListener locationListener;
#Override
protected Void doInBackground(Void... arg0) {
Looper.prepare();
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, locationListener);
this.publishProgress(l);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Location... values) {
super.onProgressUpdate(values);
}
//this method is never executed i dont know why...?
public void onLocationChanged(Location location) {
if (location != null){
latLocation = location.getLatitude();
Toast.makeText(getBaseContext(), " Your latLocation :" + latLocation, Toast.LENGTH_LONG).show();
//Log.d("Your Location", ""+latLocation);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
}

I've just implemented such AsyncTask:
class GetPositionTask extends AsyncTask<Void, Void, Location> implements LocationListener
{
final long TWO_MINUTES = 2*60*1000;
private Location location;
private LocationManager lm;
protected void onPreExecute()
{
// Configure location manager - I'm using just the network provider in this example
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
nearProgress.setVisibility(View.VISIBLE);
}
protected Location doInBackground(Void... params)
{
// Try to use the last known position
Location lastLocation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// If it's too old, get a new one by location manager
if (System.currentTimeMillis() - lastLocation.getTime() > TWO_MINUTES)
{
while (location == null)
try { Thread.sleep(100); } catch (Exception ex) {}
return location;
}
return lastLocation;
}
protected void onPostExecute(Location location)
{
nearProgress.setVisibility(View.GONE);
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.removeUpdates(this);
// HERE USE THE LOCATION
}
#Override
public void onLocationChanged(Location newLocation)
{
location = newLocation;
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
}

From what I have read and tried, you cannot use a looper (which is needed by the locationlistener), inside an ASyncTask. Click Here
Actually it mean the two threading models are not compatible, so you can't
use these together. Looper expects to to own the thread that you associate
it with, while AsyncTask owns the thread it creates for you to run in the
background. They thus conflict with each other, and can't be used together.
Dianne Hackborn suggested using a HandlerThread, but I succeeded in getting mine to work inside of an IntentService. I will admit that my code is still a bit of a hack.

Related

Get GPS location in AsyncTask

I have an AsyncTask class that needs to get user's location when this AsyncTask is called.
The idea is to check if location service is enabled or not, if not, the location service toggle will popup for user to turn it on, then it will go back to the task to continue getting the location and finish the job.
However, the code below show NullPointerException on the line lat = location.getLatitude(); near the end of onPreExecute(). They said because getLastKnownLocation gets nothing as it's just been turned on a moment ago, then how can I get the location right after the location service has been turned on?
LocationManager locationManager;
LocationListener locationListener;
double lat;
double longi;
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
location = new Location(LocationManager.NETWORK_PROVIDER);
locationManager = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);
if (!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
//I copy the part below from the internet but seems like "onProviderDisabled" and "onLocationChanged" were never be called
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.v("GPS CHECKKKKKKK",location.getLatitude()+"_"+location.getLongitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
};
locationManager.requestLocationUpdates("gps", 500, 0, locationListener);
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,5000,0, locationListener);
lat = location.getLatitude();
longi= location.getLongitude();
Log.v("GPS Cord CHECK",lat+"_"+longi);
}
#Override
protected String doInBackground(final Checkout_Package... params) {
//Doing the job that needs lat and longi value!
}
Thank you for your time!
You cannot create and put a location listener in onPreExecute() because the onChanged handlers will only be invoked much later when onPostExecute or even your AsyncTask has finished.
What you should do instead is start an AsyncTask in that location changed handler.
So in onLocationChanged().
With greenapps's suggest I figured it out. I put the code into the button that call the AsyncTask
checkout_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LocationManager locationManager;
LocationListener locationListener;
gotit = false; //Boolean to start the AsyncTask only once.
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.v("GPS CHECKKKKKKK",location.getLatitude()+"_"+location.getLongitude());
lat = location.getLatitude();
longi = location.getLongitude();
if (gotit == false) {
new Checkout_Async(Checkout.this, listener).execute(new Checkout_Package(user, product_all, getTotalCost(product_all), fee, getTotalCost(product_all) + fee, lat, longi));
gotit = true;
pd.dismiss();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
};
pd=ProgressDialog.show(Checkout.this,"",getResources().getString(R.string.please_wait),false);
locationManager.requestLocationUpdates("gps",50,0,locationListener);
}
});
Now it works. Thank you!

Arcgis : how to get device location

Hie i tried to implement this codes in my application but it doesnt work , i dont know where i went wrong.
basically, when i launch the sample of the device location. it doesnt show me where is my current location and i dont see any blue dots that resembles the current location i am at.
the only thing that i see is the map . just a plain zoom out map.
I would be really thankful if someone who could help me out on how to get the current location with the blue dots that is displayed on the map..
this is my MainActivity.class
public class HelloWorld extends Activity {
MapView mMapView = null;
ArcGISTiledMapServiceLayer tileLayer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Retrieve the map and initial extent from XML layout
mMapView = (MapView) findViewById(R.id.map);
mMapView.addLayer(new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"));
mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {
public void onStatusChanged(Object source, STATUS status) {
if (source == mMapView && status == STATUS.INITIALIZED) {
LocationService ls = mMapView.getLocationService();
ls.setAutoPan(false);
ls.start();
}
}
});
}
protected void onPause() {
super.onPause();
mMapView.pause();
}
#Override
protected void onResume() {
super.onResume();
mMapView.unpause();
}
}
this is a code that draws my location every 1 second via provider and GPS .
let's first declare variables :
private GraphicsLayer myGraphicalLayer;
MapView mMapView;
ArcGISLocalTiledLayer baseLayer;
private LocationManager mlocManager;
private LocationListener mlocListener;
in onCreate function WE CALL LocationListener:
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mlocListener);
mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, mlocListener);
// loading the map
mMapView = (MapView) findViewById(R.id.localMap);
baseLayer = new ArcGISLocalTiledLayer(basemapurl);
mMapView.addLayer(baseLayer);
// defining my position layer
myGraphicalLayer = new GraphicsLayer();
then a function to draw my location :
private void SetMyLocationPoint(final double x, final double y) {
PictureMarkerSymbol myPin = new PictureMarkerSymbol(getResources().getDrawable(
R.drawable.mylocation_icon));
Point wgspoint = new Point(x, y);
Point mapPoint = (Point) GeometryEngine.project(wgspoint, SpatialReference.create(4326),
mMapView.getSpatialReference());
Graphic myPinGraphic = new Graphic(mapPoint, myPin);
try {
myGraphicalLayer.removeAll();
} catch (Exception e) {
e.printStackTrace();
}
myGraphicalLayer.addGraphic(myPinGraphic);
myGraphicalLayer.setVisible(true);
mMapView.addLayer(myGraphicalLayer);
}
make internal class that implements MyLocationListener to get you instant location, and let it call the function named SetMyLocationPoint like this way :
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
SetMyLocationPoint(loc.getLongitude(), loc.getLatitude());
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(getApplicationContext(), "provider enabled", Toast.LENGTH_SHORT)
.show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(getApplicationContext(), "provider disabled", Toast.LENGTH_SHORT)
.show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
You need to use your own location manager or the location client to get the device's current location and then you will have to add that point on the map.
Your map should be in a MapFragment.
Get the googleMap object from the fragment and then add your custom blue dot on it.
LocationManager locationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
5000, 5, listener);
}
private LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
Log.e("Google", "Location Changed");
if (location == null)
return;
Log.e("latitude", location.getLatitude() + "");
Log.e("longitude", location.getLongitude() + "");
}
}
#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
}
};
The above code gets you the location in onLocationChanged method.
Note: i have used GPS_PROVIDER to get the location.
There are other ways to get the current location too.

Problems with getting GPS coordinates using AsyncTask

I have tried to get this code sorted couple of times. Here’s the scenario I have tried so far…
Scenario:
Once the activity is started I want to get the coordinates (long & lat) based on network/gps provider. This should run in background and it should keep checking until long & lat is not null or “0.0”. Thus, I have tried the following code with AsyncTask and thereby using LocationListener in doInBackground method.
Source Code:
public class GetLocation extends AsyncTask<String, String, String>
{
private myTest test;
boolean running =true;
private Context cont;
String addressString;
public GetLocation(myTest fr, Context contxt)
{
test = fr;
cont = contxt;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result)
{
test.GetContent();
}
#Override
protected String doInBackground(String... params) {
Looper.myLooper().prepare();
LocationManager locationManager;
locationManager = (LocationManager) cont
.getSystemService(Context.LOCATION_SERVICE);
Criteria crta = new Criteria();
crta.setAccuracy(Criteria.ACCURACY_FINE);
crta.setAltitudeRequired(false);
crta.setBearingRequired(false);
crta.setCostAllowed(true);
crta.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationManager.getBestProvider(crta, true);
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
};
locationManager.requestLocationUpdates(provider, 0, 0,
locationListener);
Looper.loop();
return addressString;
}
private void updateWithNewLocation(Location location) {
Constants.lat = Double.toString(location.getLatitude());
Constants.long = Double.toString(location.getLongitude());
}
}
Problem:
However, I also know that Looper’s can help to keep the thread active. I want to be able to get valid coordinates and this should loop until its received. How do i call to get the locations over and over again until valid one's are received? (I could put conditions within the loops i have provided but im not aware as to how and what methods i should call to achieve this). Please provide a code snippet if possible.
Cheers!
You have implemented this wrong. There is no need to create the AsyncTask. The LocationManager will asynchronously fetch locations for you and deliver them on your LocationListener.onLocationChanged. Once you get a proper Location you can call LocationManager.removeUpdates() and this will stop for further delivery of Locations.
Do not use AsyncTask for this. You just registered the LocationManager that is listen by LocationListener and use progressbar for that. Once call LocationListner.onLocationChanged try to get Lat and Long and dismiss the progress bar. OnLocationChanged will be call at you move your device for a short distance.

Android: using LocationManager and provider

I am new to android and was trying out stuff on my android emulator. While playing with the location manager and location listener, I could test the code of changing location using the emulator. The locationlistener catches the location change and moves to the specific location.
I now want to replicate the same test using my program, i.e. pass new coordinates every x seconds (may be through a thread ?) to the locationlistener, but through my program and not the emulator.
Can someone please suggest a way to go about implementing this functionality ?
The code for location listener that I found somewhere on the net and was trying:
private LocationListener locationListener;
private MapView mapView;
private MapController mc;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gps);
lm = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
lm.requestLocationUpdates(
LocationManager.GPS_PROVIDER,0,0,locationListener);
mapView = (MapView) findViewById(R.id.mpview);
mc = mapView.getController();
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location locn) {
if (locn != null) {
GeoPoint point = new GeoPoint(
(int) (locn.getLatitude() * 1E6),
(int) (locn.getLongitude() * 1E6));
mc.animateTo(point);
mapView.invalidate();
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
}
Thanks!

Fake location using GPS in android

Hi am developing an app that will set the coordinates(latitude and longitude). And it has to show my location as i am at that coordinates..It is similar to location spoofer.. http://www.androidzoom.com/android_applications/tools/location-spoofer_gkmc.html
But I am failing to do that.. here is my code..Please any one help me.
public class Mock extends MapActivity
{
private LocationManager lm;
private LocationListener locationListener;
private MapView mapView;
String mocLocationProvider;
private MapController mc;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//---use the LocationManager class to obtain GPS locations---
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
mocLocationProvider=LocationManager.GPS_PROVIDER;
lm.addTestProvider(mocLocationProvider, false, false,false, false, true, true, true, 0, 5);
lm.setTestProviderEnabled(mocLocationProvider,true);
lm.requestLocationUpdates(mocLocationProvider,0,0,locationListener);
mapView = (MapView) findViewById(R.id.mapview1);
mc = mapView.getController();
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location loc) {
loc = new Location(mocLocationProvider);
Double latitude = 1.352566007;
Double longitude = 103.78921587;
//Double altitude = Double.valueOf(parts[2]);
loc.setLatitude(latitude);
loc.setLongitude(longitude);
loc.setTime(System.currentTimeMillis());
lm.setTestProviderLocation(mocLocationProvider, loc);
mc.setZoom(16);
mapView.invalidate();
}
#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 use this method http://developer.android.com/guide/developing/tools/ddms.html#emulator-control. Haven't tried this one: http://code.google.com/p/android/issues/detail?id=915
You basically set the coordinates on real device in the same way you do in the emulator by using DDMS in Eclipse.
Just make sure you enable "fake locations" in your device. You can find the setting at Settings > Applications > Development > Allow mock locations.

Categories

Resources