0

What am i trying to do is to get the GPS location from 2 providers, the first one is the GPS which is the most accurate, the second one is the aGPS which is a combination of GPS and network. I am doing that because aGPS can get location even in tall buildings when normal gps takes more time to get. What i want is to try getting location from the first provider(GPS) for 10 seconds, if in those 10 seconds i get a location!=null, i break the timed loop and take the result to the main thread, which is the main activity. ELSE ill take the location from the second provider(aGPS) if available. If none of the provider where able to get a location, i will return null after the 10 seconds. The problem i am facing is, when i do a timed loop, the app freezes for 10 seconds so im not able to get the location to the main activity.

Here i am trying to get the location on the HomeActivity class that extends Activity:

Button btnRedCross = (Button) this.findViewById(R.id.btnRedCross);
        btnRedCross.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                OutRequestsDatabaseHandler db =new OutRequestsDatabaseHandler();
                OutRequest outreq = new OutRequest();
                outreq.setName("Red Cross");
                //TODO get the message from LocalUser db
                Calendar cal = Calendar.getInstance();
                outreq.setDate(cal.getTimeInMillis());
                outreq.setMessage("My Message");
                outreq.setType("RedCross");
                //outreq.setLongitude(12.123456);
                //outreq.setLatitude(12.123456);
                db.addOutRequest(HomeActivity.this, outreq);
                //HERE I AM TRYING TO GET THE LOCATION
                GPSTracker locationtracker=new GPSTracker(HomeActivity.this);
                location=locationtracker.getLocation();
                Log.i("LocationGetter","Result: Longitude:"+location[0]+" Latitude:"+location[1]);
            }
        });
    }

This is the GPSTracker Class where the 2 providers try to get location:

public class GPSTracker{
    Context con;
    LocationManager locMgr;
    private double longgps;
    private double latgps;
    private double longnetwork;
    private double latnetwork;
    private LocationListener gpsLocationListener;
    private LocationListener networkLocationListener;
    public GPSTracker(final Context context){
        con = context;
        locMgr = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);
        LocationProvider high = locMgr.getProvider(locMgr.getBestProvider(
                createFineCriteria(), true));
        LocationProvider low = locMgr.getProvider(locMgr.getBestProvider(
                createCoarseCriteria(), true));
        //GET LOCATION FROM GPS
         gpsLocationListener = new LocationListener() {

            @Override
            public void onStatusChanged(String provider, int status,
                    Bundle extras) {
            }

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onProviderDisabled(String provider) {
                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                        context);
                alertDialogBuilder
                        .setMessage(
                                "Please Enable GPS and Network For Accurate Result")
                        .setCancelable(false)
                        .setPositiveButton("Enable GPS",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,
                                            int id) {
                                        Intent callGPSSettingIntent = new Intent(
                                                android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                        context.startActivity(callGPSSettingIntent);
                                    }
                                });
                alertDialogBuilder.setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = alertDialogBuilder.create();
                alert.show();
            }

            @Override
            public void onLocationChanged(Location location) {
                longgps = location.getLongitude();
                latgps = location.getLatitude();
                //Log.i("LocationGetter", "GPS: Longitude:" + longgps+ " Latitude:" + latgps);

            }
        };
        locMgr.requestLocationUpdates(high.getName(), 0, 0f,gpsLocationListener);
        //GET LOCATION FROM GPS + NETWORK
        networkLocationListener=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) {
                longnetwork = location.getLongitude();
                latnetwork = location.getLatitude();
                //Log.i("LocationGetter", "Network: Longitude:"+ longnetwork + " Latitude:" + latnetwork);

            }
        };
        locMgr.requestLocationUpdates(low.getName(), 0, 0f,networkLocationListener);
    }

    public static Criteria createFineCriteria() {

        Criteria c = new Criteria();
        c.setAccuracy(Criteria.ACCURACY_FINE);
        c.setAltitudeRequired(false);
        c.setBearingRequired(false);
        c.setSpeedRequired(false);
        c.setCostAllowed(true);
        c.setPowerRequirement(Criteria.POWER_HIGH);
        return c;

    }

    public static Criteria createCoarseCriteria() {

        Criteria c = new Criteria();
        c.setAccuracy(Criteria.ACCURACY_COARSE);
        c.setAltitudeRequired(false);
        c.setBearingRequired(false);
        c.setSpeedRequired(false);
        c.setCostAllowed(true);
        c.setPowerRequirement(Criteria.POWER_HIGH);
        return c;
    }

    public double[] getLocation() {
    double location[] = new double[2];
    Calendar cal = Calendar.getInstance();
    Long endtime = cal.getTimeInMillis() + 10000;
    while (Calendar.getInstance().getTimeInMillis() < endtime) {
        if (longgps != 0 && latgps != 0) {
            location[0] = longgps;
            location[1] = latgps;
            Log.i("LocationGetter", "GPS: Longitude:" + location[0]
                    + " Latitude:" + location[1]);
            break;
        } else if (longnetwork != 0 && latnetwork != 0) {
            location[0] = longnetwork;
            location[1] = latnetwork;
            Log.i("LocationGetter", "Network: Longitude:" + location[0]
                    + " Latitude:" + location[1]);
        }
    }
    locMgr.removeUpdates(networkLocationListener);
    locMgr.removeUpdates(gpsLocationListener);
    networkLocationListener = null;
    gpsLocationListener = null;
    return location;
}
}
Xing
  • 53
  • 1
  • 4
  • You cannot wait for 10 seconds and with your code you are most likely going to get Network location fix. – Hoan Nguyen May 15 '13 at 01:02
  • Do you want to wait for GPS fixed if it come in within 10 seconds but later than Network? – Hoan Nguyen May 15 '13 at 01:11
  • Hoan I will get the network location after the 10 seconds. But within the 10 seconds If I will get the gps location, the 10 seconds loop breaks and I ll get the gps location. – Xing May 15 '13 at 11:05
  • The thing is not in the logic. The thing is that when I loop over time(10s) the app freezes for 10 sec – Xing May 15 '13 at 11:07

2 Answers2

0

Isn't this just a multithreading problem. Instead of doing the work on the main thread, one could create a second thread so that it doesn't matter if that thread is idle for 10 seconds.

Incidentally, instead of relying on any single provider, I think it's better to use all providers and trust them according to their accuracy using a Kalman filter. See my answer here for a simple Kalman filter that seems to work in the context of Android location providers.

Community
  • 1
  • 1
Stochastically
  • 7,616
  • 5
  • 30
  • 58
0

Make your GPSTracker class abstract by declaring the method updatedLocation(Location loc) without body. In code

public abstract class GPSTracker{
    .......
    private Location mLocation;

    public void updateLocation(Location loc);  

    private CountDownTimer mNetworkCountDown = new CountDownTimer(10000, 10000)
    {

        @Override
        public void onTick(long millisUntilFinished)
        {

        }

        @Override
        public void onFinish()
        {
                        // this onFinish() will be called if not cancel by Gps
            locMgr.removeUpdates(networkLocationListener);
                        updateLocation(mLocation);
        }
    }; 

        private CountDownTimer mGpsCountDown = new CountDownTimer(10000, 10000)
    {

        @Override
        public void onTick(long millisUntilFinished)
        {

        }

        @Override
        public void onFinish()
        {
            locMgr.removeUpdates(gpsLocationListener);
        }
    };   
        .........
        gpsLocationListener = new LocationListener() {
        ..........
        @Override
        public void onLocationChanged(Location location) {
            // Get a gps fix cancel both countdowns and listeners
            mGpsCountDown.cancel();
            mNetworkCountDown.cancel();
            locMgr.removeUpdates(gpsLocationListener);
            locMgr.removeUpdates(networkLocationListener);
            // The calling class will get the fix
            updateLocation(location);

            longgps = location.getLongitude();
            latgps = location.getLatitude();
            //Log.i("LocationGetter", "GPS: Longitude:" + longgps+ " Latitude:" + latgps);

        }
    };
    locMgr.requestLocationUpdates(high.getName(), 0, 0f,gpsLocationListener);
    mGpsCountDown.start();
    .......
    networkLocationListener=new LocationListener() {
    ..........
    @Override
        public void onLocationChanged(Location location) {
            // No cancelation here, Gps will cancel if it gets a fix
            mLocation = location;
            longnetwork = location.getLongitude();
            latnetwork = location.getLatitude();
            //Log.i("LocationGetter", "Network: Longitude:"+ longnetwork + " Latitude:" + latnetwork);

        }
    };
    locMgr.requestLocationUpdates(low.getName(), 0, 0f,networkLocationListener);
    mNetworkCountDown.start();
    .........
    // remove the getLocation()
} 

In HomeActivity class create a class that extends GPSTracker

public class HomeActivity extends Activity {
.........
    public class MyGPSTracker extends GPSTracker
    {
         public void updateLocation(Location location)
         {
              // location would be null if both Gps and Network did not
              // get a fix in 10 seconds
              if (location != null)
              {
                  // do whatever you want with this location fix
                  // If you want to know if this fix is from GPS or Network
                  // just use String provider = location.getProvider()
                  Log.i("LocationGetter","Result: Longitude:"+location.getLongitude()+" Latitude:"+location.getLatitude);
              }
         }
     }

     Button btnRedCross = (Button) this.findViewById(R.id.btnRedCross);
    btnRedCross.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {
            OutRequestsDatabaseHandler db =new OutRequestsDatabaseHandler();
            OutRequest outreq = new OutRequest();
            outreq.setName("Red Cross");
            //TODO get the message from LocalUser db
            Calendar cal = Calendar.getInstance();
            outreq.setDate(cal.getTimeInMillis());
            outreq.setMessage("My Message");
            outreq.setType("RedCross");
            //outreq.setLongitude(12.123456);
            //outreq.setLatitude(12.123456);
            db.addOutRequest(HomeActivity.this, outreq);
            //HERE I AM TRYING TO GET THE LOCATION
            GPSTracker locationtracker=new MyGPSTracker(HomeActivity.this);
            // You will get the location when updateLocation is called by the
            // MyGPSTracker class
            Log.i("LocationGetter","Result: Longitude:"+location[0]+" Latitude:"+location[1]);
        }
    });
}
Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54