GPS 수신기의 현재 상태를 어떻게 확인할 수 있습니까? 나는 이미 LocationListener
onStatusChanged
방법을 확인 했지만 어떻게 든 작동하지 않거나 잘못된 가능성이있는 것 같습니다.
기본적으로 화면 상단의 GPS 아이콘이 깜박이는지 (실제 수정 없음) 또는 계속 켜져 있는지 (수정 가능) 알면됩니다.
GPS 수신기의 현재 상태를 어떻게 확인할 수 있습니까? 나는 이미 LocationListener
onStatusChanged
방법을 확인 했지만 어떻게 든 작동하지 않거나 잘못된 가능성이있는 것 같습니다.
기본적으로 화면 상단의 GPS 아이콘이 깜박이는지 (실제 수정 없음) 또는 계속 켜져 있는지 (수정 가능) 알면됩니다.
답변:
SpeedView : Android 용 GPS 속도계 개발자로서 저는이 문제에 대해 가능한 모든 해결책을 시도했지만 모두 동일한 부정적인 결과를 보였을 것입니다. 작동하지 않는 것을 반복 해 보겠습니다.
그래서 여기에 내가 찾은 유일한 작동 솔루션이 있으며 실제로 내 앱에서 사용하는 솔루션이 있습니다. GpsStatus.Listener를 구현하는 다음과 같은 간단한 클래스가 있다고 가정 해 보겠습니다.
private class MyGPSListener implements GpsStatus.Listener {
public void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
if (mLastLocation != null)
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
if (isGPSFix) { // A fix has been acquired.
// Do something.
} else { // The fix has been lost.
// Do something.
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
// Do something.
isGPSFix = true;
break;
}
}
}
이제 onLocationChanged ()에서 다음을 추가합니다.
@Override
public void onLocationChanged(Location location) {
if (location == null) return;
mLastLocationMillis = SystemClock.elapsedRealtime();
// Do something.
mLastLocation = location;
}
그리고 그게 다야. 기본적으로 다음은 모든 작업을 수행하는 라인입니다.
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
물론 millis 값을 조정할 수 있지만 3 ~ 5 초 정도 설정하는 것이 좋습니다.
이것은 실제로 작동하며 네이티브 GPS 아이콘을 그리는 소스 코드를 보지는 않았지만 동작을 복제하는 것과 비슷합니다. 이것이 누군가를 돕기를 바랍니다.
mLastLocationMillis
GPS 이외의 소스에서 설정 했을 때 이것이 깨지지 않습니까? 시스템은 isGPSFix
그것이 사실 이라고 주장 하겠지만 실제로는 모든 수정일 뿐입니다 (전화 네트워크에서 하나 일 수도 있음)
수신 된 방송 의도에 따라 GPS 아이콘의 상태가 변경되는 것 같습니다. 다음 코드 샘플을 사용하여 상태를 직접 변경할 수 있습니다.
GPS가 활성화되었음을 알립니다.
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
sendBroadcast(intent);
GPS가 수정 사항을 수신하고 있음을 알립니다.
Intent intent = new Intent("android.location.GPS_FIX_CHANGE");
intent.putExtra("enabled", true);
sendBroadcast(intent);
GPS가 더 이상 수정 사항을 수신하지 않음을 알립니다.
Intent intent = new Intent("android.location.GPS_FIX_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
GPS가 비활성화되었음을 알립니다.
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
수신자를 인 텐트에 등록하는 예제 코드 :
// MyReceiver must extend BroadcastReceiver
MyReceiver receiver = new MyReceiver();
IntentFilter filter = new IntentFilter("android.location.GPS_ENABLED_CHANGE");
filter.addAction("android.location.GPS_FIX_CHANGE");
registerReceiver(receiver, filter);
이러한 브로드 캐스트 인 텐트를 수신하면 GPS 상태의 변화를 알 수 있습니다. 그러나 상태가 변경 될 때만 알림을받습니다. 따라서 이러한 인 텐트를 사용하여 현재 상태를 확인할 수 없습니다.
새 회원은 안타깝게도 댓글을 달거나 투표 할 수 없었지만 위의 Stephen Daye의 게시물은 제가 도움을 찾고 있던 문제에 대한 완벽한 해결책이었습니다.
다음 줄에 대한 작은 변경 :
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
에:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2);
기본적으로 느린 속도의 게임을 빌드하고 업데이트 간격이 이미 5 초로 설정되어 있으므로 gps 신호가 10 초 이상 나가면 무언가를 트리거 할 적절한 시간입니다.
응원 친구, 내가 당신의 게시물을 찾기 전에이 솔루션을 해결하기 위해 약 10 시간을 보냈습니다 :)
좋습니다. 지금까지의 모든 답변과 업데이트를 조합하여 다음과 같이 해보겠습니다.
ACCESS_FINE_LOCATION
매니페스트에 권한 추가LocationManager
GpsStatus.Listener
반응하는 만들기GPS_EVENT_SATELLITE_STATUS
LocationManager
과를addGpsStatusListener
GPS 리스너는 다음과 같을 수 있습니다.
GpsStatus.Listener listener = new GpsStatus.Listener() {
void onGpsStatusChanged(int event) {
if (event == GPS_EVENT_SATELLITE_STATUS) {
GpsStatus status = mLocManager.getGpsStatus(null);
Iterable<GpsSatellite> sats = status.getSatellites();
// Check number of satellites in list to determine fix state
}
}
}
API는 언제 어떤 GPS 및 위성 정보가 제공되는지에 대해 약간 불분명하지만 몇 개의 위성을 사용할 수 있는지 살펴 보는 것이 아이디어라고 생각합니다. 3 미만이면 고칠 수 없습니다. 더 많으면 수정해야합니다.
시행 착오는 Android가 위성 정보를보고하는 빈도와 각 GpsSatellite
개체에 포함 된 정보를 확인하는 방법 일 것 입니다.
GpsSatellite
객체 에서이 정보를 검색 할 수있는 방법 / 여부에 대해 더 이상 알지 못합니다 .
LocationManager.requestLocationUpdates
시간과 거리 설정을 0으로 설정하여 사용해 보셨습니까? GPS 수정 사항이 발생하는 즉시 전송됩니다. 아무것도받지 못했다면 해결 방법이 없을 가능성이 큽니다. 원한다면 위의 상태 리스너와 결합 할 수 있습니다.
Windows 모바일에서 몇 년 동안 GPS로 작업 한 후, GPS 수정을 "잃어버린"개념이 주관적 일 수 있다는 것을 깨달았습니다. GPS가 알려주는 내용을 듣기 위해 NMEAListener를 추가하고 문장을 구문 분석하면 수정 사항이 "유효"한지 여부를 알 수 있습니다. http://www.gpsinformation.org/dale/nmea.htm#GGA를 참조 하십시오 . 불행히도 일부 GPS에서는이 값이 "좋은 수정"영역에서 정상적인 작동 과정 중에도 앞뒤로 변동합니다.
따라서 다른 해결책은 GPS 위치의 UTC 시간을 전화기의 시간 (UTC로 변환)과 비교하는 것입니다. 일정 시간 차이가 나면 GPS 위치를 잃어버린 것으로 간주 할 수 있습니다.
내 MSc 프로젝트에서 작업하는 동안 비슷한 문제가 발생하면 Daye의 답변이 장치가 고정 된 위치에있는 동안 "수정 안 됨"으로 잘못보고 된 것 같습니다. 정적 위치에서 잘 작동하는 것처럼 보이는 솔루션을 약간 수정했습니다. 주요 관심사가 아니기 때문에 배터리에 어떤 영향을 미칠지 모르겠지만 수정 시간이 초과되었을 때 위치 업데이트를 다시 요청하여 수행 한 방법은 다음과 같습니다.
private class MyGPSListener implements GpsStatus.Listener {
public void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
if (Global.getInstance().currentGPSLocation != null)
{
if((SystemClock.elapsedRealtime() - mLastLocationMillis) < 20000)
{
if (!hasGPSFix)
Log.i("GPS","Fix Acquired");
hasGPSFix = true;
}
else
{
if (hasGPSFix)
{
Log.i("GPS","Fix Lost (expired)");
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener);
}
hasGPSFix = false;
}
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
Log.i("GPS", "First Fix/ Refix");
hasGPSFix = true;
break;
case GpsStatus.GPS_EVENT_STARTED:
Log.i("GPS", "Started!");
break;
case GpsStatus.GPS_EVENT_STOPPED:
Log.i("GPS", "Stopped");
break;
}
}
}
글쎄, 모든 작업 접근 방식을 통합하면 다음과 같은 결과가 나타납니다 (deprecated 처리도 함 GpsStatus.Listener
).
private GnssStatus.Callback mGnssStatusCallback;
@Deprecated private GpsStatus.Listener mStatusListener;
private LocationManager mLocationManager;
@Override
public void onCreate() {
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (checkPermission()) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_INTERVAL, MIN_DISTANCE, this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mGnssStatusCallback = new GnssStatus.Callback() {
@Override
public void onSatelliteStatusChanged(GnssStatus status) {
satelliteStatusChanged();
}
@Override
public void onFirstFix(int ttffMillis) {
gpsFixAcquired();
}
};
mLocationManager.registerGnssStatusCallback(mGnssStatusCallback);
} else {
mStatusListener = new GpsStatus.Listener() {
@Override
public void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
satelliteStatusChanged();
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
// Do something.
gpsFixAcquired();
break;
}
}
};
mLocationManager.addGpsStatusListener(mStatusListener);
}
}
private void gpsFixAcquired() {
// Do something.
isGPSFix = true;
}
private void satelliteStatusChanged() {
if (mLastLocation != null)
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2);
if (isGPSFix) { // A fix has been acquired.
// Do something.
} else { // The fix has been lost.
// Do something.
}
}
@Override
public void onLocationChanged(Location location) {
if (location == null) return;
mLastLocationMillis = SystemClock.elapsedRealtime();
mLastLocation = location;
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
참고 :이 답변은 위 답변의 조합입니다.
수정 사항이 있는지 확인해야하는 경우 GPS 수신기에서 제공 한 마지막 알려진 위치를 확인하고 .getTime () 값을 확인하여 얼마나 오래되었는지 확인합니다. 충분히 최근일 경우 (예 : 몇 초 정도) 문제가 해결 된 것입니다.
LocationManager lm = (LocationManager)context.getSystemService(LOCATION_SERVICE);
Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// Get the time of the last fix
long lastFixTimeMillis = loc.getTime();
... 마지막으로 현재 날짜 시간과 비교합니다 (UTC에서!). 충분히 최근의 경우 수정 사항이 있습니다.
나는 내 앱에서 그렇게하고있다.
LocationManager.addGpsStatusListener 를 사용 하여 GPS 상태가 변경 될 때 업데이트를받을 수 있습니다. GPS_EVENT_STARTED 및 GPS_EVENT_STOPPED를 찾으시는 것 같습니다 .
GPS_EVENT_FIRST_FIX
가 더 가깝게 들리는 것처럼 들립니다.
내가 틀렸을 수도 있지만 사람들이 주제에서 벗어나는 것 같습니다.
화면 상단의 gps 아이콘이 깜박이는지 확인하면됩니다 (실제 수정 없음).
쉽게 할 수 있습니다.
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean gps_on = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
확실한 해결책이 있는지 확인하려면 상황이 조금 더 까다로워집니다.
public class whatever extends Activity {
LocationManager lm;
Location loc;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
loc = null;
request_updates();
}
private void request_updates() {
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
// GPS is enabled on device so lets add a loopback for this locationmanager
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0, 0, locationListener);
}
}
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Each time the location is changed we assign loc
loc = location;
}
// Need these even if they do nothing. Can't remember why.
public void onProviderDisabled(String arg0) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
이제 수정이 있는지 확인하고 싶을 때마다?
if (loc != null){
// Our location has changed at least once
blah.....
}
멋지고 싶다면 System.currentTimeMillis () 및 loc.getTime ()을 사용하여 항상 시간 초과를 가질 수 있습니다.
2.1 이후 N1에서 안정적으로 작동합니다.
너무 많은 포스트 ...
GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
if( event == GpsStatus.GPS_EVENT_FIRST_FIX){
showMessageDialog("GPS fixed");
}
}
};
addGpsListener ... showMessageDialog ...이 코드를 추가하면 문자열이 포함 된 표준 대화 창이 표시됩니다.
나를 위해 완벽하게 일했습니다 :) 고마워요 : =) (이 게시물에 대해 외침, 아직 투표 할 수 없음)
수정 사항이 손실되는 즉시 업데이트가 필요하지 않은 경우 수정 사항이 여전히 존재하는지 확인하는 방법이있는 방식으로 Stephen Daye의 솔루션을 수정할 수 있습니다.
따라서 GPS 데이터가 필요할 때마다 확인할 수 있으며 GpsStatus.Listener가 필요하지 않습니다.
"전역"변수는 다음과 같습니다.
private Location lastKnownLocation;
private long lastKnownLocationTimeMillis = 0;
private boolean isGpsFix = false;
업데이트 시간과 현재 위치를 기억하기 위해 "onLocationChanged ()"내에서 호출되는 메소드입니다. 그 외에도 "isGpsFix"를 업데이트합니다.
private void handlePositionResults(Location location) {
if(location == null) return;
lastKnownLocation = location;
lastKnownLocationTimeMillis = SystemClock.elapsedRealtime();
checkGpsFix(); // optional
}
이 메서드는 GPS 수정이 있는지 알아야 할 때마다 호출됩니다.
private boolean checkGpsFix(){
if (SystemClock.elapsedRealtime() - lastKnownLocationTimeMillis < 3000) {
isGpsFix = true;
} else {
isGpsFix = false;
lastKnownLocation = null;
}
return isGpsFix;
}
내 구현에서는 먼저 checkGpsFix ()를 실행하고 결과가 true이면 "lastKnownLocation"변수를 현재 위치로 사용합니다.
나는 이것이 조금 늦었다는 것을 안다. 그러나 수정 사항이 있는지 알고 싶다면 NMEAListener를 사용하지 마십시오. 내가 읽은 내용에서 NMEAListener는 NMEA 문장을 제공하고 거기에서 올바른 문장을 선택합니다.
RMC 문장에는 A (양호) 또는 V (경고)의 수정 상태가 포함됩니다. GGA 문장에 Fix Quality (잘못된 0 개, GPS 1 개 또는 DGPS 2 개)가 포함되어 있습니다.
Android로 시작했을 뿐이므로 Java 코드를 제공 할 수는 없지만 Xamarin과 함께 사용하려는 Windows 앱용 C #에서 GPS 라이브러리를 작성했습니다. 공급자 정보를 찾고 있었기 때문에이 스레드를 만났습니다.
지금까지 Location 객체에 대해 읽은 내용에서 getAccuracy () 및 hasAccuracy ()와 같은 메서드에 대해 그다지 편하지 않습니다. 나는 NMEA 문장에서 HDOP 및 VDOP 값을 추출하여 수정 사항이 얼마나 정확한지 결정하는 데 익숙합니다. 수정하는 것은 매우 일반적이지만 HDOP가 좋지 않아 수평 정확도가 전혀 좋지 않습니다. 예를 들어, 책상에 앉아 외부 Bluetooth GPS 장치를 창문에 대고 세게 디버깅하면 고칠 가능성이 높지만 HDOP 및 VDOP는 매우 열악합니다. GPS 장치를 외부의 화분에 놓거나 GPS에 외부 안테나를 추가하면 즉시 좋은 HDOP 및 VDOP 값을 얻을 수 있습니다.
이미 onStatusChanged ()를 시도했다고 말했지만 그것은 저에게 효과적입니다.
다음은 내가 사용하는 방법입니다 (클래스 자체가 onStatusChanged를 처리하도록합니다).
private void startLocationTracking() {
final int updateTime = 2000; // ms
final int updateDistance = 10; // meter
final Criteria criteria = new Criteria();
criteria.setCostAllowed(false);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
final String p = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(p, updateTime, updateDistance,
this);
}
그리고 다음과 같이 onStatusChanged를 처리합니다.
void onStatusChanged(final String provider, final int status,
final Bundle extras) {
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
if (location == null || location.getProvider().equals(provider)) {
statusString = "No Service";
location = null;
}
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
if (location == null || location.getProvider().equals(provider)) {
statusString = "no fix";
}
break;
case LocationProvider.AVAILABLE:
statusString = "fix";
break;
}
}
onProvider {Dis, En} abled () 메서드는 사용자가 GPS 추적을 활성화 및 비활성화하는 것에 관한 것입니다. 당신이 찾고있는 것이 아닙니다.
수정을 확인하기 위해 시간 간격을 설정하는 것은 좋은 선택이 아닙니다 .. 나는 움직이지 않으면 onLocationChanged가 호출되지 않는다는 것을 알아 챘습니다 . .. 위치가 변하지 않기 때문에 이해할 수있는 것 :)
예를 들어 더 나은 방법은 다음과 같습니다.