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.
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.
Respostas:
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.
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.
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ê 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);
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 LocationManager
que 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
);
}
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.
mLocationManager
é um LocationManager
que está conectado a um LocationListener"? como posso fazer isso? Obrigado ..
LocationManager
serviço e LocationListener
: blog.doityourselfandroid.com/2010/12/25/…
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.
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.
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.
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 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 ..
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.
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.
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
O tutorial do Google para fazer isso pode ser encontrado aqui, fornece exemplos de código e explica o processo.
http://developer.android.com/training/location/location-testing.html#SendMockLocations
Instale o aplicativo GPS falso https://play.google.com/store/apps/details?id=com.incorporateapps.fakegps.fre&hl=en
Opções do desenvolvedor -> Selecione o aplicativo de localização simulada (é mau, o aplicativo de localização falsa está selecionado).
Aplicativo GPS falso :
Clique duas vezes no mapa para adicionar -> clique no botão play -> mostre a torrada "Localização falsa parada"
finalmente verifique com os aplicativos de mapas do Google.
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
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
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.
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:
Utilize o simulador de localização interativa gratuito e muito conveniente para telefones e tablets Android (chamado CATLES). Zomba da localização do GPS em todo o sistema (mesmo nos aplicativos do Google Maps ou do Facebook) e funciona em dispositivos físicos e virtuais:
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);
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)