¿Ubicación simulada de Android en el dispositivo?


147

¿Cómo puedo burlarme de mi ubicación en un dispositivo físico (Nexus One)? Sé que puedes hacer esto con el emulador en el panel de control del emulador, pero esto no funciona para un dispositivo físico.


Para las computadoras de escritorio, puede crear / instalar controladores que emulen un dispositivo GPS / dispositivo de puerto serie con el fin de realizar este tipo de pruebas. Tal vez podría crear o encontrar algo similar para Android.
AaronLS

66
Hay varias aplicaciones en Market que pueden emular la ubicación del GPS. Por ejemplo "Location spoofer".
Vlad

Hay muchas aplicaciones en la tienda que hacen esto ... Puedes probar esto - play.google.com/store/apps/… o esto - play.google.com/store/apps/…
Yehuda

1
¡También hay una aplicación en la tienda que admite comandos "geo fix" y "geo nmea" como el emulador! play.google.com/store/apps/…
luv

@Iuv más sobre esto es código abierto github.com/luv/mockgeofix
Vlad

Respuestas:


166

Parece que la única forma de hacerlo es utilizar un proveedor de ubicación simulada.

Debe habilitar ubicaciones simuladas en el panel de desarrollo en su configuración y agregar

   <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> 

a tu manifiesto.

Ahora puede ingresar su código y crear su propio proveedor de ubicación simulada y establecer la ubicación de este proveedor.


83
Hay una aplicación en el mercado llamada "GPS falso". Si habilita ubicaciones falsas en su dispositivo, ofrece una buena GUI para configurar su ubicación. Me doy cuenta de que esta no es una solución de bricolaje, pero ciertamente es una solución digna para pruebas rápidas.
Tim Green

2
Este podría ser el enlace: la misma fecha y el contenido relevante.
DefenestrationDay

44
¡@TimGreen tuya debe ser la respuesta aceptada (no solo un comentario)! Con mucho, la forma más fácil de probar
Bostone el

En realidad, la aplicación "GPS falso" no es la mejor porque solo puede establecer ubicaciones y moverse aleatoriamente. Su nueva versión puede enrutar, pero solo itera sobre puntos de paso para que salten enormes saltos en la ubicación. La respuesta de Janusz es correcta, es necesario crear su propio proveedor simulado. Hace poco hicimos eso y si alguien lo necesita o si esta pregunta aún necesita ayuda, publicaré el código.
vkinra

55
La declaración "ingrese su código y cree su propio proveedor de ubicación simulada" debe explicarse con más detalle.
Atenúa

102

Si usa este teléfono solo en el laboratorio de desarrollo, existe la posibilidad de que pueda soldar el chip GPS y alimentar el puerto serie directamente con secuencias NMEA desde otro dispositivo.


68
¿Por qué los que odian? Esta respuesta es un núcleo increíblemente duro.
Ben Zotto

61
Increíblemente duro, aunque increíblemente inútil / irrelevante también.
olivervbk

13
Aunque lo suficientemente divertido.
etienne

23
Creo que cualquiera para quien esta respuesta sea relevante, ya sabe que puede hacer esto. Dudo que esas tres personas estén buscando una solución para stackoverflow.
ToolmakerSteve

10
Si tiene problemas para descubrir cómo generar secuencias NMEA realistas en su dispositivo sin soldar, hay una opción increíble: soldar allí un dispositivo GPS externo real y mover todo el laboratorio de desarrollo en una pista real, encima de un equipo de corredores / ciclistas / carros / aviones / lo que sea, dependiendo de la velocidad que desee simular. No olvide abrir un agujero en el techo del laboratorio de desarrollo para que el dispositivo pueda recibir señales de radio de los satélites. De nada. ;-)
Stéphane Gourichon

32

Desearía tener mi cable a mano. Sé que puedes hacer telnet al emulador para cambiar su ubicación

$ telnet localhost 5554
Android Console: type 'help' for a list of commands
OK
geo fix -82.411629 28.054553
OK

No recuerdo si puedes hacer telnet a tu dispositivo, pero creo que puedes. Espero que esto ayude.

Necesitará adb (puente de depuración de Android) para esto (CLI).


obtienes un permiso denegado para todo lo que envías como comando a la consola de tu dispositivo. Tal vez sea posible con una aplicación de terminal, pero creo que eso requiere acceso de root
Janusz

Solo estamos en la misma página: no estás hablando de "adb shell", ¿verdad? De lo que estoy hablando es diferente, esto es algo que le permite configurar parámetros específicos de Android. Sé, por ejemplo, que puede configurar el reenvío de puertos (es decir, localhost: 1234 va al teléfono: 1234) sin acceso a la raíz, por lo que puede configurar un proxy SOCKS y un túnel a través de un cable sin raíz.
Tim Green

Puede usar adb forward tcp: 6000 tcp: 23 para reenviar el puerto 6000 en su máquina al puerto 23 en el dispositivo, pero no pude conectarme incluso si el puerto se muestra como abierto. El uso de un cliente telnet en el dispositivo y la conexión a localhost también falla
Janusz el

15
Esto funciona bien para el emulador pero no funciona para un dispositivo real. Por lo tanto, no responde a la pregunta de OP :(
Matthew Gilliard

44
@TimGreen Su solución es solo para emulador. La pregunta era sobre un dispositivo real.
IgorGanapolsky

29

Puede usar el permiso de Servicios de ubicación para burlarse de la ubicación ...

"android.permission.ACCESS_MOCK_LOCATION"

y luego en tu código java,

// Set location by setting the latitude, longitude and may be the altitude...
String[] MockLoc = str.split(",");
Location location = new Location(mocLocationProvider);            
Double lat = Double.valueOf(MockLoc[0]);
location.setLatitude(lat);
Double longi = Double.valueOf(MockLoc[1]);
location.setLongitude(longi);
Double alti = Double.valueOf(MockLoc[2]);
location.setAltitude(alti);

9
¿Qué valor tiene mocLocationProvider?
Victor

por ejemplo, LocationManager.GPS_PROVIDER
enigma969

25

He tenido éxito con el siguiente código. Aunque por alguna razón me consiguió un solo bloqueo (incluso si probé diferentes pares LatLng), funcionó para mí. mLocationManageres un LocationManagerque está conectado a un LocationListener:

private void getMockLocation()
{
    mLocationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
    mLocationManager.addTestProvider
    (
      LocationManager.GPS_PROVIDER,
      "requiresNetwork" == "",
      "requiresSatellite" == "",
      "requiresCell" == "",
      "hasMonetaryCost" == "",
      "supportsAltitude" == "",
      "supportsSpeed" == "",
      "supportsBearing" == "",

      android.location.Criteria.POWER_LOW,
      android.location.Criteria.ACCURACY_FINE
    );      

    Location newLocation = new Location(LocationManager.GPS_PROVIDER);

    newLocation.setLatitude (/* TODO: Set Some Lat */);
    newLocation.setLongitude(/* TODO: Set Some Lng */);

    newLocation.setAccuracy(500);

    mLocationManager.setTestProviderEnabled
    (
      LocationManager.GPS_PROVIDER, 
      true
    );

    mLocationManager.setTestProviderStatus
    (
       LocationManager.GPS_PROVIDER,
       LocationProvider.AVAILABLE,
       null,
       System.currentTimeMillis()
    );      

    mLocationManager.setTestProviderLocation
    (
      LocationManager.GPS_PROVIDER, 
      newLocation
    );      
}

1
Buena publicación, vea mi respuesta a continuación para obtener más información.
icyerasor

Hasta donde recuerdo, setTestProviderStatusse usa aquí para notificar / publicar / programar un evento con el LocationManager que el proveedor de GPS ha encontrado una solución "ahora" para que el procesamiento de dicho evento pueda ocurrir.
Dr1Ku

¿Cuál es el significado de " mLocationManageres un LocationManagerque está conectado a un LocationListener"? ¿Cómo puedo hacer esto? Gracias ..
Yehuda

Aquí hay un artículo que explica cómo verificar un cambio de ubicación utilizando el LocationManagerservicio y un LocationListener: blog.doityourselfandroid.com/2010/12/25/…
Dr1Ku

2
más 1 por la forma en que representaste el verdadero (s) y falso (s) en el método addTestProvider
A.Alqadomi

16

Lo que Dr1Ku publicó funciona. Usó el código hoy pero necesitaba agregar más locs. Aquí hay algunas mejoras:

Opcional: en lugar de usar la cadena LocationManager.GPS_PROVIDER, es posible que desee definir su propia constata PROVIDER_NAME y usarla. Cuando se registre para actualizaciones de ubicación, elija un proveedor mediante criterios en lugar de especificarlo directamente como una cadena.

Primero: en lugar de llamar a removeTestProvider, primero verifique si hay un proveedor que se eliminará (para evitar IllegalArgumentException):

if (mLocationManager.getProvider(PROVIDER_NAME) != null) {
  mLocationManager.removeTestProvider(PROVIDER_NAME);
}

Segundo: para publicar más de una ubicación, debe establecer la hora de la ubicación:

newLocation.setTime(System.currentTimeMillis());
...
mLocationManager.setTestProviderLocation(PROVIDER_NAME, newLocation);

También parece haber una prueba de Google que utiliza MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

Otro buen ejemplo de trabajo se puede encontrar en: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

Otro buen artículo es: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 También encontrará un código que realmente funciona para yo en el emulador


Sugerencia genial sobre la definición de su propio proveedor, lo que ocurre con el uso de GPS_PROVIDER es que usted (aparentemente) no puede deshacerse del proveedor simulado (más exactamente, no puede cambiar al GPS normal) hasta que se reinicie. Impresionante publicación también, ¡revisaré las referencias!
Dr1Ku

@ Dr1KU ¿Sigue siendo el caso de que no pueda volver al GPS normal? ¿Eso se especifica en alguna parte?
Kaz Dragon

@KazDragon Ese era el caso en aquel entonces. Por lo que puedo recordar, después de encender el Mock ProviderGPS normal no funcionaría, no pude obtener una solución (estaba probando directamente en un dispositivo). Este puede no ser el caso, ya que muchas cosas han sucedido en Android desde entonces.
Dr1Ku

@ Dr1Ku Ah, bueno, ahora estoy haciendo algo muy similar y recibo resultados similares a los que describiste. Esperaba saber si se trataba de una restricción incorporada en la plataforma o si simplemente me faltaba una llamada de función en alguna parte. Probablemente debería hacer una pregunta sobre esto.
Kaz Dragon el

9

Hay aplicaciones disponibles en Android Market que le permiten especificar una "Ubicación GPS simulada" para su dispositivo.

Busqué en https://market.android.com y encontré una aplicación llamada "Mi ubicación falsa" que funciona para mí.

El proveedor de GPS falso mencionado por Paul anteriormente (en http://www.cowlumbus.nl/forum/MockGpsProvider.zip ) es otro ejemplo que incluye el código fuente, aunque no pude instalar el APK proporcionado (dice Falla) [INSTALL_FAILED_OLDER_SDK] y puede que solo necesite una recompilación)

Para usar ubicaciones simuladas de GPS, debe habilitarlo en la configuración de su dispositivo. Vaya a Configuración -> Aplicaciones -> Desarrollo y marque "Permitir ubicaciones simuladas"

Luego puede usar una aplicación como las descritas anteriormente para establecer las coordenadas GPS y los mapas de Google y otras aplicaciones usarán la ubicación GPS simulada que especifique.


El GPS falso es más simple. Me pregunto por qué solicitan el identificador de llamadas en el permiso de la aplicación: S
Guillaume Massé

8

Esto funcionó para mí (Android Studio):

Desactiva el rastreo de GPS y WiFi en el teléfono. En Android 5.1.1 y versiones inferiores, seleccione "habilitar ubicaciones simuladas" en Opciones de desarrollador.

Haga una copia de su manifiesto en el directorio src / debug. Agregue lo siguiente (fuera de la etiqueta "aplicación"):

usa-permiso android: name = "android.permission.ACCESS_MOCK_LOCATION"

Configure un Fragmento de mapa llamado "mapa". Incluya el siguiente código en onCreate ():

lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
if (lm.getProvider("Test") == null) {
    lm.addTestProvider("Test", false, false, false, false, false, false, false, 0, 1);
}
lm.setTestProviderEnabled("Test", true);
lm.requestLocationUpdates("Test", 0, 0, ll);

map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    @Override
    public void onMapClick(LatLng l) {
        Location loc = new Location("Test");
        loc.setLatitude(l.latitude);
        loc.setLongitude(l.longitude);
        loc.setAltitude(0); 
        loc.setAccuracy(10f);
        loc.setElapsedRealtimeNanos(System.nanoTime());
        loc.setTime(System.currentTimeMillis()); 
        lm.setTestProviderLocation("Test", loc);
    }
};

Tenga en cuenta que es posible que tenga que aumentar temporalmente "minSdkVersion" en el archivo gradle de su módulo a 17 para usar el método "setElapsedRealtimeNanos".

Incluya el siguiente código dentro de la clase de actividad principal:

private class MyLocationListener implements LocationListener {
    @Override
    public void onLocationChanged(Location location) {
        // do whatever you want, scroll the map, etc.
    }
}

Ejecute su aplicación con AS. En Android 6.0 y superior obtendrás una excepción de seguridad. Ahora ve a Opciones de desarrollador en Configuración y selecciona "Seleccionar aplicación de ubicación simulada". Seleccione su aplicación de la lista.

Ahora, cuando tocas el mapa, onLocationChanged () disparará con las coordenadas de tu toque.

Acabo de resolver esto, así que ahora no tengo que caminar por el vecindario con los teléfonos en la mano.


Creo que funciona en Android 6 si pones este código en servicio
Hamza

7

He creado un controlador simple que simula una posición en movimiento desde una posición inicial.

Comience en la devolución de llamada de conexión:

private final GoogleApiClient.ConnectionCallbacks mConnectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
    @Override
    public void onConnected(Bundle bundle) {
        if (BuildConfig.USE_MOCK_LOCATION) {
            LocationServices.FusedLocationApi.setMockMode(mGoogleApiClient, true);
            new MockLocationMovingHandler(mGoogleApiClient).start(48.873399, 2.342911);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }
};

La clase Handler:

   private static class MockLocationMovingHandler extends Handler {

    private final static int SET_MOCK_LOCATION = 0x000001;
    private final static double STEP_LATITUDE =  -0.00005;
    private final static double STEP_LONGITUDE = 0.00002;
    private final static long FREQUENCY_MS = 1000;
    private GoogleApiClient mGoogleApiClient;
    private double mLatitude;
    private double mLongitude;

    public MockLocationMovingHandler(final GoogleApiClient googleApiClient) {
        super(Looper.getMainLooper());
        mGoogleApiClient = googleApiClient;
    }

    public void start(final double initLatitude, final double initLongitude) {
        if (hasMessages(SET_MOCK_LOCATION)) {
            removeMessages(SET_MOCK_LOCATION);
        }
        mLatitude = initLatitude;
        mLongitude = initLongitude;
        sendEmptyMessage(SET_MOCK_LOCATION);
    }

    public void stop() {
        if (hasMessages(SET_MOCK_LOCATION)) {
            removeMessages(SET_MOCK_LOCATION);
        }
    }

    @Override
    public void handleMessage(Message message) {
        switch (message.what) {
            case SET_MOCK_LOCATION:
                Location location = new Location("network");
                location.setLatitude(mLatitude);
                location.setLongitude(mLongitude);
                location.setTime(System.currentTimeMillis());
                location.setAccuracy(3.0f);
                location.setElapsedRealtimeNanos(System.nanoTime());
                LocationServices.FusedLocationApi.setMockLocation(mGoogleApiClient, location);

                mLatitude += STEP_LATITUDE;
                mLongitude += STEP_LONGITUDE;
                sendEmptyMessageDelayed(SET_MOCK_LOCATION, FREQUENCY_MS);
                break;
        }
    }
}

Espero que pueda ayudar ...


6

La solución mencionada por icyerasor y proporcionada por Pedro en http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/ funcionó muy bien para mí. Sin embargo, no ofrece soporte para iniciar, detener y reiniciar correctamente el proveedor de GPS simulado.

He cambiado un poco su código y reescribí la clase para que sea AsyncTask en lugar de Thread. Esto nos permite comunicarnos con el subproceso de interfaz de usuario, por lo que podemos reiniciar el proveedor en el punto donde estábamos cuando lo detuvimos. Esto es útil cuando cambia la orientación de la pantalla.

El código, junto con un proyecto de muestra para Eclipse, se puede encontrar en GitHub: https://github.com/paulhoux/Android-MockProviderGPS

Todo el crédito debe ir a Pedro por hacer la mayor parte del trabajo duro.


6

Añadir a su manifiesto

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
    tools:ignore="MockLocation,ProtectedPermissions" />

Función de ubicación simulada

void setMockLocation() {
    LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false,
            false, false, true, true, true, 0, 5);
    locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);

    Location mockLocation = new Location(LocationManager.GPS_PROVIDER);
    mockLocation.setLatitude(-33.852);  // Sydney
    mockLocation.setLongitude(151.211);
    mockLocation.setAltitude(10);
    mockLocation.setAccuracy(5);
    mockLocation.setTime(System.currentTimeMillis());
    mockLocation.setElapsedRealtimeNanos(System.nanoTime());
    locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockLocation);
}

También deberá habilitar ubicaciones simuladas en la configuración de desarrollador de sus dispositivos. Si eso no está disponible, configure la "aplicación de ubicación simulada" en su aplicación una vez que se haya implementado lo anterior.


3

La aplicación falsa de GPS de Google Play me sirvió. Solo asegúrese de leer todas las instrucciones en la descripción de la aplicación. Debe deshabilitar otros servicios de ubicación, así como iniciar su aplicación después de habilitar "GPS falso". Funcionó muy bien para lo que necesitaba.

Aquí está el enlace a la aplicación en GooglePlay: GPS falso




2

Escribí una aplicación que ejecuta un servidor web (REST-Like) en su teléfono Android, para que pueda configurar la posición del GPS de forma remota . El sitio web proporciona un mapa en el que puede hacer clic para establecer una nueva posición, o usar las teclas "wasd" para moverse en cualquier dirección. La aplicación fue una solución rápida, por lo que casi no hay interfaz de usuario ni documentación, pero la implementación es sencilla y puedes buscar todo en las (solo cuatro) clases.

Repositorio del proyecto: https://github.com/juliusmh/RemoteGeoFix


1

Si su dispositivo está conectado a su computadora y está tratando de cambiar el envío de cables GPS a través del control del emulador, no funcionará.
Este es un control EMULATOR por una razón.
Simplemente configúrelo para actualizarlo en el cambio de GPS.

lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);  

    ll = new LocationListener() {        
        public void onLocationChanged(Location location) {  
          // Called when a new location is found by the network location provider.  
            onGPSLocationChanged(location); 
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {       
            bigInfo.setText("Changed "+ status);  
        }

        public void onProviderEnabled(String provider) {
            bigInfo.setText("Enabled "+ provider);
        }

        public void onProviderDisabled(String provider) {
            bigInfo.setText("Disabled "+ provider);
        }
      };

Cuando se actualiza el GPS, vuelva a escribir el siguiente método para hacer lo que desea;

public void onGPSLocationChanged(Location location){  
if(location != null){  
    double pLong = location.getLongitude();  
    double pLat = location.getLatitude();  
    textLat.setText(Double.toString(pLat));  
    textLong.setText(Double.toString(pLong));  
    if(autoSave){  
        saveGPS();  
        }
    }
}

No olvide poner estos en el manifiesto
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION


0

Me pregunto si necesita la configuración elaborada de Mock Location. En mi caso, una vez que obtuve una ubicación fija, estaba llamando a una función para hacer algo con esa nueva ubicación. En un temporizador, crea una ubicación simulada. Y llame a la función con esa ubicación en su lugar. Sabiendo todo el tiempo que en poco tiempo el GPS generaría una ubicación actual real. Lo cual está bien. Si tiene el tiempo de actualización establecido suficientemente largo.


0

Tal vez no sea un enfoque de "programador", pero si desea ahorrar tiempo y obtener una solución de trabajo instantánea, pruebe una de las aplicaciones dedicadas a la ubicación simulada disponible en Google Play:

Fake GPS Location Spoofer

Ubicaciones simuladas

Ubicación GPS falsa


1
¿Los probaste? ¿Funcionaron según lo solicitado en la pregunta?
arekolek

Alguna preferencia? ¿O uno los necesita a todos? : P
arekolek

Fake GPS Location Spoofer es lo suficientemente bueno, pero Mock Locations permite establecer una ruta que es una buena característica.
klimat


0

Use este permiso en el archivo de manifiesto

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION">

Android Studio recomendará que "la ubicación simulada solo se solicite en un archivo de manifiesto de prueba o de depuración específico (generalmente src / debug / AndroidManifest.xml)" simplemente deshabilite la inspección

Ahora asegúrese de haber marcado la opción " Permitir ubicaciones falsas " en la configuración de desarrollador de su teléfono

Usar LocationManager

locationManager.addTestProvider(mocLocationProvider, false, false,
                false, false, true, true, true, 0, 5);
locationManager.setTestProviderEnabled(mocLocationProvider, true);

Ahora configura la ubicación donde quieras

Location mockLocation = new Location(mocLocationProvider); 
mockLocation.setLatitude(lat); 
mockLocation.setLongitude(lng); 
mockLocation.setAltitude(alt); 
mockLocation.setTime(System.currentTimeMillis()); 
locationManager.setTestProviderLocation( mocLocationProvider, mockLocation); 

0

Las soluciones anteriores no me funcionaron porque estaba probando en un dispositivo Android con la última versión de Google Play Services que utiliza el cliente FusedLocationProviderClient . Después de configurar el permiso de ubicación simulada en el manifiesto de la aplicación y la aplicación como la aplicación de ubicación simulada especificada en la configuración del desarrollador (como se menciona en las respuestas anteriores), agregué el código de Kotlin a continuación que se burló con éxito de la ubicación.

locationProvider = FusedLocationProviderClient(context)
locationProvider.setMockMode(true)

val loc = Location(providerName)
val mockLocation = Location(providerName) // a string
mockLocation.latitude = latitude  // double
mockLocation.longitude = longitude
mockLocation.altitude = loc.altitude
mockLocation.time = System.currentTimeMillis()
mockLocation.accuracy = 1f
mockLocation.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    mockLocation.bearingAccuracyDegrees = 0.1f
    mockLocation.verticalAccuracyMeters = 0.1f
    mockLocation.speedAccuracyMetersPerSecond = 0.01f
}
//        locationManager.setTestProviderLocation(providerName, mockLocation)
locationProvider.setMockLocation(mockLocation)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.