Расположение макета Android на устройстве? - PullRequest
141 голосов
/ 28 марта 2010

Как я могу смоделировать свое местоположение на физическом устройстве (Nexus One)? Я знаю, что вы можете сделать это с помощью эмулятора на панели управления эмулятором, но это не работает для физического устройства.

Ответы [ 20 ]

159 голосов
/ 01 апреля 2010

Кажется, что единственный способ сделать это - использовать провайдера фиктивного местоположения.

Вы должны включить макеты мест на панели разработки в настройках и добавить

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

к вашему манифесту.

Теперь вы можете зайти в свой код и создать своего собственного провайдера для определения местоположения и указать местоположение этого провайдера.

101 голосов
/ 29 марта 2010

Если вы используете этот телефон только в лаборатории разработки, есть вероятность, что вы сможете припаять чип GPS и напрямую подключить последовательный порт с последовательностями NMEA от другого устройства.

32 голосов
/ 06 апреля 2010

Хотелось бы, чтобы у меня был свой кабель под рукой. Я знаю, что вы можете telnet к эмулятору, чтобы изменить его местоположение

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

Я не могу вспомнить, можете ли вы подключиться к вашему устройству, но я думаю, что вы можете. Надеюсь, это поможет.

Для этого вам понадобится adb (мост отладки Android) (CLI).

28 голосов
/ 06 апреля 2010

Вы можете использовать разрешение Службы определения местоположения, чтобы смоделировать местоположение ...

"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);
24 голосов
/ 19 января 2011

У меня был успех со следующим кодом. Хотя по какой-то причине у меня была одна блокировка (даже если я пробовал разные пары LatLng), это сработало для меня. mLocationManager - это LocationManager, который подключен к 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
    );      
}
14 голосов
/ 26 января 2011

В каких Dr1Ku размещены работы. Использовал код сегодня, но нужно было добавить больше locs. Итак, вот некоторые улучшения:

Необязательно: Вместо использования строки LocationManager.GPS_PROVIDER вы можете определить собственное constat PROVIDER_NAME и использовать его. При регистрации для получения обновлений местоположения выберите поставщика по критериям, а не указывайте его в виде строки.

Во-первых: вместо вызова removeTestProvider, сначала проверьте, есть ли провайдер для удаления (чтобы избежать IllegalArgumentException):

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

Второй: чтобы опубликовать более одного местоположения, вы должны установить время для местоположения:

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

Также, похоже, есть тест Google, который использует MockLocationProviders: 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 Вы также найдете некоторый код, который действительно работает для меня на эмуляторе.

9 голосов
/ 12 августа 2011

В Android Market есть приложения, которые позволяют вам указать «Местоположение GPS-макета» для вашего устройства.

Я искал https://market.android.com и нашел приложение под названием «Мое поддельное местоположение», которое работает для меня.

Поставщик Mock GPS, упомянутый Полом выше (в http://www.cowlumbus.nl/forum/MockGpsProvider.zip), является другим примером, который включает исходный код - хотя я не смог установить прилагаемый APK (он говорит Failure [INSTALL_FAILED_OLDER_SDK] и может просто перекомпиляция)

Чтобы использовать макеты GPS, вам необходимо включить их в настройках вашего устройства. Зайдите в «Настройки» -> «Приложения» -> «Разработка» и проверьте «Разрешить фиктивные местоположения»

Затем вы можете использовать приложение, подобное описанному выше, для установки координат GPS, а карты Google и другие приложения будут использовать фиктивное местоположение GPS, указанное вами.

8 голосов
/ 14 августа 2013

Это сработало для меня (Android Studio):

Отключение GPS и WiFi отслеживания на телефоне. На Android 5.1.1 и ниже выберите «Включить фиктивные местоположения» в Настройках разработчика.

Создайте копию своего манифеста в каталоге src / debug. Добавьте к нему следующее (вне тега «application»):

использует разрешение android: name = "android.permission.ACCESS_MOCK_LOCATION"

Настройка фрагмента карты под названием «карта». Включите следующий код в 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);
    }
};

Обратите внимание, что вам, возможно, придется временно увеличить "minSdkVersion" в файле gradle вашего модуля до 17, чтобы использовать метод "setElapsedRealtimeNanos".

Включите следующий код в основной класс деятельности:

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

Запустите ваше приложение с AS. На Android 6.0 и выше вы получите исключение безопасности. Теперь перейдите в «Параметры разработчика» в «Настройках» и выберите «Выбор приложения для определения местоположения». Выберите ваше приложение из списка.

Теперь, когда вы нажимаете на карту, onLocationChanged () срабатывает с координатами вашего касания.

Я только что понял это, так что теперь мне не нужно бродить по окрестностям с телефонами в руках.

7 голосов
/ 11 июля 2015

Я создал простой обработчик, имитирующий перемещение позиции из начальной позиции.

Запустите его в обратном вызове вашего соединения:

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

    }
};

Класс обработчика:

   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 голосов
/ 22 июля 2011

Решение, упомянутое icyerasor и предоставленное Педро на http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/, сработало очень хорошо для меня. Тем не менее, он не предлагает поддержку для правильного запуска, остановки и перезапуска провайдера фиктивного GPS.

Я немного изменил его код и переписал класс как AsyncTask вместо Thread. Это позволяет нам взаимодействовать с потоком пользовательского интерфейса, поэтому мы можем перезапустить провайдера с того места, где мы были, когда мы его остановили. Это удобно, когда меняется ориентация экрана.

Код вместе с примером проекта для Eclipse можно найти на GitHub: https://github.com/paulhoux/Android-MockProviderGPS

Все заслуги должны быть отданы Педро за большую часть тяжелой работы.

...