Карты Yandex без использования Yandex Map Kit или карты из различных источников в приложении под Android

    Здравствуйте!
    В этом сообщении рассмотрим использование карт из различных источников (в том числе Yandex карты) в приложении под Android.
    image
    Для решения задачи будем использовать библиотеку osmdroid. Нам потребуется сама библиотека(ссылка не на последнюю версию, эта версия, как мне кажется, более стабильна и быстрее, чем более новые) и еще одна дополнительная. Добавим их в проект (использовался Eclipse под Windows) (Build Path->Configure Buil Path->Libraries->Add External JARs).
    Пропишем необходимые разрешения в манифесте проекта
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    Для добавления новых источников карт, например, Yandex и Google (Mapnik уже встроен в библиотеку) потребуется расширить класс XYTileSource
    MyTileSource
    public class MyTileSource extends XYTileSource {
    
    	public MyTileSource(String aName, string aResourceId, int aZoomMinLevel,
    			int aZoomMaxLevel, int aTileSizePixels,
    			String aImageFilenameEnding, String... aBaseUrl) {
    		super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel,
    				aTileSizePixels, aImageFilenameEnding, aBaseUrl);
    
    	}
    	//переопределим метод getTileURLString, он будет возвращать ссылку на тайл карты
    	@Override
    	public String getTileURLString(MapTile aTile) {
    
    		return String.format(getBaseUrl(), aTile.getX(), aTile.getY(),
    				aTile.getZoomLevel());
    	}
    
    }
    


    Проблема в том, что osmdroid не поддерживает проекцию Yandex карт. Поэтому для корректного отображения Yandex карт расширим класс TilesOverlay. Для преобразования координат в тайлы и обратно в сети был найден класс. Вот этот немного доработанный класс
    YandexUtils
    public class YandexUtils {
    	public static double[] geoToMercator(double[] g) {
    		double d = g[0] * Math.PI / 180, m = g[1] * Math.PI / 180, l = 6378137, k = 0.0818191908426, f = k
    				* Math.sin(m);
    		double h = Math.tan(Math.PI / 4 + m / 2), j = Math.pow(
    				Math.tan(Math.PI / 4 + Math.asin(f) / 2), k), i = h / j;
    		// return new DoublePoint(Math.round(l * d), Math.round(l *
    		// Math.log(i)));
    		return new double[] { l * d, l * Math.log(i) };
    	}
    
    	public static double[] mercatorToGeo(double[] e) {
    		double j = Math.PI, f = j / 2, i = 6378137, n = 0.003356551468879694, k = 0.00000657187271079536, h = 1.764564338702e-8, m = 5.328478445e-11;
    		double g = f - 2 * Math.atan(1 / Math.exp(e[1] / i));
    		double l = g + n * Math.sin(2 * g) + k * Math.sin(4 * g) + h
    				* Math.sin(6 * g) + m * Math.sin(8 * g);
    		double d = e[0] / i;
    		return new double[] { d * 180 / Math.PI, l * 180 / Math.PI };
    	}
    
    	public static double[] mercatorToTiles(double[] e) {
    		double d = Math.round((20037508.342789 + e[0]) * 53.5865938), f = Math
    				.round((20037508.342789 - e[1]) * 53.5865938);
    		d = boundaryRestrict(d, 0, 2147483647);
    		f = boundaryRestrict(f, 0, 2147483647);
    		return new double[] { d, f };
    	}
    
    	public static double[] tileToMercator(long[] d) {
    		return new double[] { Math.round(d[0] / 53.5865938 - 20037508.342789),
    				Math.round(20037508.342789 - d[1] / 53.5865938) };
    	}
    
    	public static double[] tileCoordinatesToPixels(double[] i, int h) {
    		double g = Math.pow(2, toScale(h));
    		return new double[] { (int) i[0] / g, (int) i[1] / g };
    	}
    
    	public static double boundaryRestrict(double f, double e, double d) {
    		return Math.max(Math.min(f, d), e);
    	}
    
    	public static int toScale(int i) {
    		return 23 - i;
    	}
    
    	public static long[] getTile(double[] h, int i) {
    		long e = 8;
    		long j = toScale(i), g = (long) h[0] >> j, f = (long) h[1] >> j;
    		return new long[] { g >> e, f >> e };
    	}
    
    	public static long[] getPxCoordFromTileCoord(double[] h, int i) {
    		long j = toScale(i), g = (long) h[0] >> j, f = (long) h[1] >> j;
    		return new long[] { g, f };
    	}
    
    	public static long[] getTileCoordFromPixCoord(long[] h, int i) {
    		long j = toScale(i), g = h[0] << j, f = h[1] << j;
    		return new long[] { g, f };
    
    	}
    
    	public static double[] ReGetTile(double[] h, int i) {
    		long e = 8;
    		long j = toScale(i);
    		long g = (long) h[0] << (int) j;
    		long f = (long) h[1] << (int) j;
    		double ge = g << (int) e;
    		double fe = f << (int) e;
    		long g2 = (long) (h[0] + 1) << (int) j;
    		long f2 = (long) (h[1] + 1) << (int) j;
    		double ge2 = g2 << (int) e;
    		double fe2 = f2 << (int) e;
    
    		double ad_g = (ge2 - ge) * (h[0] - Math.floor(h[0]));
    		double ad_f = (fe2 - fe) * (h[1] - Math.floor(h[1]));
    
    		return new double[] { ge + ad_g, fe + ad_f };
    	}
    
    	public static double[] ReGetTile(long[] h, int i) {
    		long e = 8;
    		long j = toScale(i);
    		long g = (long) h[0] << (int) j;
    		long f = (long) h[1] << (int) j;
    		return new double[] { g << (int) e, f << (int) e };
    	}
    
    	public static double[] getGeoFromTile(int x, int y, int zoom) {
    		double a, c1, c2, c3, c4, g, z, mercX, mercY;
    		a = 6378137;
    		c1 = 0.00335655146887969;
    		c2 = 0.00000657187271079536;
    		c3 = 0.00000001764564338702;
    		c4 = 0.00000000005328478445;
    		mercX = (x * 256 * 2 ^ (23 - zoom)) / 53.5865938 - 20037508.342789;
    		mercY = 20037508.342789 - (y * 256 * 2 ^ (23 - zoom)) / 53.5865938;
    
    		g = Math.PI / 2 - 2 * Math.atan(1 / Math.exp(mercY / a));
    		z = g + c1 * Math.sin(2 * g) + c2 * Math.sin(4 * g) + c3
    				* Math.sin(6 * g) + c4 * Math.sin(8 * g);
    
    		return new double[] { mercX / a * 180 / Math.PI, z * 180 / Math.PI };
    	}
    
    	public static long[] getTileFromGeo(double lat, double lon, int zoom) {
    		double rLon, rLat, a, k, z;
    		rLon = lon * Math.PI / 180;
    		rLat = lat * Math.PI / 180;
    		a = 6378137;
    		k = 0.0818191908426;
    		z = Math.pow(
    				Math.tan(Math.PI / 4 + rLat / 2)
    						/ (Math.tan(Math.PI / 4 + Math.asin(k * Math.sin(rLat))
    								/ 2)), k);
    		return new long[] {
    				(int) (((20037508.342789 + a * rLon) * 53.5865938 / Math.pow(2,
    						(23 - zoom))) / 256),
    				(int) (((20037508.342789 - a * Math.log(z)) * 53.5865938 / Math
    						.pow(2, (23 - zoom)))) / 256 };
    	}
    
    	public static double tile2lon(int x, int aZoom) {
    		return (x / Math.pow(2.0, aZoom) * 360.0) - 180;
    	}
    
    	public static double tile2lat(int y, int aZoom) {
    
    		final double MerkElipsK = 0.0000001;
    		final long sradiusa = 6378137;
    		final long sradiusb = 6356752;
    		final double FExct = (double) Math.sqrt(sradiusa * sradiusa - sradiusb
    				* sradiusb)
    				/ sradiusa;
    		final int TilesAtZoom = 1 << aZoom;
    		double result = (y - TilesAtZoom / 2) / -(TilesAtZoom / (2 * Math.PI));
    		result = (2 * Math.atan(Math.exp(result)) - Math.PI / 2) * 180
    				/ Math.PI;
    		double Zu = result / (180 / Math.PI);
    		double yy = ((y) - TilesAtZoom / 2);
    
    		double Zum1 = Zu;
    		Zu = Math.asin(1
    				- ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct * Math.sin(Zum1),
    						FExct))
    				/ (Math.exp((2 * yy) / -(TilesAtZoom / (2 * Math.PI))) * Math
    						.pow(1 + FExct * Math.sin(Zum1), FExct)));
    		while (Math.abs(Zum1 - Zu) >= MerkElipsK) {
    			Zum1 = Zu;
    			Zu = Math
    					.asin(1
    							- ((1 + Math.sin(Zum1)) * Math.pow(
    									1 - FExct * Math.sin(Zum1), FExct))
    							/ (Math.exp((2 * yy)
    									/ -(TilesAtZoom / (2 * Math.PI))) * Math
    										.pow(1 + FExct * Math.sin(Zum1), FExct)));
    		}
    
    		result = Zu * 180 / Math.PI;
    
    		return result;
    
    	}
    
    	public static int[] getMapTileFromCoordinates(final double aLat,
    			final double aLon, final int zoom) {
    		final int[] out = new int[2];
    
    		final double E2 = (double) aLat * Math.PI / 180;
    		final long sradiusa = 6378137;
    		final long sradiusb = 6356752;
    		final double J2 = (double) Math.sqrt(sradiusa * sradiusa - sradiusb
    				* sradiusb)
    				/ sradiusa;
    		final double M2 = (double) Math.log((1 + Math.sin(E2))
    				/ (1 - Math.sin(E2)))
    				/ 2
    				- J2
    				* Math.log((1 + J2 * Math.sin(E2)) / (1 - J2 * Math.sin(E2)))
    				/ 2;
    		final double B2 = (double) (1 << zoom);
    		out[0] = (int) Math.floor(B2 / 2 - M2 * B2 / 2 / Math.PI);
    
    		out[1] = (int) Math.floor((aLon + 180) / 360 * (1 << zoom));
    
    		return out;
    	}
    }
    


    Теперь когда есть формулы для преобразования координат можем расширить TilesOverlay
    YandexTilesOverlay
    public class YandexTilesOverlay extends TilesOverlay {
    	private final Rect mTileRect = new Rect();
    	private final Point mTilePos = new Point();
    
    	public YandexTilesOverlay(MapTileProviderBase aTileProvider,
    			Context aContext) {
    		super(aTileProvider, aContext);
    	}
            //переопределим метод draw для отрисовки Yandex тайлов
    	@Override
    	protected void draw(Canvas c, MapView osmv, boolean shadow) {
    		//текущий масштаб
    		int zoom = osmv.getZoomLevel();
    		final Projection pj = osmv.getProjection();
    		//координаты углов видимой части карты
    		BoundingBoxE6 bb = osmv.getBoundingBox();
    		//получаем координаты верхнего левого и нижнего правого тайла
    		double[] MercatorTL = YandexUtils.geoToMercator(new double[] {
    				bb.getLonWestE6() / 1E6, bb.getLatNorthE6() / 1E6 });
    		double[] TilesTL = YandexUtils.mercatorToTiles(MercatorTL);
    		long[] TileTL = YandexUtils.getTile(TilesTL, zoom);
    
    		double[] MercatorRB = YandexUtils.geoToMercator(new double[] {
    				bb.getLonEastE6() / 1E6, bb.getLatSouthE6() / 1E6 });
    		double[] TilesRB = YandexUtils.mercatorToTiles(MercatorRB);
    		long[] TileRB = YandexUtils.getTile(TilesRB, zoom);
    		mTileProvider
    				.ensureCapacity((int) ((TileRB[1] - TileTL[1] + 1) * (TileRB[0]
    						- TileTL[0] + 1)));
    		//геокоординаты верхнего левого тайла Yandex
    		double[] reTiles = YandexUtils.ReGetTile(new long[] { TileTL[0],
    				TileTL[1] }, zoom);
    		long xx = (long) reTiles[0];
    		long yy = (long) reTiles[1];
    		double[] reMercator = YandexUtils.tileToMercator(new long[] { xx, yy });
    		double[] tmp = YandexUtils.mercatorToGeo(reMercator);
    		//геокоординаты верхнего левого тайла Yandex переводим в экранные координаты osmdroid
    		GeoPoint gp = new GeoPoint(tmp[1], tmp[0]);
    		pj.toPixels(gp, mTilePos);
    		//в цикле отрисовываем все видимые тайлы Yandex
    		for (int y = (int) TileTL[1]; y <= TileRB[1]; y++) {
    			int xcount = 0;
    
    			for (int x = (int) TileTL[0]; x <= TileRB[0]; x++) {
    
    				final MapTile tile = new MapTile(zoom, x, y);
    				final Drawable currentMapTile = mTileProvider.getMapTile(tile);
    				if (currentMapTile != null) {
    
    					mTileRect.set(mTilePos.x, mTilePos.y, mTilePos.x + 256,
    							mTilePos.y + 256);
    					currentMapTile.setBounds(mTileRect);
    					currentMapTile.draw(c);
    
    				}
    				xcount++;
    				mTilePos.x += 256;
    			}
    			mTilePos.x -= xcount * 256;
    			mTilePos.y += 256;
    		}
    	}
    
    }
    


    Осталось вывести карты на форме
    BlogOsmYandexActivity
    public class BlogOsmYandexActivity extends Activity {
    	MapView mMap;
    	MapController mMapController;
    	YandexTilesOverlay tilesOverlayYandex;
    	TilesOverlay tilesOverlayGoogle;
    	TilesOverlay tilesOverlayMapnik;
    	MapTileProviderBasic tileProviderYandex;
    	MapTileProviderBasic tileProviderGoogle;
    	MapTileProviderBasic tileProviderMapnik;
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		//разметка
    		RelativeLayout rl = new RelativeLayout(this);
    		//карта
    		mMap = new MapView(this, 256);
    		//включить встроенные кнопки управления масштабом
    		mMap.setBuiltInZoomControls(true);
    		//добавляем карту в разметку
    		rl.addView(mMap, new RelativeLayout.LayoutParams(
    				LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    		setContentView(rl);
    		//устанавливаем начальный масштаб и координаты центра карты
    		mMapController = mMap.getController();
    		mMapController.setZoom(15);
    		mMapController.setCenter(new GeoPoint(55.751893, 37.617166));
    		//добавляем источник тайлов Yandex
    		//ссылку можно подсмотреть в firebug 
    		//getTileURLString подставит вместо %s  координаты тайла и масштаб
    		ITileSource tileSourceYandex = new MyTileSource(
    				"YandexMap",
    				null,
    				0,
    				23,
    				256,
    				".png",
    				"http://vec04.maps.yandex.net/tiles?l=map&v=2.28.0&x=%s&y=%s&z=%s&lang=ru-RU",
    				"http://vec03.maps.yandex.net/tiles?l=map&v=2.28.0&x=%s&y=%s&z=%s&lang=ru-RU",
    				"http://vec02.maps.yandex.net/tiles?l=map&v=2.28.0&x=%s&y=%s&z=%s&lang=ru-RU",
    				"http://vec01.maps.yandex.net/tiles?l=map&v=2.28.0&x=%s&y=%s&z=%s&lang=ru-RU");
    		//добавляем источник тайлов Google
    		ITileSource tileSourceGoogle = new MyTileSource(
    				"Google-Map",
    				null,
    				0,
    				23,
    				256,
    				".png",
    				"http://mt0.google.com/vt/lyrs=m&hl=ru&x=%s&y=%s&z=%s&s=Galileo",
    				"http://mt1.google.com/vt/lyrs=m&hl=ru&x=%s&y=%s&z=%s&s=Galileo",
    				"http://mt2.google.com/vt/lyrs=m&hl=ru&x=%s&y=%s&z=%s&s=Galileo",
    				"http://mt3.google.com/vt/lyrs=m&hl=ru&x=%s&y=%s&z=%s&s=Galileo");
    		//создаем поставщика тайлов и задаем для него источник тайлов Yandex
    		tileProviderYandex = new MapTileProviderBasic(getApplicationContext());
    		tileProviderYandex.setTileSource(tileSourceYandex);
    		tileProviderYandex.setTileRequestCompleteHandler(mMap
    				.getTileRequestCompleteHandler());
    		//создаем слой Yandex карты
    		tilesOverlayYandex = new YandexTilesOverlay(tileProviderYandex,
    				this.getBaseContext());
    		//создаем поставщика тайлов и задаем для него источник тайлов Google
    		tileProviderGoogle = new MapTileProviderBasic(getApplicationContext());
    		tileProviderGoogle.setTileRequestCompleteHandler(mMap
    				.getTileRequestCompleteHandler());
    		tileProviderGoogle.setTileSource(tileSourceGoogle);
    		//создаем слой Google карты
    		tilesOverlayGoogle = new TilesOverlay(tileProviderGoogle,
    				this.getBaseContext());
    		//создаем поставщика тайлов и задаем для него источник тайлов Mapnik
    		tileProviderMapnik = new MapTileProviderBasic(getApplicationContext());
    		tileProviderMapnik.setTileRequestCompleteHandler(mMap
    				.getTileRequestCompleteHandler());
    		tileProviderMapnik.setTileSource(TileSourceFactory.MAPNIK);
    		//создаем слой Mapnik карты
    		tilesOverlayMapnik = new TilesOverlay(tileProviderMapnik,
    				this.getBaseContext());
    		//устанавливаем Yandex карты текущим слоем
    		mMap.getOverlayManager().setTilesOverlay(tilesOverlayYandex);
    	}
    	//меню для смены карт/слоев
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		SubMenu sm = menu.addSubMenu("Выбор карты");
    		sm.add(0, 111, Menu.NONE, "Яндекс");
    		sm.add(0, 222, Menu.NONE, "Google");
    		sm.add(0, 333, Menu.NONE, "Mapnik");
    		return true;
    	}
    	//в зависимости от выбора устанавливаем текущую карту/слой
    	@Override
    	public boolean onOptionsItemSelected(MenuItem item) {
    		switch (item.getItemId()) {
    		case (111):
    			mMap.getOverlayManager().setTilesOverlay(tilesOverlayYandex);
    			mMap.invalidate();
    			return true;
    		case (222):
    			mMap.getOverlayManager().setTilesOverlay(tilesOverlayGoogle);
    			mMap.invalidate();
    			return true;
    		case (333):
    			mMap.getOverlayManager().setTilesOverlay(tilesOverlayMapnik);
    			mMap.invalidate();
    			return true;
    		default:
    			return super.onOptionsItemSelected(item);
    		}
    	}
    }
    


    Результат
    image
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 26
    • +3
      На всякий случай напомню, что описанные в этой статье действия нарушают пользовательские соглашения картографических сервисов.
      • 0
        А можно подробнее? Очень интересно.
        • +1
          Ну откройте соглашения и прочтите. И у гугла и у яндекса картами можно пользоваться только через предоставленный API и с сохранением копирайтов, включая копирайты поставщиков данных. У bing, насколько я знаю, достаточно указатб копирайты.
          Сделать легальное приложение можно, но надо уделить внимание правильному использованию API.
          • 0
            Sasplaneta нарушает соглашения? Почему не прикроют их сайт? А наше маленькое скромное приложение для некомерческих нужд вызовет гнев гигантов и они нас поразят нас своей молнией
            • +2
              sasplaneta безусловно нарушает. Заметте, что я весьма мягко выразился, я не говорил, что за это нарушение вас кто-то будет преследовать. Я просто напомнил, что вообще говоря, такое использование нелегально. Нарушать или нет — это всецело ваш выбор.

              P.S. Также можно посмотреть, как сделана поддержка карт гугла в openlayers. Там просто подгружаеться API гугла и работа идет через него. Все законно.
        • 0
          Соглашение Yandex, какой пункт нарушен?
          • 0
            Соглашение API Яндекс.карт пункт 2.3.6.2
            • 0
              в статье ничего нет про удаление товарных знаков, если подскажете ссылку на лого, которое нужно вывести поверх карты буду признателен
              • 0
                Вы удалили, а точнее не вывели копирайт Яндекса. Хотя я вполне могу и ошибаться.
            • 0
              Это соглашение на сам сервис, как он предоставлен на maps.yandex.ru. Вам нужно смотреть лицензию на API. А там, для JS API запрещено создание не веб приложений на его основе. Для мобильных клиентов есть API Yandex Map Kit. Лезть за тайлами в обход него нельзя.
              • 0
                API Yandex не используется, только тайлы загружаются, по ссылкам которые видны в браузере, есть прямой запрет на скачивание картинок с серверов Yandex?
                Вывести копирайт Yandex не проблема, если есть такое требование и ссылки на лого для различных разрешений экранов
                • 0
                  Конечно есть. Читайте правила, ссылку на которые уже привели:
                  legal.yandex.ru/maps_termsofuse/
                  Пункт 1.2 «Настоящие Условия представляют собой дополнение к Пользовательскому соглашению...»
                  Идете по ссылке. Читаете.
                  legal.yandex.ru/rules/
                  Читаете пункт 6.2: «Использование контента, а также каких-либо иных элементов сервисов возможно только в рамках функционала, предлагаемого тем или иным сервисом.»

                  Используйте Yandex maps kit, он сделан для того, чтобы вы могли использовать яндекс-карты в своих приложениях.
                  • 0
                    В этом пункте есть слова, что разрешается использование контента в личных некомерческих целях, их нельзя отнести к теме этого сообщения, т.е. использование тайлов в своей программе?
                    • 0
                      Я не юрист и я не достаточно компетентен, чтобы корректно интерпретировать условия лицензий.
                      Но вы понимаете, что как только вы выложите свою программу в общественный доступ, это уже точно будут не личные цели.
          • 0
            >>> <uses-permission android:name=«android.permission.ACCESS_COARSE_LOCATION»/>
            >>> <uses-permission android:name=«android.permission.ACCESS_FINE_LOCATION»/>

            Если есть FINE, COARSE уже не требуется прописывать.
            • 0
              Скопировал разрешения из wiki библиотеки
            • 0
              Как Вам уже верно написали, подобное использование Яндекс.Карт запрещено пользовательскими соглашениями Яндекса.

              Сначала ПС Яндекс.Карт legal.yandex.ru/maps_termsofuse/. Читаем п. 2.2.

              2.2. Любая информация, используемая в Сервисе, включая картографические материалы и данные о дорожной ситуации (состоянии загруженности автомобильных дорог) (далее — «Данные»), предназначена исключительно для личного некоммерческого использования. При этом любое копирование данных, их воспроизведение, переработка, распространение, доведение до всеобщего сведения (опубликование) в сети Интернет, любое использование в средствах массовой информации и/или в коммерческих целях без предварительного письменного разрешения правообладателя запрещается, за исключением случаев, прямо предусмотренных настоящими Условиями, условиями использования других сервисов Яндекса или документами, указанными в п. 1.2. настоящих Условий.

              Итак, понимаем, что можно использовать только если это разрешено другими сервисами Яндекса. Например, API Яндекс.Карт или Yandex Map Kit. Так как речь идет о мобильном приложении, читаем ПС Map Kit.

              legal.yandex.ru/mapkit/

              2.1. Сервис представляет собой интерфейс программирования, который дает возможность взаимодействия с сервисом «Яндекс.Карты» и сервисом «Яндекс.Народная карта», в том числе с Данными этих сервисов и возможность использования функциональности указанных сервисов в мобильных приложении (-ях).

              2.3.1. Для получения доступа к Сервису необходимо написать письмо по электронной почте на адрес: support@mobmaps.yandex.ru (в теме письма указать «Map Kit запрос API-ключа») и получить API-ключ. Яндекс вправе по своему усмотрению отказать в доступе к Сервису без объяснения причин.

              2.3.2. Сервис может использоваться Пользователем только в рамках мобильных приложений, доступных для бесплатного открытого использования неограниченным кругом лиц. Сервис не может использоваться для приложений, требующих оплаты, или иным образом ограничивающих доступ к ним третьих лиц. Необходимость зарегистрироваться не считается ограничением доступа в рамках настоящего пункта.
              2.3.3. Пользователь может использовать Данные и функции, полученные при помощи Сервиса, только в рамках функциональности, предоставляемой Сервисом.
              2.3.4. Пользователь обязуется разместить в своем мобильном приложении в разделе «О программе» или ином подобном разделе мобильного приложения, гиперссылку на Условия использования сервиса Яндекс.Карты, размещенные по адресу: legal.yandex.ru/maps_termsofuse/, следующего вида — «Условия использования сервиса Яндекс.Карты».

              2.3.7. ОГРАНИЧЕНИЯ. Используя Сервис, Пользователь не имеет права:
              2.3.7.1. Изменять, декомпилировать и/или каким либо образом модифицировать программный код, полученный посредством Сервиса.
              2.3.7.2. Удалять, скрывать или модифицировать любые содержащиеся в Сервисе или Данных товарные знаки, логотипы, ссылки или иные указания на Правообладателей, равно как и любые другие уведомления и/или информацию, передаваемые Сервисом вместе с Данными.
              2.3.7.3. Создавать на основе Сервиса системы мониторинга транспортных средств, отображающих информацию в реальном времени, и любые другие услуги, связанные с управлением и диспетчеризацией транспортных средств.
              2.3.7.4. Использовать любые автоматические программы или устройства для получения API-ключа.
              2.3.7.5. Сохранять, обрабатывать и видоизменять полученные через Сервис Данные (включая результаты геокодирования), за исключением случаев временного хранения (кэширования) результатов геокодирования исключительно для целей улучшения функциональности и работоспособности Сервиса и только для использования в рамках возможностей, предоставляемых Сервисом.
              • 0
                это выше уже «обсосали», в чем смысл вашего комментария?
                • 0
                  В том, что выше Вы просили ссылки на конкретные пункты, по которым подобное использование Яндекс.Карт запрещено. Мне показалось, что Вам их так и не дали.
                  Извините, если мой комментарий Вас задел. Могу удалить.
                  • 0
                    Нет конечно, я не обиделся, просто все эти пункты уже обсуждали, во всех соглашениях идут сноски, что для личного использования как бы можно. Я знаю программу в маркете, в которой используется подобный подход на этой же библиотеке, только реализация другая, автор полностью переработал код библиотеки, так вот по словам автора, яндекс был не против этой программы, даже разрешил использовать информацию о пробках.

                    • 0
                      Ну если Вы дадите ссылку на приложение, я смогу подтвердить или опровергнуть Ваши слова. :-) Лично я о таком не слышала. А информация о пробках и через мап кит, и через JS API предоставляется.
                  • 0
                    Еще хотел добавить, что сервис Map Kit никоим образом не используется, от Яндекса только получаются тайлы, по ссылкам, который были подсмотрены в браузере на ПК при загрузке в нем карты
                    • 0
                      Я понимаю. Но использование тайлов Яндекс.Карт разрешено только через мапкит или апи.
              • 0
                Мне нравится пользоваться оффлайновыми картами — они быстрее работают и трафик не просят. Сначала сделал себе карту Киева через Mobile Atlas Creator. С большим количеством масштабов заняла чуть менее 500 Мб. Хорошая приятная на вид карта. Включив EDGE, можно наложить слой Яндекс пробок.

                Но лафа с Mobile Atlas Creator быстро закончилась. Opensreetmap блочит приложения типа Mobile Atlas Creator. Потом я наткнулся на MapDroyd. Вся карта Украины весит менее 50Мб. И куда удобнее. Через Mobile Atlas Creator у меня создавалась карта Киева несколько часов и со второго раза.

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

                Самое читаемое