Android尝试获取X秒的位置而不冻结应用程序

时间:2013-05-15 00:46:38

标签: android timer gps location

我想要做的是从2个提供商获取GPS位置,第一个是最准确的GPS,第二个是GPS和网络的组合的aGPS。我这样做是因为当普通gps需要更多时间时,aGPS即使在高层建筑中也能获得位置。 我想要的是尝试从第一个提供商(GPS)获取位置10秒,如果在那10秒钟我得到一个位置!= null,我打破定时循环并将结果带到主线程,这是主要的活动。如果可用的话,ELSE会从第二个提供商(aGPS)获取该位置。如果没有提供者能够获得位置,我将在10秒后返回null。 我面临的问题是,当我进行定时循环时,应用会冻结10秒钟,因此我无法获得主要活动的位置。

这里我试图获得扩展Activity的HomeActivity类的位置:

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

2 个答案:

答案 0 :(得分:0)

这不仅仅是一个多线程问题。可以创建第二个线程,而不是在主线程上进行工作,这样该线程是否空闲10秒并不重要。

顺便说一句,我认为最好不要依赖任何一个提供商,而是使用卡尔曼滤波器,根据其准确性使用所有提供商并信任它们。有关简单的卡尔曼滤波器,请参阅my answer here,该滤波器似乎适用于Android位置提供商。

答案 1 :(得分:0)

通过声明没有正文的方法updatedLocation(Location loc)来使您的GPSTracker类抽象化。在代码中

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