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; } }