Skip to content

Detectar Android Mock Location desde Delphi

En los últimos años, una parte de nuestros dispositivos móviles se ha convertido en muy importante, hablamos del GPS. A tal punto que ninguno de los dispositivos salen de fabrica si un GPS integrado.

La funciones que podemos obtener con un GPS son innumerables, desde ubicación geoespacial hasta la captura de Pokémon.

Para los desarrolladores es esencial manejar este sensor de manera experta, pero tenemos una gran contra.

Todas las funciones que podamos desarrollar para el GPS, se verán afectadas si el usuario instala una simple aplicación de simulación de GPS.

En un artículo anterior aprendimos como detectar si el servicio de GPS esta activo, hoy aprenderemos como detectar si la información del GPS es falsa en Android desde Delphi (Android Mock Location).

Mock location provider android

En Android, tenemos una versión de quiebre, un antes y un después de Android 6.

En dicha versión se realizaron muchos cambios, como por ejemplo la forma de solicitar permisos, y entre ellos los servicios de GPS no se quedaron atrás.

Antes de la versión 6, para simular una posición, la aplicación debía solicitar al usuario el permiso llamado ALLOW_MOCK_LOCATION.

function TForm1.isMockLocation(): Boolean;
begin
  if TOSVersion.Check(6) then
  begin
    Result := False;
  begin
  else
  begin
    Result := not (JStringToString(TJSettings_Secure.JavaClass.getString(SharedActivityContext.getContentResolver, TJSettings_Secure.JavaClass.ALLOW_MOCK_LOCATION)) = '0');
  end;
end;

Para detecta si la información del GPS era falsa en estas versiones, simplemente verificábamos en las Apps instaladas en el dispositivo con versiones menores a 6, si alguna poseía este permiso. Y con ello teníamos una gran seguridad de que el usuario podría estar simulando la posición.

Desde la versión de Android 6 (Marshmallow), todo cambió, las aplicaciones para simular una posición, no necesitaban más dicho permiso. Y para hacerla aún más difícil, no necesitan ningún permiso.

Con este cambio lograron que Android tenga el control de los Fake GPS Apps y no los usuarios.

Para poder verificar los Fake GPS Apps, se implemento en java la función isFromMockProvider(), que devuelve True si la información del GPS es falsa o False si la información del GPS es verdadera, o sea que proviene del mismo GPS y no de una App. Totalmente manejada por Android como mencionamos anteriormente.

La forma de utilizar la función isFromMockProvider() en Java es la siguiente:

boolean isMock = false;
if (android.os.Build.VERSION.SDK_INT >= 18) {
    isMock = location.isFromMockProvider();
} else {
    isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}

Pero en Delphi, la forma de utilizar la función isFromMockProvider() es muy diferente, ya que tenemos que hacer uso de las unidades de Java implementadas en Delphi.

La función en Delphi que detecta si la información del GPS es falsa, es la siguiente completando el ejemplo anterior, con el chequeo de la versión de Android:

Uses
  Androidapi.JNI.Provider,
  Androidapi.JNI.Net,
  Androidapi.JNI.Location;

function TForm1.isMockLocation(): Boolean;
begin
  if TOSVersion.Check(6) then
  begin
    Result := LocationSimulation();
  begin
  else
  begin
    Result := not (JStringToString(TJSettings_Secure.JavaClass.getString(SharedActivityContext.getContentResolver, TJSettings_Secure.JavaClass.ALLOW_MOCK_LOCATION)) = '0');
  end;
end;


function TForm1.LocationSimulation(): Boolean;
var
  LocationManagerObj: JObject;
  LocationManager: JLocationManager;
  Location: JLocation;
begin
  try
    LocationManagerObj := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);

    LocationManager := TJLocationManager.Wrap(LocationManagerObj);

    Location := LocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER);

    if Location.isFromMockProvider then
      Result := True
    else
      Result := False;
  except
    Result := False;
  end;
end;