Posizione fittizia Android sul dispositivo?


147

Come posso deridere la mia posizione su un dispositivo fisico (Nexus One)? So che puoi farlo con l'emulatore nel pannello di controllo dell'emulatore, ma questo non funziona per un dispositivo fisico.


Per i computer desktop è possibile creare / installare driver che emulano un dispositivo GPS / dispositivo porta seriale allo scopo di eseguire questo tipo di test. Forse potresti creare o trovare qualcosa di simile per Android.
AaronLS

6
Esistono diverse applicazioni nel mercato che possono emulare la posizione GPS. Ad esempio "Location spoofer".
Vlad

Ci sono molte app nel negozio che lo fanno. Puoi provare questo - play.google.com/store/apps/… o questo - play.google.com/store/apps/…
Yehuda

1
C'è anche un'app nello store che supporta i comandi "geo fix" e "geo nmea" proprio come l'emulatore! play.google.com/store/apps/…
luv

@Iuv più su di esso è open source github.com/luv/mockgeofix
Vlad

Risposte:


166

Sembra che l'unico modo per fare sia usare un provider di localizzazione fittizia.

Devi abilitare posizioni simulate nel pannello di sviluppo nelle tue impostazioni e aggiungere

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

al tuo manifest.

Ora puoi inserire il tuo codice e creare il tuo provider di posizioni fittizie e impostare la posizione di questo provider.


83
Esiste sul mercato un'applicazione chiamata "GPS falso". Se abiliti Posizioni fittizie sul tuo dispositivo, offre una buona interfaccia grafica per l'impostazione della tua posizione. Mi rendo conto che questa non è una soluzione fai-da-te, ma sicuramente una soluzione degna per test rapidi.
Tim Green,

2
questo potrebbe essere il collegamento: stessa data e contenuto pertinente.
DefenestrationDay

4
@TimGreen la tua dovrebbe essere la risposta accettata (non solo un commento)! Di gran lunga il modo più semplice per testare
Bostone il

In realtà l'applicazione "fake gps" non è la migliore perché può solo impostare posizioni e spostarsi casualmente. La loro nuova versione può instradare ma itera solo su punti intermedi così enormi salti nella posizione. La risposta di Janusz è davvero corretta che è necessario creare il proprio provider di simulazione. L'abbiamo fatto di recente e se qualcuno ne ha bisogno o se questa domanda ha ancora bisogno di aiuto, posterò il codice.
Vkinra,

5
L'affermazione "inserisci il tuo codice e crea il tuo provider di posizioni fittizie" dovrebbe essere spiegata in modo più dettagliato.
Dimmer

102

Se si utilizza questo telefono solo nel laboratorio di sviluppo, è possibile saldare il chip GPS e alimentare la porta seriale direttamente con sequenze NMEA da altri dispositivi.


68
Perché gli odiatori? Questa risposta è incredibilmente dura.
Ben Zotto,

61
Incredibilmente hardcore anche se incredibilmente inutile / irrilevante.
olivervbk,

13
Abbastanza divertente, però.
etienne

23
ehm, penso che chiunque per cui questa risposta sia pertinente, sappia già che può farlo. Dubito che queste tre persone stiano cercando una soluzione per StackOverflow.
ToolmakerSteve

10
Se hai difficoltà a capire come generare sequenze NMEA realistiche nel tuo dispositivo non saldato, c'è un'opzione fantastica: saldare lì un dispositivo GPS esterno reale e spostare l'intero laboratorio di sviluppo su una pista reale, in cima a una squadra di corridori / motociclisti / auto / aerei / qualunque cosa a seconda della velocità che si desidera simulare. Non dimenticare di aprire un buco nel tetto del laboratorio di sviluppo in modo che il dispositivo possa ricevere segnali radio dai satelliti. Prego. ;-)
Stéphane Gourichon,

32

Vorrei avere il cavo a portata di mano. So che puoi telnet all'emulatore per cambiare la sua posizione

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

Non ricordo se puoi telnet sul tuo dispositivo, ma penso che tu possa farlo. Spero che aiuti.

Per questo (CLI) è necessario adb (ponte di debug Android).


ricevi un'autorizzazione negata a tutto ciò che invii come comando alla console del tuo dispositivo. Forse è possibile con un'applicazione terminale, ma penso che richieda l'accesso come root
Janusz,

Solo così siamo sulla stessa pagina: non stai parlando di "adb shell", vero? Quello di cui sto parlando è diverso, questa è una configurazione che ti consente di impostare parametri specifici di Android. So, ad esempio, che è possibile impostare il port forwarding (ovvero localhost: 1234 va al telefono: 1234) senza accesso root, quindi è possibile impostare un proxy SOCKS e un tunnel tramite un cavo senza root.
Tim Green

È possibile utilizzare adb forward tcp: 6000 tcp: 23 per inoltrare la porta 6000 sulla propria macchina alla porta 23 sul dispositivo, ma non sono stato in grado di connettersi anche se la porta è mostrata come aperta. Anche l'utilizzo di un client Telnet sul dispositivo e la connessione a localhost falliscono
Janusz,

15
Funziona bene con l'emulatore ma non funziona con un dispositivo reale. Quindi non risponde affatto alla domanda di OP :(
Matthew Gilliard,

4
@TimGreen La tua soluzione è solo per l'emulatore. La domanda riguardava il dispositivo reale.
IgorGanapolsky,

29

È possibile utilizzare l'autorizzazione dei servizi di localizzazione per deridere la posizione ...

"android.permission.ACCESS_MOCK_LOCATION"

e poi nel tuo codice 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
che valore ha mocLocationProvider?
Victor,

ad es. LocationManager.GPS_PROVIDER
enigma969,

25

Ho avuto successo con il seguente codice. Anche se mi ha dato un unico lucchetto per qualche motivo (anche se ho provato diverse coppie di LatLng), ha funzionato per me. mLocationManagerè un LocationManagerche è collegato 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
Bel post, vedi la mia risposta qui sotto per le aggiunte.
icyerasor,

Per quanto ricordo, setTestProviderStatusviene utilizzato qui per notificare / postare / pianificare un evento con il LocationManager che il provider GPS ha trovato una correzione "adesso" in modo che possa avvenire l'elaborazione di detto evento.
Dr1Ku,

Qual è il significato di " mLocationManageris a LocationManagerche è collegato a un LocationListener"? come posso fare questo? Grazie ..
Yehuda, il

Ecco un articolo che spiega come verificare la presenza di un cambio di posizione utilizzando il LocationManagerservizio e un LocationListener: blog.doityourselfandroid.com/2010/12/25/…
Dr1Ku

2
più 1 per il modo in cui hai rappresentato il / i vero / i e il / i falso / i nel metodo addTestProvider
A.Alqadomi il

16

Ciò che Dr1Ku ha pubblicato funziona. Oggi ho usato il codice ma dovevo aggiungere più loc. Quindi, ecco alcuni miglioramenti:

Facoltativo: anziché utilizzare la stringa LocationManager.GPS_PROVIDER, potresti voler definire la tua constat PROVIDER_NAME e usarla. Quando ti registri per gli aggiornamenti di posizione, scegli un provider tramite i criteri invece di specificarlo direttamente come stringa.

Primo: invece di chiamare removeTestProvider, prima controlla se c'è un provider da rimuovere (per evitare IllegalArgumentException):

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

Secondo: per pubblicare più di una posizione, è necessario impostare l'orario per la posizione:

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

Sembra anche che ci sia un test di Google che utilizza MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

Un altro buon esempio di lavoro è disponibile all'indirizzo: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

Un altro buon articolo è: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 Troverai anche del codice che funziona davvero per io sull'emulatore.


Fantastico suggerimento sulla definizione del proprio provider, la cosa migliore con l'uso di GPS_PROVIDER è che (apparentemente) non è possibile liberarsi del provider fittizio (più precisamente, non è possibile passare al normale GPS) fino al riavvio. Fantastico post, controllerò i riferimenti!
Dr1Ku,

@ Dr1KU È ancora possibile non tornare al normale GPS? È specificato da qualche parte?
Kaz Dragon,

@KazDragon Allora era il caso. Da quello che posso ricordare, dopo aver Mock Provideracceso il normale GPS non funzionava, non riuscivo a ottenere una correzione (stavo testando direttamente su un dispositivo). Questo potrebbe non essere il caso poiché da allora sono successe molte cose in Android.
Dr1Ku,

@ Dr1Ku Ah, bene, sto facendo qualcosa di molto simile ora e sto ricevendo risultati simili a quelli che hai descritto. Speravo di sapere se si trattava di una limitazione integrata nella piattaforma o che mi mancava una chiamata di funzione da qualche parte. Probabilmente dovrei fare una domanda al riguardo.
Kaz Dragon,

9

Esistono app disponibili in Android Market che ti consentono di specificare una "Posizione GPS fittizia" per il tuo dispositivo.

Ho cercato https://market.android.com e trovato un'app chiamata "La mia posizione falsa" che funziona per me.

Il provider GPS Mock menzionato da Paul sopra (su http://www.cowlumbus.nl/forum/MockGpsProvider.zip ) è un altro esempio che include il codice sorgente, anche se non sono stato in grado di installare l'APK fornito (dice Failure [INSTALL_FAILED_OLDER_SDK] e potrebbe essere necessario solo ricompilare)

Per utilizzare posizioni simulate GPS è necessario abilitarlo nelle impostazioni del dispositivo. Vai su Impostazioni -> Applicazioni -> Sviluppo e seleziona "Consenti posizioni fittizie"

È quindi possibile utilizzare un'app come quelle sopra descritte per impostare le coordinate GPS e Google Maps e altre app useranno la posizione GPS finta specificata.


Il falso GPS è più semplice. Mi chiedo solo perché stanno chiedendo l'id chiamante nell'autorizzazione dell'app: S
Guillaume Massé,

8

Questo ha funzionato per me (Android Studio):

Disabilita il tracciamento GPS e WiFi sul telefono. Su Android 5.1.1 e versioni precedenti, seleziona "abilita posizioni simulate" in Opzioni sviluppatore.

Crea una copia del tuo manifest nella directory src / debug. Aggiungere quanto segue (al di fuori del tag "applicazione"):

usi-permesso android: name = "android.permission.ACCESS_MOCK_LOCATION"

Imposta un frammento di mappa chiamato "mappa". Includi il seguente codice in 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);
    }
};

Si noti che potrebbe essere necessario aumentare temporaneamente "minSdkVersion" nel file di gradle del modulo su 17 per utilizzare il metodo "setElapsedRealtimeNanos".

Includi il codice seguente nella classe di attività principale:

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

Esegui la tua app con AS. Su Android 6.0 e versioni successive otterrai un'eccezione di sicurezza. Ora vai su Opzioni sviluppatore in Impostazioni e seleziona "Seleziona app di posizione fittizia". Seleziona la tua app dall'elenco.

Ora quando tocchi sulla mappa, onLocationChanged () si attiva con le coordinate del tuo tocco.

L'ho appena capito, quindi ora non devo andare in giro per il quartiere con i telefoni in mano.


penso che funzioni su Android 6 se metti questo codice in servizio
Hamza,

7

Ho creato un semplice gestore simulando una posizione mobile da una posizione iniziale.

Avviarlo nel callback della connessione:

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

Spero che possa aiutare ..


6

La soluzione menzionata da icyerasor e fornita da Pedro all'indirizzo http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/ ha funzionato molto bene per me. Tuttavia, non offre supporto per l'avvio, l'arresto e il riavvio corretti del provider GPS finto.

Ho modificato un po 'il suo codice e riscritto la classe in modo che fosse un AsyncTask anziché un thread. Questo ci consente di comunicare con il thread dell'interfaccia utente, in modo da poter riavviare il provider nel punto in cui eravamo quando lo abbiamo interrotto. Questo è utile quando cambia l'orientamento dello schermo.

Il codice, insieme a un progetto di esempio per Eclipse, è disponibile su GitHub: https://github.com/paulhoux/Android-MockProviderGPS

Tutto il merito dovrebbe essere affidato a Pedro per aver svolto gran parte del duro lavoro.


6

Aggiungi al tuo manifest

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

Funzione di localizzazione fittizia

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

Dovrai anche abilitare posizioni simulate nelle impostazioni dello sviluppatore dei tuoi dispositivi. Se questo non è disponibile, imposta "finta applicazione di localizzazione" sulla tua applicazione una volta implementato quanto sopra.


3

La falsa app GPS di Google Play ha fatto il trucco per me. Assicurati di leggere tutte le indicazioni nella descrizione dell'app. Devi disabilitare altri servizi di localizzazione e avviare l'app dopo aver abilitato "Fake GPS". Ha funzionato alla grande per quello che mi serviva.

Ecco il link all'app su Google Play: GPS falso




2

Ho scritto un'app che esegue un WebServer (simile a REST) ​​sul tuo telefono Android, in modo da poter impostare la posizione GPS da remoto . Il sito Web fornisce una mappa su cui è possibile fare clic per impostare una nuova posizione o utilizzare i tasti "wasd" per spostarsi in qualsiasi direzione. L'app è stata una soluzione rapida, quindi non c'è quasi nessuna interfaccia utente né documentazione, ma l'implementazione è semplice e puoi cercare tutto nelle (solo quattro) classi.

Archivio del progetto: https://github.com/juliusmh/RemoteGeoFix


1

Se il dispositivo è collegato al computer e si sta tentando di modificare i cavi di invio GPS tramite il controllo dell'emulatore, non funzionerà.
Questo è un controllo EMULATOR per un motivo.
Basta configurarlo per aggiornarti sul cambio 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);
        }
      };

Quando il GPS viene aggiornato, riscrivi il seguente metodo per fare ciò che desideri;

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

Non dimenticare di metterli nel manifest
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION


0

Mi chiedo se hai bisogno dell'elaborata configurazione di Mock Location. Nel mio caso, una volta trovata una posizione fissa, chiamavo una funzione per fare qualcosa con quella nuova posizione. In un timer creare una posizione simulata. E chiama invece la funzione con quella posizione. Sapendo tutto questo in breve tempo il GPS avrebbe trovato una posizione reale reale. Che va bene Se il tempo di aggiornamento è impostato su un tempo sufficientemente lungo.


0

Forse non è un approccio da "programmatore", ma se vuoi risparmiare tempo e trovare subito una soluzione funzionante prova una delle app dedicate alla posizione simulata disponibili in Google Play:

Spoofer di posizione GPS falso

Posizioni simulate

Posizione GPS falsa


1
Li hai provati? Hanno funzionato come richiesto nella domanda?
Arekolek,

Qualche preferenza? O uno ha bisogno di tutti loro? : P
arekolek,

Posizione falsa GPS Lo spoiler è abbastanza buono, ma Posizioni simulate consente di impostare un percorso che è una bella funzionalità.
klimat,


0

Utilizzare questa autorizzazione nel file manifest

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

Android Studio raccomanderà che "La posizione simulata dovrebbe essere richiesta solo in un file manifest specifico per test o debug (in genere src / debug / AndroidManifest.xml)" disabilita semplicemente l'ispezione

Ora assicurati di aver selezionato " Consenti posizioni simulate " nelle impostazioni dello sviluppatore del tuo telefono

Usa LocationManager

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

Ora imposta la posizione dove vuoi

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

0

Le soluzioni di cui sopra non hanno funzionato per me perché stavo testando su un dispositivo Android con l'ultima versione di Google Play Services che utilizza FusedLocationProviderClient . Dopo aver impostato l'autorizzazione di posizione fittizia nel manifest dell'app e l'app come app di posizione fittizia specificata nelle impostazioni dello sviluppatore (come menzionato nelle risposte precedenti), ho quindi aggiunto il codice Kotlin di seguito che ha deriso correttamente la posizione.

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.