设备上的 Android 模拟位置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2531317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:12:08  来源:igfitidea点击:

Android mock location on device?

androidgpslocationmocking

提问by Isaac Waller

How can I mock my location on a physical device (Nexus One)? I know you can do this with the emulator in the Emulator Control panel, but this doesn't work for a physical device.

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

回答by Janusz

It seems the only way to do is to use a mock location provider.

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

You have to enable mock locations in the development panel in your settings and add

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

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

to your manifest.

到您的清单。

Now you can go in your code and create your own mock location provider and set the location of this provider.

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

回答by tomash

If you use this phone only in development lab, there is a chance you can solder away GPS chip and feed serial port directly with NMEA sequences from other device.

如果你只在开发实验室使用这款手机,你有可能焊掉 GPS 芯片,直接用来自其他设备的 NMEA 序列馈入串口。

回答by Tim Green

I wish I had my cable handy. I know you can telnet to the emulator to change its location

我希望我的电缆在手边。我知道你可以 telnet 到模拟器来改变它的位置

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

I cannot remember if you can telnet to your device, but I think you can. I hope this helps.

我不记得你是否可以 telnet 到你的设备,但我认为你可以。我希望这有帮助。

You'll need adb (android debugging bridge) for this (CLI).

为此(CLI),您将需要 adb(android 调试桥)。

回答by Vishwanath

You can use the Location Services permission to mock location...

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

"android.permission.ACCESS_MOCK_LOCATION"

"android.permission.ACCESS_MOCK_LOCATION"

and then in your java code,

然后在你的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);

回答by Dr1Ku

I've had success with the following code. Albeit it got me a single lock for some reason (even if I've tried different LatLng pairs), it worked for me. mLocationManageris a LocationManagerwhich is hooked up to a LocationListener:

我已经成功使用以下代码。尽管出于某种原因它给了我一个锁(即使我尝试了不同的 LatLng 对),它对我有用。mLocationManagerLocationManager连接到 a 的 a 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
    );      
}

回答by icyerasor

What Dr1Ku posted works. Used the code today but needed to add more locs. So here are some improvements:

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

Optional: Instead of using the LocationManager.GPS_PROVIDER String, you might want to define your own constat PROVIDER_NAME and use it. When registering for location updates, pick a provider via criteria instead of directly specifying it in as a string.

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

First: Instead of calling removeTestProvider, first check if there is a provider to be removed (to avoid IllegalArgumentException):

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

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

Second: To publish more than one location, you have to set the time for the location:

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

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

There also seems to be a google Test that uses MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

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

Another good working example can be found at: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

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

Another good article is: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358You'll also find some code that actually works for me on the emulator.

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

回答by fijiaaron

There are apps available in the Android Market that allow you to specify a "Mock GPS Location" for your device.

Android Market 中有一些应用程序允许您为您的设备指定“模拟 GPS 位置”。

I searched https://market.android.comand found an app called "My Fake Location" that works for me.

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

The Mock GPS Provider mentioned by Paul above (at http://www.cowlumbus.nl/forum/MockGpsProvider.zip) is another example that includes source code -- although I wasn't able to install the provided APK (it says Failure [INSTALL_FAILED_OLDER_SDK] and may just need a recompile)

Paul 上面提到的 Mock GPS Provider(在http://www.cowlumbus.nl/forum/MockGpsProvider.zip)是另一个包含源代码的例子——尽管我无法安装提供的 APK(它说失败[INSTALL_FAILED_OLDER_SDK] 并且可能只需要重新编译)

In order to use GPS mock locations you need to enable it in your device settings. Go to Settings -> Applications -> Development and check "Allow mock locations"

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

You can then use an app like the ones described above to set GPS coordinates and Google maps and other apps will use the mock GPS location you specify.

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

回答by Chris B

This worked for me (Android Studio):

这对我有用(Android Studio):

Disable GPS and WiFi tracking on the phone. On Android 5.1.1 and below, select "enable mock locations" in Developer Options.

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

Make a copy of your manifest in the src/debug directory. Add the following to it (outside of the "application" tag):

在 src/debug 目录中制作清单的副本。添加以下内容(在“application”标签之外):

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

使用权限 android:name="android.permission.ACCESS_MOCK_LOCATION"

Set up a map Fragment called "map". Include the following code in onCreate():

设置一个名为“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);
    }
};

Note that you may have to temporarily increase "minSdkVersion" in your module gradle file to 17 in order to use the "setElapsedRealtimeNanos" method.

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

Include the following code inside the main activity class:

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

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

Run your app with AS. On Android 6.0 and above you will get a security exception. Now go to Developer Options in Settings and select "Select mock location app". Select your app from the list.

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

Now when you tap on the map, onLocationChanged() will fire with the coordinates of your tap.

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

I just figured this out so now I don't have to tramp around the neighborhood with phones in hand.

我刚刚想通了这一点,所以现在我不必拿着手机在附近闲逛。

回答by smora

I've created a simple Handler simulating a moving position from an initial position.

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

Start it in your connection callback :

在您的连接回调中启动它:

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

    }
};

The Handler class :

处理程序类:

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

Hope it can help..

希望它可以帮助..

回答by Paul Houx

The solution mentioned by icyerasor and provided by Pedro at http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/worked very well for me. However, it does not offer support for properly starting, stopping and restarting the mock GPS provider.

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

I have changed his code a bit and rewritten the class to be an AsyncTask instead of a Thread. This allows us to communicate with the UI Thread, so we can restart the provider at the point where we were when we stopped it. This comes in handy when the screen orientation changes.

我稍微更改了他的代码并将类重写为 AsyncTask 而不是线程。这允许我们与 UI 线程通信,因此我们可以在停止时重新启动提供程序。当屏幕方向改变时,这会派上用场。

The code, along with a sample project for Eclipse, can be found on GitHub: https://github.com/paulhoux/Android-MockProviderGPS

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

All credit should go to Pedro for doing most of the hard work.

所有的功劳都归功于佩德罗所做的大部分辛勤工作。