0

我想做的是从 2 个提供商那里获取 GPS 位置,第一个是最准确的 GPS,第二个是 GPS 和网络结合的 aGPS。我这样做是因为当普通 GPS 需要更多时间才能获取时,即使在高层建筑中,aGPS 也可以获取位置。我想要的是尝试从第一个提供商(GPS)获取位置 10 秒,如果在这 10 秒内我得到一个位置!= null,我打破定时循环并将结果带到主线程,这是主线程活动。否则,如果有的话,我会从第二个提供商 (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;
}
}
4

2 回答 2

0

这不只是一个多线程问题。可以创建第二个线程,而不是在主线程上进行工作,这样该线程是否空闲 10 秒都没有关系。

顺便说一句,我认为最好使用所有提供者并使用卡尔曼滤波器根据它们的准确性信任它们,而不是依赖任何单个提供者。请参阅我的答案,了解一个似乎在 Android 位置提供程序的上下文中工作的简单卡尔曼滤波器。

于 2013-05-15T12:19:06.307 回答
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]);
        }
    });
}
于 2013-05-15T18:19:56.347 回答