Sebagai pengembang SpeedView: GPS speedometer untuk Android, saya pasti sudah mencoba setiap solusi yang mungkin untuk masalah ini, semua dengan hasil negatif yang sama. Mari tegaskan kembali apa yang tidak berhasil:
- onStatusChanged () tidak dipanggil di Eclair dan Froyo.
- Menghitung semua satelit yang tersedia tentu saja tidak berguna.
- Memeriksa apakah salah satu satelit mengembalikan true untuk usedInFix () juga tidak terlalu membantu. Sistem jelas kehilangan perbaikan tetapi terus melaporkan bahwa masih ada beberapa sat yang digunakan di dalamnya.
Jadi, inilah satu-satunya solusi yang saya temukan, dan yang benar-benar saya gunakan di aplikasi saya. Katakanlah kita memiliki kelas sederhana ini yang mengimplementasikan 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) {
} else {
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
isGPSFix = true;
break;
}
}
}
Oke, sekarang di onLocationChanged () kami menambahkan yang berikut:
@Override
public void onLocationChanged(Location location) {
if (location == null) return;
mLastLocationMillis = SystemClock.elapsedRealtime();
mLastLocation = location;
}
Dan itu dia. Pada dasarnya, ini adalah baris yang melakukan semuanya:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000
Anda tentu saja dapat mengubah nilai milis, tetapi saya sarankan untuk menyetelnya sekitar 3-5 detik.
Ini benar-benar berfungsi dan meskipun saya belum melihat kode sumber yang menggambar ikon GPS asli, ini hampir mereplikasi perilakunya. Semoga ini bisa membantu seseorang.
mLastLocationMillis
diatur oleh sumber selain GPS? Sistem akan mengklaim bahwaisGPSFix
itu benar tetapi pada kenyataannya itu hanya perbaikan apa pun (mungkin satu dari jaringan telepon)Ikon GPS tampaknya mengubah statusnya sesuai dengan maksud siaran yang diterima. Anda dapat mengubah sendiri statusnya dengan contoh kode berikut:
Beri tahu bahwa GPS telah diaktifkan:
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent);
Beri tahu bahwa GPS menerima perbaikan:
Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent);
Beri tahu bahwa GPS tidak lagi menerima perbaikan:
Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent);
Beri tahu bahwa GPS telah dinonaktifkan:
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent);
Contoh kode untuk mendaftarkan penerima ke maksud:
// 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);
Dengan menerima maksud siaran ini, Anda dapat melihat perubahan dalam status GPS. Namun, Anda hanya akan diberi tahu saat keadaan berubah. Oleh karena itu, tidak mungkin untuk menentukan status saat ini menggunakan maksud ini.
sumber
anggota baru jadi sayangnya saya tidak dapat berkomentar atau memilih, namun posting Stephen Daye di atas adalah solusi sempurna untuk masalah yang sama persis dengan yang saya sedang mencari bantuan.
perubahan kecil ke baris berikut:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
untuk:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2);
pada dasarnya karena saya sedang membangun game yang serba lambat dan interval pembaruan saya sudah diatur ke 5 detik, setelah sinyal gps keluar selama 10+ detik, itulah waktu yang tepat untuk memicu sesuatu.
cheers sobat, menghabiskan sekitar 10 jam mencoba menyelesaikan solusi ini sebelum saya menemukan posting Anda :)
sumber
Oke, jadi mari kita coba kombinasi dari semua jawaban dan pembaruan sejauh ini dan lakukan sesuatu seperti ini:
ACCESS_FINE_LOCATION
izin ke manifes AndaLocationManager
GpsStatus.Listener
yang bereaksiGPS_EVENT_SATELLITE_STATUS
LocationManager
denganaddGpsStatusListener
Pendengar GPS bisa jadi seperti ini:
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 agak tidak jelas tentang kapan dan apa GPS dan informasi satelit yang diberikan, tapi saya pikir ide yang akan melihat berapa banyak satelit yang tersedia. Jika di bawah tiga, maka Anda tidak dapat memperbaikinya. Jika lebih, maka Anda harus memperbaikinya.
Trial and error mungkin adalah cara yang harus dilakukan untuk menentukan seberapa sering Android melaporkan info satelit, dan info apa yang
GpsSatellite
dikandung setiap objek.sumber
GpsSatellite
objek.LocationManager.requestLocationUpdates
dengan pengaturan waktu dan jarak yang disetel ke 0? Itu akan mengirimi Anda perbaikan GPS segera setelah terjadi. Jika Anda tidak menerima apa pun, kemungkinan besar Anda tidak memiliki perbaikan. Anda dapat menggabungkan ini dengan pendengar status di atas jika Anda mau.Setelah beberapa tahun bekerja dengan GPS di windows mobile, saya menyadari bahwa konsep "kehilangan" sinyal GPS bisa jadi subjektif. Untuk sekadar mendengarkan apa yang dikatakan GPS kepada Anda, menambahkan NMEAListener dan menguraikan kalimat akan memberi tahu Anda apakah perbaikan itu "valid" atau tidak. Lihat http://www.gpsinformation.org/dale/nmea.htm#GGA . Sayangnya dengan beberapa GPS, nilai ini akan berfluktuasi bolak-balik bahkan selama pengoperasian normal di area "perbaikan yang baik".
Jadi, solusi lainnya adalah membandingkan waktu UTC dari lokasi GPS dengan waktu telepon (dikonversi ke UTC). Jika jaraknya berbeda dengan perbedaan waktu tertentu, Anda dapat berasumsi bahwa Anda kehilangan posisi GPS.
sumber
mengalami masalah serupa saat mengerjakan proyek MSc saya, tampaknya jawaban Daye secara keliru melaporkan "tidak ada perbaikan" sementara perangkat tetap berada di lokasi statis. Saya telah memodifikasi solusinya hanya sedikit yang tampaknya berfungsi dengan baik untuk saya di lokasi statis. Saya tidak tahu bagaimana pengaruhnya terhadap baterai karena ini bukan perhatian utama saya, tetapi inilah cara saya melakukannya dengan meminta kembali pembaruan lokasi ketika waktu perbaikan telah habis.
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; } } }
sumber
Nah, menyusun setiap pendekatan kerja akan menghasilkan ini (juga menangani 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) { }
Catatan: jawaban ini adalah kombinasi dari jawaban di atas.
sumber
Jika Anda hanya perlu tahu apakah ada perbaikan, periksa lokasi terakhir yang diketahui disediakan oleh penerima GPS dan periksa nilai .getTime () untuk mengetahui berapa usianya. Jika cukup baru-baru ini (seperti ... beberapa detik) Anda harus memperbaikinya.
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();
... dan akhirnya bandingkan dengan waktu tanggal saat ini (Dalam UTC!). Jika cukup baru-baru ini, Anda harus memperbaikinya.
Saya melakukannya di aplikasi saya dan sejauh ini bagus.
sumber
Anda dapat mencoba menggunakan LocationManager.addGpsStatusListener untuk mendapatkan pembaruan ketika status GPS berubah. Sepertinya GPS_EVENT_STARTED dan GPS_EVENT_STOPPED mungkin yang Anda cari.
sumber
GPS_EVENT_FIRST_FIX
suara yang lebih cocok.Saya mungkin salah tetapi tampaknya orang-orang tampaknya keluar dari topik
Itu mudah dilakukan
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); boolean gps_on = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
Untuk melihat apakah Anda memiliki perbaikan yang solid, semuanya menjadi sedikit lebih rumit:
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) {} };
Sekarang kapan pun Anda ingin melihat apakah Anda telah memperbaikinya?
if (loc != null){ // Our location has changed at least once blah..... }
Jika Anda ingin menjadi mewah, Anda selalu dapat memiliki waktu tunggu menggunakan System.currentTimeMillis () dan loc.getTime ()
Bekerja dengan andal, setidaknya pada N1 sejak 2.1.
sumber
Dengan LocationManager Anda bisa getLastKnownLocation () setelah Anda getBestProvider (). Ini memberi Anda objek Lokasi, yang memiliki metode getAccuracy () dalam meter dan getTime () dalam milidetik UTC
Apakah ini memberi Anda info yang cukup?
Atau mungkin Anda bisa mengulangi LocationProviders dan mencari tahu apakah masing-masing memenuhi Kriteria (ACCURACY_COARSE)
sumber
begitu banyak postingan ...
GpsStatus.Listener gpsListener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { if( event == GpsStatus.GPS_EVENT_FIRST_FIX){ showMessageDialog("GPS fixed"); } } };
menambahkan kode ini, dengan addGpsListener ... showMessageDialog ... hanya menampilkan jendela dialog standar dengan string
melakukan pekerjaan dengan sempurna untuk saya :) terima kasih banyak: =) (sry untuk posting ini, belum dapat memilih)
sumber
Jika Anda tidak memerlukan pembaruan segera setelah perbaikan hilang, Anda dapat memodifikasi solusi Stephen Daye dengan cara itu, bahwa Anda memiliki metode yang memeriksa apakah perbaikan masih ada.
Jadi Anda bisa memeriksanya kapan pun Anda membutuhkan beberapa data GPS dan dan Anda tidak memerlukan GpsStatus.Listener itu.
Variabel "global" adalah:
private Location lastKnownLocation; private long lastKnownLocationTimeMillis = 0; private boolean isGpsFix = false;
Ini adalah metode yang dipanggil dalam "onLocationChanged ()" untuk mengingat waktu pembaruan dan lokasi saat ini. Selain itu, update "isGpsFix":
private void handlePositionResults(Location location) { if(location == null) return; lastKnownLocation = location; lastKnownLocationTimeMillis = SystemClock.elapsedRealtime(); checkGpsFix(); // optional }
Metode itu dipanggil setiap kali saya perlu tahu apakah ada sinyal GPS:
private boolean checkGpsFix(){ if (SystemClock.elapsedRealtime() - lastKnownLocationTimeMillis < 3000) { isGpsFix = true; } else { isGpsFix = false; lastKnownLocation = null; } return isGpsFix; }
Dalam implementasi saya, saya pertama kali menjalankan checkGpsFix () dan jika hasilnya benar saya menggunakan variabel "lastKnownLocation" sebagai posisi saya saat ini.
sumber
Saya tahu ini agak terlambat. Namun mengapa tidak menggunakan NMEAListener jika Anda ingin tahu apakah Anda memiliki perbaikan. Dari apa yang saya baca, NMEAListener akan memberi Anda kalimat NMEA dan dari sana Anda memilih kalimat yang benar.
Kalimat RMC berisi status perbaikan yaitu A untuk OK atau V untuk peringatan. Kalimat GGA berisi Fix Quality (0 invalid, 1 GPS or 2 DGPS)
Saya tidak dapat menawarkan kode java apa pun karena saya baru saja memulai dengan Android, tetapi saya telah membuat pustaka GPS di C # untuk aplikasi Windows, yang ingin saya gunakan dengan Xamarin. Saya hanya menemukan utas ini karena saya mencari informasi penyedia.
Dari apa yang telah saya baca sejauh ini tentang objek Lokasi, saya tidak begitu nyaman dengan metode seperti getAccuracy () dan hasAccuracy (). Saya terbiasa mengekstrak dari kalimat NMEA nilai HDOP dan VDOP untuk menentukan seberapa akurat perbaikan saya. Sangat umum untuk memperbaiki, tetapi memiliki HDOP yang buruk yang berarti akurasi horizontal Anda tidak terlalu bagus sama sekali. Misalnya duduk di meja Anda melakukan debug dengan perangkat GPS Bluetooth eksternal yang menempel di jendela, Anda kemungkinan besar akan mendapatkan perbaikan, tetapi HDOP dan VDOP yang sangat buruk. Tempatkan perangkat GPS Anda di pot bunga di luar atau sesuatu yang serupa atau tambahkan antena eksternal ke GPS dan segera Anda mendapatkan nilai HDOP dan VDOP yang baik.
sumber
Mungkin itu kemungkinan terbaik untuk membuat TimerTask yang menyetel Lokasi yang diterima ke nilai tertentu (null?) Secara teratur. Jika nilai baru diterima oleh GPSListener, itu akan memperbarui lokasi dengan data saat ini.
Saya pikir itu akan menjadi solusi yang berhasil.
sumber
Anda mengatakan bahwa Anda sudah mencoba onStatusChanged (), tetapi itu berhasil untuk saya.
Inilah metode yang saya gunakan (saya membiarkan kelas itu sendiri menangani 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); }
Dan saya menangani onStatusChanged sebagai berikut:
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; } }
Perhatikan bahwa metode onProvider {Dis, En} abled () adalah tentang mengaktifkan dan menonaktifkan pelacakan GPS oleh pengguna; bukan yang Anda cari.
sumber
Menyetel interval waktu untuk memeriksa perbaikan bukanlah pilihan yang baik .. saya perhatikan bahwa onLocationChanged tidak dipanggil jika Anda tidak bergerak .. apa yang bisa dimengerti karena lokasi tidak berubah :)
Cara yang lebih baik misalnya:
sumber