我想要做的是从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;
}
}
答案 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]);
}
});
}