diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/location/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/location/BUCK
deleted file mode 100644
index f2c28f62e7b..00000000000
--- a/ReactAndroid/src/main/java/com/facebook/react/modules/location/BUCK
+++ /dev/null
@@ -1,20 +0,0 @@
-load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library")
-
-rn_android_library(
- name = "location",
- srcs = glob(["**/*.java"]),
- is_androidx = True,
- visibility = [
- "PUBLIC",
- ],
- deps = [
- react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"),
- react_native_dep("third-party/android/support/v4:lib-support-v4"),
- react_native_dep("third-party/java/infer-annotations:infer-annotations"),
- react_native_dep("third-party/java/jsr-305:jsr-305"),
- react_native_target("java/com/facebook/react/bridge:bridge"),
- react_native_target("java/com/facebook/react/common:common"),
- react_native_target("java/com/facebook/react/module/annotations:annotations"),
- react_native_target("java/com/facebook/react/modules/core:core"),
- ],
-)
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/location/LocationModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/location/LocationModule.java
deleted file mode 100644
index 46df8e28c29..00000000000
--- a/ReactAndroid/src/main/java/com/facebook/react/modules/location/LocationModule.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-package com.facebook.react.modules.location;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.location.LocationProvider;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import androidx.core.content.ContextCompat;
-import com.facebook.common.logging.FLog;
-import com.facebook.react.bridge.Arguments;
-import com.facebook.react.bridge.Callback;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.facebook.react.bridge.ReactContextBaseJavaModule;
-import com.facebook.react.bridge.ReactMethod;
-import com.facebook.react.bridge.ReadableMap;
-import com.facebook.react.bridge.WritableMap;
-import com.facebook.react.common.ReactConstants;
-import com.facebook.react.common.SystemClock;
-import com.facebook.react.module.annotations.ReactModule;
-import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
-import javax.annotation.Nullable;
-
-/**
- * Native module that exposes Geolocation to JS.
- */
-@SuppressLint("MissingPermission")
-@ReactModule(name = LocationModule.NAME)
-public class LocationModule extends ReactContextBaseJavaModule {
-
- public static final String NAME = "LocationObserver";
- private @Nullable String mWatchedProvider;
- private static final float RCT_DEFAULT_LOCATION_ACCURACY = 100;
-
- private final LocationListener mLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class)
- .emit("geolocationDidChange", locationToMap(location));
- }
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- if (status == LocationProvider.OUT_OF_SERVICE) {
- emitError(PositionError.POSITION_UNAVAILABLE, "Provider " + provider + " is out of service.");
- } else if (status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
- emitError(PositionError.TIMEOUT, "Provider " + provider + " is temporarily unavailable.");
- }
- }
-
- @Override
- public void onProviderEnabled(String provider) { }
-
- @Override
- public void onProviderDisabled(String provider) { }
- };
-
- public LocationModule(ReactApplicationContext reactContext) {
- super(reactContext);
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- private static class LocationOptions {
- private final long timeout;
- private final double maximumAge;
- private final boolean highAccuracy;
- private final float distanceFilter;
-
- private LocationOptions(
- long timeout,
- double maximumAge,
- boolean highAccuracy,
- float distanceFilter) {
- this.timeout = timeout;
- this.maximumAge = maximumAge;
- this.highAccuracy = highAccuracy;
- this.distanceFilter = distanceFilter;
- }
-
- private static LocationOptions fromReactMap(ReadableMap map) {
- // precision might be dropped on timeout (double -> int conversion), but that's OK
- long timeout =
- map.hasKey("timeout") ? (long) map.getDouble("timeout") : Long.MAX_VALUE;
- double maximumAge =
- map.hasKey("maximumAge") ? map.getDouble("maximumAge") : Double.POSITIVE_INFINITY;
- boolean highAccuracy =
- map.hasKey("enableHighAccuracy") && map.getBoolean("enableHighAccuracy");
- float distanceFilter = map.hasKey("distanceFilter") ?
- (float) map.getDouble("distanceFilter") :
- RCT_DEFAULT_LOCATION_ACCURACY;
-
- return new LocationOptions(timeout, maximumAge, highAccuracy, distanceFilter);
- }
- }
-
- /**
- * Get the current position. This can return almost immediately if the location is cached or
- * request an update, which might take a while.
- *
- * @param options map containing optional arguments: timeout (millis), maximumAge (millis) and
- * highAccuracy (boolean)
- */
- @ReactMethod
- public void getCurrentPosition(
- ReadableMap options,
- final Callback success,
- Callback error) {
- LocationOptions locationOptions = LocationOptions.fromReactMap(options);
-
- try {
- LocationManager locationManager =
- (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE);
- String provider = getValidProvider(locationManager, locationOptions.highAccuracy);
- if (provider == null) {
- error.invoke(
- PositionError.buildError(
- PositionError.POSITION_UNAVAILABLE, "No location provider available."));
- return;
- }
- Location location = locationManager.getLastKnownLocation(provider);
- if (location != null && (SystemClock.currentTimeMillis() - location.getTime()) < locationOptions.maximumAge) {
- success.invoke(locationToMap(location));
- return;
- }
-
- new SingleUpdateRequest(locationManager, provider, locationOptions.timeout, success, error)
- .invoke(location);
- } catch (SecurityException e) {
- throwLocationPermissionMissing(e);
- }
- }
-
- /**
- * Start listening for location updates. These will be emitted via the
- * {@link RCTDeviceEventEmitter} as {@code geolocationDidChange} events.
- *
- * @param options map containing optional arguments: highAccuracy (boolean)
- */
- @ReactMethod
- public void startObserving(ReadableMap options) {
- if (LocationManager.GPS_PROVIDER.equals(mWatchedProvider)) {
- return;
- }
- LocationOptions locationOptions = LocationOptions.fromReactMap(options);
-
- try {
- LocationManager locationManager =
- (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE);
- String provider = getValidProvider(locationManager, locationOptions.highAccuracy);
- if (provider == null) {
- emitError(PositionError.POSITION_UNAVAILABLE, "No location provider available.");
- return;
- }
- if (!provider.equals(mWatchedProvider)) {
- locationManager.removeUpdates(mLocationListener);
- locationManager.requestLocationUpdates(
- provider,
- 1000,
- locationOptions.distanceFilter,
- mLocationListener);
- }
- mWatchedProvider = provider;
- } catch (SecurityException e) {
- throwLocationPermissionMissing(e);
- }
- }
-
- /**
- * Stop listening for location updates.
- *
- * NB: this is not balanced with {@link #startObserving}: any number of calls to that method will
- * be canceled by just one call to this one.
- */
- @ReactMethod
- public void stopObserving() {
- LocationManager locationManager =
- (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE);
- locationManager.removeUpdates(mLocationListener);
- mWatchedProvider = null;
- }
-
- @Nullable
- private String getValidProvider(LocationManager locationManager, boolean highAccuracy) {
- String provider =
- highAccuracy ? LocationManager.GPS_PROVIDER : LocationManager.NETWORK_PROVIDER;
- if (!locationManager.isProviderEnabled(provider)) {
- provider = provider.equals(LocationManager.GPS_PROVIDER)
- ? LocationManager.NETWORK_PROVIDER
- : LocationManager.GPS_PROVIDER;
- if (!locationManager.isProviderEnabled(provider)) {
- return null;
- }
- }
- // If it's an enabled provider, but we don't have permissions, ignore it
- int finePermission = ContextCompat.checkSelfPermission(getReactApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION);
- if (provider.equals(LocationManager.GPS_PROVIDER) && finePermission != PackageManager.PERMISSION_GRANTED) {
- return null;
- }
- return provider;
- }
-
- private static WritableMap locationToMap(Location location) {
- WritableMap map = Arguments.createMap();
- WritableMap coords = Arguments.createMap();
- coords.putDouble("latitude", location.getLatitude());
- coords.putDouble("longitude", location.getLongitude());
- coords.putDouble("altitude", location.getAltitude());
- coords.putDouble("accuracy", location.getAccuracy());
- coords.putDouble("heading", location.getBearing());
- coords.putDouble("speed", location.getSpeed());
- map.putMap("coords", coords);
- map.putDouble("timestamp", location.getTime());
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- map.putBoolean("mocked", location.isFromMockProvider());
- }
-
- return map;
- }
-
- private void emitError(int code, String message) {
- getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class)
- .emit("geolocationError", PositionError.buildError(code, message));
- }
-
- /**
- * Provides a clearer exception message than the default one.
- */
- private static void throwLocationPermissionMissing(SecurityException e) {
- throw new SecurityException(
- "Looks like the app doesn't have the permission to access location.\n" +
- "Add the following line to your app's AndroidManifest.xml:\n" +
- "", e);
- }
-
- private static class SingleUpdateRequest {
-
- private final Callback mSuccess;
- private final Callback mError;
- private final LocationManager mLocationManager;
- private final String mProvider;
- private final long mTimeout;
- private Location mOldLocation;
- private final Handler mHandler = new Handler();
- private final Runnable mTimeoutRunnable = new Runnable() {
- @Override
- public void run() {
- synchronized (SingleUpdateRequest.this) {
- if (!mTriggered) {
- mError.invoke(PositionError.buildError(PositionError.TIMEOUT, "Location request timed out"));
- mLocationManager.removeUpdates(mLocationListener);
- FLog.i(ReactConstants.TAG, "LocationModule: Location request timed out");
- mTriggered = true;
- }
- }
- }
- };
- private final LocationListener mLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- synchronized (SingleUpdateRequest.this) {
- if (!mTriggered && isBetterLocation(location, mOldLocation)) {
- mSuccess.invoke(locationToMap(location));
- mHandler.removeCallbacks(mTimeoutRunnable);
- mTriggered = true;
- mLocationManager.removeUpdates(mLocationListener);
- }
-
- mOldLocation = location;
- }
- }
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {}
-
- @Override
- public void onProviderEnabled(String provider) {}
-
- @Override
- public void onProviderDisabled(String provider) {}
- };
- private boolean mTriggered;
-
- private SingleUpdateRequest(
- LocationManager locationManager,
- String provider,
- long timeout,
- Callback success,
- Callback error) {
- mLocationManager = locationManager;
- mProvider = provider;
- mTimeout = timeout;
- mSuccess = success;
- mError = error;
- }
-
- public void invoke(Location location) {
- mOldLocation = location;
- mLocationManager.requestLocationUpdates(mProvider, 100, 1, mLocationListener);
- mHandler.postDelayed(mTimeoutRunnable, mTimeout);
- }
-
- private static final int TWO_MINUTES = 1000 * 60 * 2;
-
- /** Determines whether one Location reading is better than the current Location fix
- * taken from Android Examples https://developer.android.com/guide/topics/location/strategies.html
- *
- * @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
- */
- private boolean isBetterLocation(Location location, Location currentBestLocation) {
- if (currentBestLocation == null) {
- // A new location is always better than no location
- return true;
- }
-
- // Check whether the new location fix is newer or older
- long timeDelta = location.getTime() - currentBestLocation.getTime();
- boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
- boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
- 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 true;
- // If the new location is more than two minutes older, it must be worse
- } else if (isSignificantlyOlder) {
- return false;
- }
-
- // 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 true;
- } else if (isNewer && !isLessAccurate) {
- return true;
- } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
- return true;
- }
-
- return false;
- }
-
- /** Checks whether two providers are the same */
- private boolean isSameProvider(String provider1, String provider2) {
- if (provider1 == null) {
- return provider2 == null;
- }
- return provider1.equals(provider2);
- }
- }
-}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/location/PositionError.java b/ReactAndroid/src/main/java/com/facebook/react/modules/location/PositionError.java
deleted file mode 100644
index b643382c831..00000000000
--- a/ReactAndroid/src/main/java/com/facebook/react/modules/location/PositionError.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-package com.facebook.react.modules.location;
-
-import com.facebook.react.bridge.Arguments;
-import com.facebook.react.bridge.WritableMap;
-
-/**
- * @see {https://developer.mozilla.org/en-US/docs/Web/API/PositionError}
- */
-public class PositionError {
- /**
- * The acquisition of the geolocation information failed because
- * the page didn't have the permission to do it.
- */
- public static int PERMISSION_DENIED = 1;
-
- /**
- * The acquisition of the geolocation failed because at least one
- * internal source of position returned an internal error.
- */
- public static int POSITION_UNAVAILABLE = 2;
-
- /**
- * The time allowed to acquire the geolocation, defined by
- * PositionOptions.timeout information was reached before the information was obtained.
- */
- public static int TIMEOUT = 3;
-
- public static WritableMap buildError(int code, String message) {
- WritableMap error = Arguments.createMap();
- error.putInt("code", code);
-
- if (message != null) {
- error.putString("message", message);
- }
-
- /**
- * Provide error types in error message. Feature parity with iOS
- */
- error.putInt("PERMISSION_DENIED", PERMISSION_DENIED);
- error.putInt("POSITION_UNAVAILABLE", POSITION_UNAVAILABLE);
- error.putInt("TIMEOUT", TIMEOUT);
- return error;
- }
-}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
index c136b1beb84..d564204541e 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
+++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
@@ -34,7 +34,6 @@ rn_android_library(
react_native_target("java/com/facebook/react/modules/i18nmanager:i18nmanager"),
react_native_target("java/com/facebook/react/modules/image:image"),
react_native_target("java/com/facebook/react/modules/intent:intent"),
- react_native_target("java/com/facebook/react/modules/location:location"),
react_native_target("java/com/facebook/react/modules/netinfo:netinfo"),
react_native_target("java/com/facebook/react/modules/network:network"),
react_native_target("java/com/facebook/react/modules/permissions:permissions"),
diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
index 31a871d5efa..1e0b35ea29a 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
@@ -28,7 +28,6 @@ import com.facebook.react.modules.fresco.FrescoModule;
import com.facebook.react.modules.i18nmanager.I18nManagerModule;
import com.facebook.react.modules.image.ImageLoaderModule;
import com.facebook.react.modules.intent.IntentModule;
-import com.facebook.react.modules.location.LocationModule;
import com.facebook.react.modules.netinfo.NetInfoModule;
import com.facebook.react.modules.network.NetworkingModule;
import com.facebook.react.modules.permissions.PermissionsModule;
@@ -88,7 +87,6 @@ import javax.inject.Provider;
ImageLoaderModule.class,
ImageStoreManager.class,
IntentModule.class,
- LocationModule.class,
NativeAnimatedModule.class,
NetworkingModule.class,
NetInfoModule.class,
@@ -239,14 +237,6 @@ public class MainReactPackage extends LazyReactPackage {
return new IntentModule(context);
}
}),
- ModuleSpec.nativeModuleSpec(
- LocationModule.class,
- new Provider() {
- @Override
- public NativeModule get() {
- return new LocationModule(context);
- }
- }),
ModuleSpec.nativeModuleSpec(
NativeAnimatedModule.class,
new Provider() {