设备上的Android模拟位置?


147

如何模拟我在物理设备(Nexus One)上的位置?我知道您可以使用“模拟器控制”面板中的模拟器来执行此操作,但这不适用于物理设备。


对于台式计算机,您可以创建/安装用于模拟GPS设备/串行端口设备的驱动程序,以进行此类测试。也许您可以为Android创建或找到类似的东西。
AaronLS 2010年

6
电子市场中有几个可以模拟GPS位置的应用程序。例如“位置欺骗者”。
弗拉德

有很多在做这个商店的应用程序。你可以试试这个- play.google.com/store/apps/...或本- play.google.com/store/apps/...
耶胡达

1
商店中还有一个应用程序,它支持“ geo fix”和“ geo nmea”命令,就像模拟器一样!play.google.com/store/apps/...
LUV

@Iuv更超过它是开源的github.com/luv/mockgeofix
弗拉德

Answers:


166

看来唯一的方法是使用模拟位置提供程序。

您必须在设置的开发面板中启用模拟位置,然后添加

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

到你的清单。

现在,您可以输入代码并创建自己的模拟位置提供程序,并设置该提供程序的位置。


83
市场上有一个名为“ Fake GPS”的应用程序。如果您在设备上启用了“模拟位置”,它将提供一个漂亮的GUI来设置您的位置。我意识到这不是一个自己动手的解决方案,但肯定是一个值得快速测试的解决方案。
格林

2
可能是链接-相同的日期和相关内容。
DefenestrationDay

4
@TimGreen您的答案应该是被接受的(不仅仅是评论)!到目前为止,最简单的测试方法
波士顿

实际上,“ fake gps”应用程序不是最好的,因为它只能设置位置并随机移动。他们的新版本可以路由,但只能在航路点上迭代,因此位置会产生巨大的跳跃。Janusz的回答确实是正确的,您需要创建自己的模拟提供程序。我们最近这样做了,如果有人需要它,或者如果这个问题仍然需要帮助,我将发布代码。
vkinra

5
应该更详细地解释“进入您的代码并创建自己的模拟位置提供程序”语句。
昏暗的人,

102

如果您仅在开发实验室中使用此手机,则有可能您可以焊接掉GPS芯片,并直接将其他设备的NMEA序列馈入串行端口。


68
为什么讨厌?这个答案非常难。
Ben Zotto

61
超级铁杆,虽然也没用/无关紧要。
olivervbk 2011年

13
不过,足够有趣。
etienne 2012年

23
嗯,我认为与此答案相关的任何人都已经知道他们可以做到这一点。我怀疑这三个人正在寻找stackoverflow的解决方案。
制造商史蒂夫(Steve)2014年

10
如果您在弄清楚如何在未焊接的设备中生成逼真的NMEA序列时遇到麻烦,则有一个很棒的选择:在实际的外部GPS设备上焊接,然后将整个开发实验室移动到实际的轨道上,并由一组跑步者/骑自行车的人/汽车/飞机/任何东西,取决于您要模拟的速度。别忘了在开发实验室的屋顶上开一个洞,以便该设备可以接收来自卫星的无线电信号。别客气。;-)
斯特凡纳·古里科

32

我希望我的电缆方便。我知道您可以telnet到模拟器以更改其位置

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

我不记得您是否可以远程登录到设备,但我认为可以。我希望这有帮助。

为此,您需要adb(Android调试桥)。


您将获得拒绝所有作为命令发送到设备控制台的内容的权限。也许使用终端应用程序是可能的,但是我认为这需要root用户访问
Janusz 2010年

只是我们在同一页面上:您不是在谈论“ adb shell”吗?我要说的是不同的,这是使您可以设置android特定参数的设置。我知道,例如,您可以在没有root用户访问权限的情况下设置端口转发(即localhost:1234转到phone:1234),因此可以通过不带root用户的电缆来设置SOCKS代理和隧道。
蒂姆·格林2010年

您可以使用adb forward tcp:6000 tcp:23将计算机上的端口6000转发到设备上的端口23,但是即使该端口显示为打开,我也无法连接。在设备上使用telnet客户端并连接到本地主机也会失败
Janusz 2010年

15
这对于仿真器工作正常,但不适用于实际设备。因此,它根本无法回答OP的问题:(
Matthew Gilliard,

4
@TimGreen您的解决方案仅适用于仿真器。问题是关于真实设备。
IgorGanapolsky

29

您可以使用位置服务权限来模拟位置...

"android.permission.ACCESS_MOCK_LOCATION"

然后在您的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
mocLocationProvider的价值是什么?
维克多

例如LocationManager.GPS_PROVIDER
enigma969 '16

25

我在以下代码上取得了成功。尽管由于某种原因(即使我尝试了不同的LatLng对),我也获得了一个锁,但是它对我来说还是有效的。mLocationManagerLocationManager连接到的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
不错的帖子,请参见下面的答案。
icyerasor 2011年

据我所知,setTestProviderStatus此处用于通过LocationManager通知/发布/安排事件,即GPS提供商已找到“现在”修复程序,因此可以处理所述事件。
Dr1Ku 2015年

mLocationManager是一个链接LocationManager到LocationListener的a ” 是什么意思?我怎样才能做到这一点?谢谢..
Yehuda

这是一篇文章,说明如何使用LocationManager服务和a 来检查位置更改LocationListenerblog.doityourselfandroid.com/2010/12/25/…– Dr1Ku 2015
6:49

2
在方法addTestProvider中代表真和假的方式加1
A.Alqadomi 16/12/19

16

Dr1Ku发布的内容有效。今天使用了代码,但需要添加更多位置。因此,这里有一些改进:

可选:您可能不想定义LocationManager.GPS_PROVIDER字符串,而是要定义自己的常量PROVIDER_NAME并使用它。注册位置更新时,请通过条件选择提供商,而不是直接将其指定为字符串。

首先:首先检查是否有要删除的提供程序,而不是调用removeTestProvider(以避免IllegalArgumentException):

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

第二:要发布多个位置,您必须设置位置时间:

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

似乎还有一个使用MockLocationProviders的Google测试:http ://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

另一个很好的工作示例可以在以下位置找到:http : //pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

另一篇好文章是:http : //ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 您还将找到一些实际适用的代码我在模拟器上。


关于定义自己的提供程序的很酷的建议,使用GPS_PROVIDER的事情是(显然)您不能摆脱模拟提供程序(更确切地说,您不能切换到普通GPS),直到重新启动。很棒的帖子,我也会参考一下!
Dr1Ku 2011年

@ Dr1KU是否仍然无法切换回普通GPS?是在某处指定的吗?
卡兹巨龙

@KazDragon那时就是这种情况。据我所记得,打开Mock Provider电源后,普通的GPS将无法工作,我无法获得修复(我是直接在设备上进行测试)。自从Android发生了很多事情以来,情况可能并非如此。
Dr1Ku

@ Dr1Ku嗯,我现在正在做非常相似的事情,并且收到与您描述的结果相似的结果。我希望知道这是平台内置的限制,还是我只是在某个地方缺少函数调用。我可能应该对此提出一个问题。
卡兹巨龙

9

Android电子市场中有可用的应用程序,可让您为设备指定“模拟GPS位置”。

我搜索了https://market.android.com,找到了一个适用于我的名为“我的虚假位置”的应用。

保罗在上面提到的Mock GPS提供程序(位于http://www.cowlumbus.nl/forum/MockGpsProvider.zip)是另一个包含源代码的示例-尽管我无法安装提供的APK(它说失败[INSTALL_FAILED_OLDER_SDK],可能只需要重新编译即可)

为了使用GPS模拟位置,您需要在设备设置中启用它。转到设置->应用程序->开发,然后选中“允许模拟位置”

然后,您可以使用上述应用程序来设置GPS坐标,然后Google地图和其他应用程序将使用您指定的模拟GPS位置。


假GPS更简单。我只是想知道为什么他们要在应用许可中要求呼叫者ID:S
GuillaumeMassé2013年

8

这对我有用(Android Studio):

禁用手机上的GPS和WiFi跟踪。在Android 5.1.1及更低版本上,在开发人员选项中选择“启用模拟位置”。

在src / debug目录中复制清单。向其中添加以下内容(在“应用程序”标签之外):

使用权限android:name =“ android.permission.ACCESS_MOCK_LOCATION”

设置一个称为“ map”的地图片段。在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);
    }
};

请注意,为了使用“ setElapsedRealtimeNanos”方法,您可能必须暂时将模块gradle文件中的“ minSdkVersion”增加到17。

在主要活动类中包含以下代码:

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

使用AS运行您的应用。在Android 6.0及更高版本上,您将获得安全例外。现在转到“设置”中的“开发人员选项”,然后选择“选择模拟位置应用”。从列表中选择您的应用。

现在,当您点击地图时,onLocationChanged()将使用您点击的坐标触发。

我只是想出了这一点,所以现在我不必手持电话在附近闲逛。


我认为,如果您将此代码投入使用,它将在android 6上运行
Hamza

7

我创建了一个简单的Handler,从初始位置模拟了移动位置。

在连接回调中启动它:

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

    }
};

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

希望能有所帮助。


6

由icyerasor提及并由Pedro在http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/提供的解决方案 对我来说非常有效。但是,它不提供对正确启动,停止和重新启动模拟GPS提供程序的支持。

我稍微更改了他的代码,并将该类重写为AsyncTask而不是Thread。这使我们能够与UI线程进行通信,因此我们可以在停止该提供程序的那一刻重新启动该提供程序。当屏幕方向改变时,这很方便。

可以在GitHub上找到该代码以及Eclipse的示例项目:https//github.com/paulhoux/Android-MockProviderGPS

所有功劳应该归功于Pedro所做的大部分努力。


6

添加到清单

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

模拟定位功能

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

您还需要在设备开发人员设置中启用模拟位置。如果不可用,请在完成上述操作后将“模拟位置应用程序”设置为您的应用程序。


3

谷歌播放的伪造的GPS应用对我有用。只要确保您已阅读应用说明中的所有说明即可。启用“假GPS”后,您必须禁用其他定位服务并启动您的应用。很好地满足了我的需求。

这是GooglePlay上应用程序的链接: 伪造GPS




2

我编写了一个在Android手机上运行WebServer(类似REST)的应用,因此您可以远程设置GPS位置。该网站提供了一个地图,您可以在其上单击以设置新位置,或使用“ wasd”键向任何方向移动。该应用程序是一个快速的解决方案,因此几乎没有UI或文档,但是实现非常简单,您可以在(只有四个)类中查找所有内容。

项目资源库:https : //github.com/juliusmh/RemoteGeoFix


1

如果您的设备已插入计算机,并且您试图通过仿真器控件发送GPS线,则它将无法正常工作。
这是一个EMULATOR控件的原因。
只需进行设置即可更新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);
        }
      };

GPS更新后,请重写以下方法以执行您想要的操作;

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

不要忘记将它们放在清单
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION


0

我想知道您是否需要精心设计的“模拟位置”。就我而言,一旦获得了固定位置,我就在调用一个函数以对该新位置进行处理。在计时器中创建一个模拟位置。然后改为在该位置调用该函数。短时间内知道所有这些,GPS会提供一个实际的当前位置。没关系 如果您将更新时间设置得足够长。


0

也许这不是“程序员”方法,但是如果您想节省时间并立即获得有效的解决方案,请尝试以下专用于Google Play的模拟位置的应用程序之一:

假GPS定位踏板

模拟位置

假GPS位置


1
你尝试过吗?他们是否按照问题的要求工作?
arekolek

有什么喜好吗?还是需要所有这些?:P
arekolek '18年

假GPS定位Spoofer足够好,但是“模拟位置”允许设置路线,这是一个不错的功能。
klimat


0

在清单文件中使用此权限

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

android studio建议“仅在测试或调试特定的清单文件(通常为src / debug / AndroidManifest.xml)中请求模拟位置”,只需禁用检查即可

现在,请确保您已在手机的开发者设置中选中了“ 允许模拟位置

使用LocationManager

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

现在在任何地方设置位置

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

0

上述解决方案对我不起作用,因为我正在使用最新版本的Google Play服务版本(使用FusedLocationProviderClient)在Android设备上进行测试。在应用清单中设置模拟位置许可并将应用设置为开发人员设置中指定的模拟位置应用之后(如先前的答案中所述),然后我在下面添加了Kotlin代码,该代码成功模拟了位置。

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.