사용자 위치를 얻기 위해 디자인 한 클래스 LocationHelper가 있습니다. 생성시, 필자는 필요한 정확도와 현재 위치가 얼마나되어야 하는지를 지정합니다. 새로 획득 한 위치이거나 최근의 위치가 충분하지 않은 경우 위치 관리자로부터 업데이트를 수신하기를 원합니다. 내 문제는이 방법 중 하나에서 이것이 발생하기를 원하고 정확한 위치가 발견 될 때까지 돌아 오지 않는 것이다. 원하는 위치에 도달 할 때까지 메서드가 반환되지 않게하려면 어떻게합니까? 배경 서비스에서 LocationHelper 클래스 만 사용하므로 반환하는 데 시간이 오래 걸릴 염려가 없습니다. 위치가 null인지 (정확한 위치가 발견 될 때까지) 리턴을 확인하기 전에 while 루프를 넣을 생각을했습니다. 그렇다면 기다림을 실행할 것입니다.하지만 이것을 생각하면 좋습니다. 청취자가 업데이트를받지 못하도록합니까?반환하기 전에 메서드가 정확한 위치를 기다리는 것을 만드는 방법은 무엇입니까?
제 설명이 충분하지 않습니다 (내 문제는 getCurrentFix, 하단에있는 경우), 감사합니다 아래 코드입니다.
package com.s0812532.AutoBagger;
import java.util.Date;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
/**
* Class LocationHelper
* Class for obtaining the user's location. Capable of obtaining the current
* position, or the most recent fix available fix without getting a new one, in
* order to conserve battery power. Will automatically decide whether to use
* GPS/network based on required accuracy. Must not be called directly from the UI
* thread or the app will become unresponsive.
*/
public class LocationHelper {
//
// Fields
//
/**
* The maximum accuracy, in metres, for the location fix to be considered accurate enough.
*/
private int accuracyRequired;
/**
* The maximum age, in seconds, for the location fix to be considered recent enough.
*/
private int ageRequired;
/**
* The Location obtained by the constructor
*/
private Location position;
/**
* An instance of the system location manager.
*/
private LocationManager lm;
/**
* The context passed in, in order to be able to access system resources like GPS.
*/
private Context mCtx;
/**
* The current time, set by the constructor.
*/
private long time;
/**
* A scaling factor which is applied to the accuracy of any network
* based location fix to compensate for the inaccuracy of its reporting.
*/
private static final float NETWORK_ACCURACY_SCALE = 5;
//
// Constructors
//
/**
* Constructor which will get a location fix (current or recent) which meets the
* criteria provided so that it can be acted on.
* @return
* @param age The maximum age, in seconds, for the location fix to be
* considered recent enough.
* @param accuracy The maximum accuracy, in metres, for the location fix to
* be considered accurate enough.
*/
public LocationHelper(Context ctx, int age, int accuracy)
{
mCtx = ctx;
setAgeRequired(age);
setAccuracyRequired(accuracy);
//Get the time (in milliseconds since UNIX epoch)
//TODO - need to test what happens when phone clock is wrong
Date now = new Date();
time = now.getTime();
//TODO - handle when LocationManager returns as null
lm = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE);
//Finally, get a fix to satisfy conditions (if a new fix is required then
//getCurrentFix() will detect this and call getCurrentFix() itself.
position = getRecentFix();
}
//
// Methods
//
//
// Accessor methods
//
/**
* Set the value of accuracyRequired
* The maximum accuracy, in metres, for the location fix to be considered accurate
* enough.
* @param newVar the new value of accuracyRequired
*/
private void setAccuracyRequired (int acc) {
//TODO - Test that value is not negative
accuracyRequired = acc;
}
private void setAgeRequired (int age) {
//TODO - Test that the value is not negative
ageRequired = age;
}
//
// Other methods
//
/**
* Returns the location fix obtained by the constructor.
* @return Location
*/
public Location getLocation()
{
return position;
}
/**
* Returns the distance between the user's location and a location provided as an
* argument.
* @return float
* @param location
*/
public float getDistance(Location location)
{
return position.distanceTo(location);
}
/**
* Obtains the most recent fixes from the GPS and Network location managers, and
* stores the more accurate of the two if it is accurate/recent enough, otherwise
* it will call getCurrentFix in order to get an accurate enough fix.
* @return Location
*/
private Location getRecentFix()
{
//TODO - need to check if location sources are enabled, and deal with it if they aren't
Location GPSFix = lm.getLastKnownLocation("GPS");
Location networkFix = lm.getLastKnownLocation("network");
//Adjust the stated accuracy of the network location fix due to errors in reporting
networkFix.setAccuracy(networkFix.getAccuracy()/NETWORK_ACCURACY_SCALE);
if((GPSFix.getAccuracy() < accuracyRequired) & (time - GPSFix.getTime() < ageRequired))
{
//Last GPS fix is good enough, so return it.
return GPSFix;
}
else if ((networkFix.getAccuracy() < accuracyRequired) & (time - networkFix.getTime() < ageRequired))
{
//Last network fix is good enough, so return it.
return networkFix;
}
else {
//none of the available fixes are good enough, so obtain a new one.
return getCurrentFix();
}
}
/**
* Obtains either a GPS or Network based LocationManager, and gets a new fix, if
* possible. GPS/Network is decided upon based accuracy required.
* @return Location
*/
private Location getCurrentFix()
{
//TODO - need to put in some sort of timeout (perhaps getting status updates will do)
LocationListener networkListener = new LocationListener() {
public void onLocationChanged(Location loc) {
//check to see if new position is accurate enough
if (loc.getAccuracy() < accuracyRequired) {
position = loc;
}
else if (new Date().getTime() - time > 15000) { //if it has been looking for network location updates for 15 seconds or more
//Get updates from GPS instead
lm.requestLocationUpdates("gps", 0, 0, GPSListener);
}
}
public void onProviderDisabled(String provider) {
// TODO - network location is/has been disabled by user - do something like warn user it is a bad idea
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
};
LocationListener GPSListener = new LocationListener() {
public void onLocationChanged(Location loc) {
// TODO - check to see if new position is accurate enough
if (loc.getAccuracy() < accuracyRequired) {
position = loc;
}
else if (new Date().getTime() - time > 60000) { //if it has been looking for GPS location updates for 60 seconds or more
//TODO Report an error getting location
}
}
public void onProviderDisabled(String provider) {
// TODO - GPS is/has been turned off by user - do something like warn user it is a bad idea
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
};
if(accuracyRequired < 200) {
//First try network updates, then use GPS if sufficient accuracy not obtained in time
lm.requestLocationUpdates("network", 0, 0, networkListener);
}
else {
//GPS updates required for accuracy
lm.requestLocationUpdates("gps", 0, 0, GPSListener);
}
while (position == null){
//Do nothing, this is just to stop the method returning the position until it has been set
try {
wait(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return position;
}
}
메인 UI와는 다른 스레드에서 실행되며 사용자 상호 작용이 전혀없는 서비스라는 의미입니다. 나는 당신의 대답이 나의 문제를 해결할 것이라고 생각합니다. 감사. – ablack89
차가움. 서비스가 주 스레드에서 실행되는 호출을 가지고 있고 서비스가 활동과 동일한 프로세스 (기본 동작)에서 차단할 수 있다고 판단한 경우에만 해당됩니다. –