Localização simulada Android no dispositivo?


147

Como posso zombar da minha localização em um dispositivo físico (Nexus One)? Eu sei que você pode fazer isso com o emulador no painel de controle do emulador, mas isso não funciona para um dispositivo físico.


Para computadores de mesa, você pode criar / instalar drivers que emulam um dispositivo GPS / dispositivo de porta serial com a finalidade de realizar esse tipo de teste. Talvez você possa criar ou encontrar algo semelhante para o Android.
AaronLS

6
Existem várias aplicações no Market que podem emular a localização do GPS. Por exemplo "Localização spoofer".
Vlad

Existem muitos aplicativos na loja que fazem isso. Você pode tentar isso - play.google.com/store/apps/… ou isto - play.google.com/store/apps/…
Yehuda

1
Há também um aplicativo na loja que suporta os comandos "geo fix" e "geo nmea", assim como o emulador! play.google.com/store/apps/…
luv

@Iuv mais sobre ele é de código aberto github.com/luv/mockgeofix
Vlad

Respostas:


166

Parece que a única maneira de fazer é usar um provedor de localização simulado.

Você precisa habilitar locais simulados no painel de desenvolvimento em suas configurações e adicionar

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

para o seu manifesto.

Agora você pode inserir seu código e criar seu próprio provedor de localização simulada e definir o local desse provedor.


83
Existe uma aplicação no mercado chamada "GPS falso". Se você ativar locais simulados no seu dispositivo, ele oferece uma boa interface gráfica para definir sua localização. Sei que essa não é uma solução "faça você mesmo", mas certamente uma solução valiosa para testes rápidos.
Tim Green

2
esse pode ser o link - mesma data e conteúdo relevante.
amigos estão

4
O @ TimGreen deve ser a resposta aceita (não apenas um comentário)! De longe a maneira mais fácil de testar
Bostone

Na verdade, o aplicativo "GPS falso" não é o melhor, pois só pode definir locais e se mover aleatoriamente. Sua nova versão pode rotear, mas apenas itera sobre pontos de passagem, saltos enormes no local. A resposta de Janusz é realmente correta: você precisa criar seu próprio provedor de simulação. Recentemente, fizemos isso e se alguém precisar ou se essa pergunta ainda precisar de ajuda, postarei o código.
vkinra

5
A declaração "insira seu código e crie seu próprio provedor de localização simulada" deve ser explicada em mais detalhes.
Dims 16/02

102

Se você usar este telefone apenas no laboratório de desenvolvimento, é possível soldar o chip GPS e alimentar a porta serial diretamente com sequências NMEA de outro dispositivo.


68
Por que os inimigos? Esta resposta é incrivelmente difícil.
Ben Zotto

61
Incrivelmente incondicional, embora incrivelmente inútil / irrelevante também.
olivervbk

13
Divertido o suficiente, no entanto.
Etienne

23
hum, acho que alguém para quem essa resposta seria relevante, já sabe que pode fazer isso. Duvido que essas três pessoas estejam procurando uma solução no stackoverflow.
Página

10
Se você tiver problemas para descobrir como gerar sequências NMEA realistas em seu dispositivo não vendido, há uma opção incrível: soldar um dispositivo GPS externo real e mover todo o laboratório de desenvolvimento em uma pista real, em cima de uma equipe de corredores / ciclistas / carros / aviões / o que for, dependendo da velocidade que você deseja simular. Não se esqueça de abrir um buraco no teto do laboratório de desenvolvimento para que o dispositivo possa receber sinais de rádio de satélites. De nada. ;-)
Stéphane Gourichon

32

Eu gostaria de ter meu cabo à mão. Eu sei que você pode telnetar para o emulador para mudar sua localização

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

Não me lembro se você pode telnetar para o seu dispositivo, mas acho que sim. Eu espero que isso ajude.

Você precisará do adb (ponte de depuração do Android) para isso (CLI).


você recebe uma permissão negada para tudo o que você envia como um comando para o console do seu dispositivo. Talvez seja possível com uma aplicação de terminal, mas eu acho que requer acesso root
Janusz

Só estamos na mesma página: você não está falando sobre "adb shell", está? O que eu estou falando é diferente, isso é algo que permite definir parâmetros específicos do Android. Eu sei, por exemplo, que você pode configurar o encaminhamento de porta (por exemplo, localhost: 1234 vai para o telefone: 1234) sem acesso root, para que você possa configurar um proxy SOCKS e encapsular através de um cabo sem raiz.
Tim Green

Você pode usar o adb forward tcp: 6000 tcp: 23 para encaminhar a porta 6000 na sua máquina para a porta 23 no dispositivo, mas não consegui conectar, mesmo que a porta seja exibida como aberta. Usando um cliente telnet no dispositivo e conectar à localhost também falhar
Janusz

15
Isso funciona bem para o emulador, mas não funciona para um dispositivo real. Portanto, ele não responde à pergunta do OP :(
Matthew Gilliard

4
@ TimGreen Sua solução é apenas para emulador. A pergunta era sobre dispositivo real.
IgorGanapolsky

29

Você pode usar a permissão dos Serviços de Localização para simular a localização ...

"android.permission.ACCESS_MOCK_LOCATION"

e depois no seu 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
qual é o valor de mocLocationProvider?
Victor

por exemplo LocationManager.GPS_PROVIDER
enigma969 12/11

25

Eu tive sucesso com o seguinte código. Embora tenha conseguido um bloqueio único por algum motivo (mesmo que eu tenha tentado diferentes pares de LatLng), funcionou para mim. mLocationManageré um LocationManagerque está conectado a um 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
Bom post, veja minha resposta abaixo para adições.
precisa saber é o seguinte

Tanto quanto me lembro, setTestProviderStatusé usado aqui para notificar / postar / agendar um evento com o LocationManager de que o provedor de GPS encontrou uma correção "agora" para que o processamento do referido evento possa ocorrer.
Dr1Ku

Qual é o significado de " mLocationManageré um LocationManagerque está conectado a um LocationListener"? como posso fazer isso? Obrigado ..
Yehuda

Aqui está um artigo explicando como verificar uma alteração de local usando o LocationManagerserviço e LocationListener: blog.doityourselfandroid.com/2010/12/25/…
Dr1Ku

2
mais 1 para a maneira que você representava os verdadeiros (s) e falso (s) no addTestProvider método
A.Alqadomi

16

O que o Dr1Ku postou funciona. Usou o código hoje, mas precisava adicionar mais locais. Então, aqui estão algumas melhorias:

Opcional: Em vez de usar a String LocationManager.GPS_PROVIDER, convém definir sua própria constante PROVIDER_NAME e usá-la. Ao se registrar para atualizações de local, escolha um provedor por critérios, em vez de especificá-lo diretamente como uma sequência.

Primeiro: em vez de chamar removeTestProvider, verifique primeiro se há um provedor a ser removido (para evitar IllegalArgumentException):

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

Segundo: para publicar mais de um local, é necessário definir o horário do local:

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

Também parece haver um teste do Google que usa MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

Outro bom exemplo de trabalho pode ser encontrado em: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

Outro bom artigo é: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 Você também encontrará algum código que realmente funciona para eu no emulador.


Sugestão interessante sobre como definir seu próprio provedor, o problema com o GPS_PROVIDER é que você (aparentemente) não pode se livrar do provedor falso (mais exatamente, você não pode mudar para o GPS normal) até a reinicialização. Post incrível também, vou conferir as referências!
Dr1Ku

@ Dr1KU Ainda não é possível voltar ao GPS normal? Isso está especificado em algum lugar?
quer

@KazDragon Esse era o caso naquela época. Pelo que me lembro, depois de ligar Mock Provider, o GPS normal não funcionava, não consegui uma solução (estava testando diretamente em um dispositivo). Pode não ser esse o caso, já que muita coisa aconteceu no Android desde então.
Dr1Ku

@ Dr1Ku Ah, bem, agora estou fazendo algo muito semelhante e recebendo resultados semelhantes aos que você descreveu. Eu esperava saber se isso era uma restrição incorporada à plataforma ou se estava faltando uma chamada de função em algum lugar. Eu provavelmente deveria fazer uma pergunta com isso.
Kaz Dragão

9

Existem aplicativos disponíveis no Android Market que permitem especificar um "Local simulado para GPS" para o seu dispositivo.

Pesquisei https://market.android.com e encontrei um aplicativo chamado "Meu local falso" que funciona para mim.

O provedor de GPS Mock mencionado por Paul acima (em http://www.cowlumbus.nl/forum/MockGpsProvider.zip ) é outro exemplo que inclui o código-fonte - embora eu não tenha conseguido instalar o APK fornecido (ele diz Failure [INSTALL_FAILED_OLDER_SDK] e pode precisar apenas de uma recompilação)

Para usar locais simulados do GPS, você precisa habilitá-lo nas configurações do seu dispositivo. Vá para Configurações -> Aplicativos -> Desenvolvimento e marque "Permitir locais simulados"

Você pode usar um aplicativo como os descritos acima para definir coordenadas GPS e o Google Maps e outros aplicativos usarão a localização GPS simulada que você especificar.


GPS falso é mais simples. Eu só estou querendo saber por que eles estão pedindo identificador de chamadas na permissão app: S
Guillaume Massé

8

Isso funcionou para mim (Android Studio):

Desative o rastreamento GPS e Wi-Fi no telefone. No Android 5.1.1 e abaixo, selecione "ativar locais simulados" em Opções do desenvolvedor.

Faça uma cópia do seu manifesto no diretório src / debug. Adicione o seguinte a ele (fora da tag "application"):

usa-permissão android: name = "android.permission.ACCESS_MOCK_LOCATION"

Configure um fragmento de mapa chamado "mapa". Inclua o seguinte código em 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);
    }
};

Observe que talvez você precise aumentar temporariamente "minSdkVersion" no arquivo gradle do módulo para 17 para usar o método "setElapsedRealtimeNanos".

Inclua o seguinte código na classe de atividade principal:

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

Execute seu aplicativo com o AS. No Android 6.0 e superior, você receberá uma exceção de segurança. Agora vá para Opções do desenvolvedor em Configurações e selecione "Selecionar aplicativo de localização simulada". Selecione seu aplicativo na lista.

Agora, quando você toca no mapa, onLocationChanged () é acionado com as coordenadas da sua torneira.

Eu descobri isso agora e agora não tenho que andar pelo bairro com telefones na mão.


Eu acho que trabalhar em android 6 se você colocar esse código em serviço
Hamza

7

Eu criei um manipulador simples simulando uma posição móvel de uma posição inicial.

Inicie-o no retorno de chamada da conexão:

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) {

    }
};

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

Espero que possa ajudar ..


6

A solução mencionada por icyerasor e fornecida por Pedro em http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/ funcionou muito bem para mim. No entanto, ele não oferece suporte para iniciar, parar e reiniciar corretamente o provedor de GPS falso.

Alterei um pouco o código dele e reescrevi a classe para ser um AsyncTask em vez de um Thread. Isso nos permite comunicar com o thread da interface do usuário, para que possamos reiniciar o provedor no ponto em que estávamos quando o interrompemos. Isso é útil quando a orientação da tela muda.

O código, junto com um projeto de amostra para Eclipse, pode ser encontrado no GitHub: https://github.com/paulhoux/Android-MockProviderGPS

Todo o crédito deve ser dado a Pedro por fazer a maior parte do trabalho duro.


6

Adicione ao seu manifesto

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

Função de localização 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);
}

Você também precisará ativar locais simulados nas configurações de desenvolvedor de seus dispositivos. Se não estiver disponível, defina o "aplicativo de localização simulada" para o seu aplicativo depois que o acima for implementado.


3

O aplicativo GPS falso do Google Play fez o truque para mim. Certifique-se de ler todas as instruções na descrição do aplicativo. Você precisa desativar outros serviços de localização e iniciar o aplicativo depois de ativar o "GPS falso". Funcionou muito bem para o que eu precisava.

Aqui está o link para o aplicativo no GooglePlay: GPS falso




2

Eu escrevi um aplicativo que executa um servidor Web (semelhante ao REST) ​​no seu telefone Android, para que você possa definir a posição do GPS remotamente . O site fornece um mapa no qual você pode clicar para definir uma nova posição ou usar as teclas "wasd" para se mover em qualquer direção. O aplicativo foi uma solução rápida, por isso quase não há interface do usuário nem documentação, mas a implementação é direta e você pode pesquisar tudo nas (apenas quatro) classes.

Repositório do projeto: https://github.com/juliusmh/RemoteGeoFix


1

Se o seu dispositivo estiver conectado ao computador e você tentar alterar os cabos de GPS através do controle Emulador, ele não funcionará.
Este é um controle EMULATOR por um motivo.
Basta configurá-lo para atualizar você sobre a alteração do 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 o GPS é atualizado, reescreva o método a seguir para fazer o que você deseja;

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

Não se esqueça de colocá-los no manifesto
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION


0

Gostaria de saber se você precisa da configuração elaborada do Mock Location. No meu caso, quando obtive um local fixo, estava chamando uma função para fazer algo com esse novo local. Em um cronômetro, crie um local simulado. E chame a função com esse local. Sabendo disso o tempo todo, o GPS apresentaria uma localização atual real. O que está bom. Se você tiver o tempo de atualização definido o tempo suficiente.


0

Talvez não seja uma abordagem de 'programador', mas se você deseja economizar seu tempo e obter uma solução operacional instantânea, tente um dos aplicativos dedicados à localização simulada disponíveis no Google Play:

Spoofer falso da localização de GPS

Mock Locations

Localização GPS falsa


1
Você experimentou? Eles trabalharam conforme solicitado na pergunta?
23917 arekolek

Alguma preferência? Ou alguém precisa de todos eles? : P
arekolek

O GPS falso Spoofer de localização é bom o suficiente, mas o Mock Locations permite definir uma rota que é um recurso interessante.
klimat


0

Use esta permissão no arquivo de manifesto

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

O android studio recomendará que "O local simulado deve ser solicitado apenas em um arquivo de manifesto específico de teste ou depuração (normalmente src / debug / AndroidManifest.xml)" apenas desative a inspeção

Agora, verifique se você marcou a opção " Permitir locais simulados " na configuração do desenvolvedor do seu telefone

Use LocationManager

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

Agora defina o local onde quiser

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

0

As soluções acima não funcionaram para mim porque eu estava testando em um dispositivo Android com a versão mais recente do Google Play Services, que utiliza o FusedLocationProviderClient . Depois de definir a permissão de localização simulada no manifesto do aplicativo e o aplicativo como o aplicativo de localização simulada especificado nas configurações do desenvolvedor (conforme mencionado nas respostas anteriores), adicionei o código Kotlin abaixo, que simulava com êxito o local.

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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.