Android Попробуйте определить местоположение в течение X секунд без зависания приложения

Что я пытаюсь сделать, так это получить местоположение GPS от 2 провайдеров, первый — это GPS, который является наиболее точным, второй — это aGPS, который представляет собой комбинацию GPS и сети. Я делаю это, потому что GPS может определять местоположение даже в высоких зданиях, когда обычному GPS требуется больше времени. Что я хочу, так это попытаться получить местоположение от первого провайдера (GPS) в течение 10 секунд, если за эти 10 секунд я получу местоположение! Мероприятия. ИНАЧЕ я возьму местоположение у второго провайдера (aGPS), если он доступен. Если ни один из провайдеров не смог получить местоположение, я верну нуль через 10 секунд. Проблема, с которой я сталкиваюсь, заключается в том, что когда я выполняю временной цикл, приложение зависает на 10 секунд, поэтому я не могу определить местоположение основного действия.

Здесь я пытаюсь получить местоположение в классе HomeActivity, который расширяет 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]);
            }
        });
    }

Это класс GPSTracker, в котором 2 провайдера пытаются определить местоположение:

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;
}
}

person Xing    schedule 15.05.2013    source источник
comment
Вы не можете ждать 10 секунд, и с вашим кодом вы, скорее всего, получите исправление сетевого местоположения.   -  person Hoan Nguyen    schedule 15.05.2013
comment
Вы хотите дождаться исправления GPS, если оно придет в течение 10 секунд, но позже, чем сеть?   -  person Hoan Nguyen    schedule 15.05.2013
comment
Хоан, я получу сетевое местоположение через 10 секунд. Но в течение 10 секунд, если я получу местоположение GPS, цикл 10 секунд разорвется, и я получу местоположение GPS.   -  person Xing    schedule 15.05.2013
comment
Дело не в логике. Дело в том, что когда я зацикливаюсь по времени (10 секунд), приложение зависает на 10 секунд.   -  person Xing    schedule 15.05.2013


Ответы (2)


Разве это не проблема многопоточности? Вместо выполнения работы в основном потоке можно создать второй поток, чтобы не имело значения, простаивает ли этот поток в течение 10 секунд.

Кстати, вместо того, чтобы полагаться на какого-то одного провайдера, я думаю, что лучше использовать всех провайдеров и доверять им в соответствии с их точностью, используя фильтр Калмана. См. мой ответ здесь для простого фильтра Калмана, который, кажется, работает в контексте Android. провайдеры местоположения.

person Stochastically    schedule 15.05.2013

Сделайте свой класс GPSTracker абстрактным, объявив метод updatedLocation(Location loc) без тела. В коде

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()
} 

В классе HomeActivity создайте класс, расширяющий 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]);
        }
    });
}
person Hoan Nguyen    schedule 15.05.2013