Hi Dev, adakah yang pernah mencoba membuat fitur lokasi pada project android? kesempatan yang ada saat ini saya gunakan untuk menulis ulang kode saya kedalam kotlin, dari yang sebelumnya adalah java. Sebenarnya saya tidak hanya sekedar menulis ulang kode, melainkan juga melakukan optimasi, agar performance aplikasi yang saya buat menjadi lebih baik.
Masalah timbul ketika titik marker saya berada jauh dari lokasi saya saat ini, bisa sampai 900-600 meter. Pertanyaan saya adalah bagaimana penulisan kode yang benar agar saya bisa mendapatkan titik lokasi yang presisi?
Sebagai gambaran, kira-kira beginilah kode saya.
package com.agam.mapslocation;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
public class MapsActivity extends Activity {
private static final int ONE_MINUTE = 1000 * 60 * 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
final LocationManager locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
final EditText et = (EditText) findViewById(R.id.editText1);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location l) {
// Called when a new location is found by the network location
// provider.
Location gps = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location net = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Location bestLocation = null;
bestLocation = isBetterLocation(gps, net);
bestLocation = isBetterLocation(bestLocation, l);
if(bestLocation!=null)
displayLocation(et, bestLocation);
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
if (provider.equals(LocationManager.GPS_PROVIDER)) {
et.setText("GPS ON!");
}
}
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location
// updates
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, locationListener);
}
public static void displayLocation(View v, Location l) {
((EditText) v).setText(String.format(
"Long:%s,\nLat:%s,\nAccu:%s,\nTime ago:%s,\nProvider:%s",
l.getLongitude(), l.getLatitude(), l.getAccuracy(),
new java.util.Date().getTime() - l.getTime(), l.getProvider()));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_maps, menu);
return true;
}
/**
* Determines whether one Location reading is better than the current
* Location fix
*
* @param location
* The new Location that you want to evaluate
* @param currentBestLocation
* The current Location fix, to which you want to compare the new
* one
*/
protected Location isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return location;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > ONE_MINUTE;
boolean isSignificantlyOlder = timeDelta < -ONE_MINUTE;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return location;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return currentBestLocation;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return location;
} else if (isNewer && !isLessAccurate) {
return location;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return location;
}
return currentBestLocation;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}
Setelah berkonsultasi, ternyata ada banyak sekali faktor yang mempengaruhi hasil yang diperoleh.
- Pastikan kamu menggunakan provider location yang benar seperti GPS atau Network, bahkan lebih baik jika menggunakan keduanya.
- Pastikan kamu mendapatkan permission dari user untuk mengakses GPS, atau setidaknya perangkat smartphone android yang digunakan built in device GPS.
- Pastikan juga bahwa kamu tidak menggunakan Wifi, karena lokasi fisik modem Wifi belum tentu berada di sekitar kamu, bisa jadi devicenya berada jauh dari lokasi dimana kamu berada. Kasus seperti topik di atas, umumnya paling banyak ditemui di poin ini.
- Pastikan juga perangkat smartphone kamu terinstall google service, sebab ini starting poin untuk membantu GPS mengkalkulasi ulang lokasi, sehingga tidak perlu memulainya lagi dari 0, melainkan bisa menggunakan historical yang dicatat google service.
Untuk bisa memahami bagaimana cara kerja Android mendapatkan lokasi, dan bagaimana mengidentifikasi ordinate fix dan ordinate yang salah. Saya telah merangkumnya menjadi beberapa poin penting.
GPS chipset
- Hasilnya sudah pasti presisi
- Proses mendapatkan titik sedikit lebih lambat
- Tidak bisa mentolerir obstacle building block, artinya kecil sekali kemungkinan mendapatkan lokasi presisi ketika kamu berada di dalam gedung atau terhalang pepohonan.
- Membutuhkan chipset GPS.
- Bisa berjalan di mode pesawat.
- Bergantung terhadap jumlah satelit yang bisa ditangkap
MACs Wifi (modem)
- Kadang-kadang hasilnya membingungkan tergantung dimana kamu terhubung dengan wifi tersebut. Akurasinya bisa sampai 10-100m.
- Proses penentuan lokasi cukup cepat
- Perlu mengaktifkan fitur wifi
- Perlu mengkonsumsi paket data
- Perlu google service terinstall di perangkat android kamu (beberapa perangkat murah mungkin tidak bisa dipasang service ini)
Network Provider (relatif terhadap SIM Card nomor ponsel kamu)
- Hasilnya cukup presisi, meskipun jarak antara perangkat kamu dengan tower pemancar (BTS) sekitar ratusan meter, atau puluhan kilo meter.
- Proses penentuan lokasi sangat cepat.
- Perlu mengaktifkan SIM Card.