package nodomain.freeyourgadget.gadgetbridge.womp;
|
|
import android.Manifest;
|
import android.content.Context;
|
import android.content.pm.PackageManager;
|
import android.location.Location;
|
import android.location.LocationListener;
|
import android.location.LocationManager;
|
import android.os.Bundle;
|
import android.os.Handler;
|
import android.os.Looper;
|
|
import androidx.core.content.ContextCompat;
|
|
import org.json.JSONObject;
|
|
/**
|
* 取一次当前位置,优先用最近缓存,必要时单次刷新。
|
*/
|
public final class WompLocation {
|
public interface Callback {
|
void onResult(boolean ok, String json);
|
}
|
|
private static volatile Location lastFix;
|
|
private WompLocation() {}
|
|
public static void remember(Location location) {
|
if (location != null) {
|
lastFix = location;
|
}
|
}
|
|
public static Location peek() {
|
return lastFix;
|
}
|
|
public static String toJson(Location location) {
|
try {
|
JSONObject obj = new JSONObject();
|
obj.put("longitude", location.getLongitude());
|
obj.put("latitude", location.getLatitude());
|
return obj.toString();
|
} catch (Exception e) {
|
return "{}";
|
}
|
}
|
|
public static void fetch(Context context, Callback callback) {
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
!= PackageManager.PERMISSION_GRANTED
|
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
|
!= PackageManager.PERMISSION_GRANTED) {
|
callback.onResult(false, "{\"message\":\"请先开启定位权限\"}");
|
return;
|
}
|
Context app = context.getApplicationContext();
|
LocationManager lm = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
Location fresh = newest(readLast(lm), lastFix);
|
if (fresh != null && System.currentTimeMillis() - fresh.getTime() < 120_000) {
|
lastFix = fresh;
|
callback.onResult(true, toJson(fresh));
|
return;
|
}
|
Handler handler = new Handler(Looper.getMainLooper());
|
final boolean[] done = {false};
|
LocationListener listener = new LocationListener() {
|
@Override
|
public void onLocationChanged(Location location) {
|
finish(lm, this, handler, done, callback, location, true);
|
}
|
|
@Override
|
public void onStatusChanged(String provider, int status, Bundle extras) {}
|
|
@Override
|
public void onProviderEnabled(String provider) {}
|
|
@Override
|
public void onProviderDisabled(String provider) {}
|
};
|
try {
|
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener, Looper.getMainLooper());
|
} catch (Exception ignored) {
|
}
|
try {
|
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener, Looper.getMainLooper());
|
} catch (Exception ignored) {
|
}
|
handler.postDelayed(() -> {
|
Location fallback = newest(readLast(lm), lastFix, fresh);
|
if (fallback != null) {
|
finish(lm, listener, handler, done, callback, fallback, true);
|
} else {
|
finish(lm, listener, handler, done, callback, null, false);
|
}
|
}, 8000);
|
}
|
|
private static void finish(LocationManager lm, LocationListener listener, Handler handler,
|
boolean[] done, Callback callback, Location location, boolean ok) {
|
if (done[0]) {
|
return;
|
}
|
done[0] = true;
|
handler.removeCallbacksAndMessages(null);
|
try {
|
lm.removeUpdates(listener);
|
} catch (Exception ignored) {
|
}
|
if (ok && location != null) {
|
lastFix = location;
|
callback.onResult(true, toJson(location));
|
} else {
|
callback.onResult(false, "{\"message\":\"无法获取定位,请开启GPS后重试\"}");
|
}
|
}
|
|
private static Location readLast(LocationManager lm) {
|
Location best = null;
|
try {
|
best = newest(best, lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
|
} catch (Exception ignored) {
|
}
|
try {
|
best = newest(best, lm.getLastKnownLocation(LocationManager.GPS_PROVIDER));
|
} catch (Exception ignored) {
|
}
|
return best;
|
}
|
|
private static Location newest(Location... items) {
|
Location best = null;
|
for (Location item : items) {
|
if (item == null) {
|
continue;
|
}
|
if (best == null || item.getTime() > best.getTime()) {
|
best = item;
|
}
|
}
|
return best;
|
}
|
}
|