Плитки sqlite какой файл android
Обновлено: 21.11.2024
@dlmcauslan Мы переместили ваш исходный выпуск в частное хранилище. Однако, поскольку вы не можете комментировать/подписываться там, я воспроизвожу вашу исходную проблему здесь. Приносим извинения за путаницу.
Окружающая среда
- Версия ОС Android: 10.
- Затронутые устройства: Samsung Galaxy Tab Active Pro (SM-T545), Samsung Galaxy Tab Active 3 (SM-T575)
- Версия Maps SDK: 10.0.0-beta.15 и новее
Наблюдаемое поведение и шаги для воспроизведения
Использование Mapbox SDK более новой версии, чем 10.0.0-beta.15, может привести к повреждению локальной базы данных SQLite нашего приложения. Это не проблема в версиях 10.0.0-beta.14 и более ранних.
- Выполните полное удаление и новую установку нашего приложения.
- Быстро увеличивайте и уменьшайте масштаб карты, чтобы вызвать большое количество запросов фрагментов.
- В конце концов (обычно в течение одной минуты — хотя это зависит от того, как часто приложение обращается к своей локальной базе данных) приложение полностью аварийно завершает работу со следующей трассировкой стека:
Ожидаемое поведение
Mapbox не должен повредить локальную базу данных приложения.
Примечания/предварительный анализ
Анализируя байты заголовка файла базы данных после повреждения, мы получаем 53 51 4C 69 74 14 03 03 00 01 01 17 03 03 00 13, что соответствует строке UTF-8 "SQLit���������� ".
Похоже, что выполнение большого количества запросов плиток каким-то образом повреждает сам файл базы данных или перезаписывает некоторые из его байтов.
Дополнительные ссылки и ссылки
Текст был успешно обновлен, но возникли следующие ошибки:
dlmcauslan прокомментировал 5 мая 2021 г.
@kkaefer спасибо за быстрый ответ. Да, вы правы, использование Mapbox SDK повреждает другую базу данных в нашем приложении (не базу данных mapbox).
Я протестировал несколько разных версий, и 10.0.0-бета.12, и 10.0.0-бета.14 подходят. Использование версий 10.0.0-beta.15 и 10.0.0-beta.18 привело к повреждению базы данных нашего приложения.
Насколько я могу судить, повреждение базы данных происходит, когда мы обращаемся к нашей базе данных, в то время как Mapbox делает большое количество запросов (~10 в секунду).
kiryldz прокомментировал 6 мая 2021 г.
@dlmcauslan, можете ли вы создать очень-очень простой образец приложения, как вы описали (используя ту же базовую конфигурацию, версию Mapbox Maps, Anko и т. д.), и посмотреть, воспроизводится ли там эта проблема с повреждением БД. Если это так, я был бы признателен, если бы вы могли поделиться этим примером кода, чтобы мы могли двигаться быстрее с нашей стороны. Спасибо!
kkaefer прокомментировал 6 мая 2021 г.
@dlmcauslan Я попытался воспроизвести эту проблему, создав пример приложения с com.mapbox.maps:android:10.0.0-beta.18 и org.jetbrains.anko:anko-sqlite:0.10.8 . Приложение создает представление карты и открывает базу данных, в которую каждую секунду вставляется новая строка. Я тестировал это как в обычном режиме, так и с параметром ResourceOptions.loadTilePacksFromNetwork, установленным в true. Даже после панорамирования (что вызывает больше операций с базой данных, поскольку мы загружаем больше данных и сохраняем их в кеше), мне не удалось инициировать событие повреждения.
Я протестировал это с помощью эмулятора и физического Google Pixel XL, оба работают под управлением Android 10.
kkaefer прокомментировал 6 мая 2021 г.
- Используете ли вы ResourceOptions.loadTilePacksFromNetwork? Этот параметр по умолчанию имел значение true в более ранних версиях, но по умолчанию имеет значение false в текущей бета-версии. 18.
- SEGV_MAPERR указывает на проблему с отображением памяти, которое мы используем, когда этот параметр включен.
- Используете ли вы в своем приложении какой-либо другой код, использующий сопоставление памяти?
в то же время Mapbox делает большое количество запросов (~10 в секунду).
Как вы оцениваете, что Mapbox делает большое количество запросов?
dlmcauslan прокомментировал 7 мая 2021 г.
Я ожидаю, что разница между созданным вами примером приложения и тем, которое создал я, заключается в том, что вы вставляли новую строку в базу данных каждую секунду, в то время как в моем тестовом приложении я вставляю строку в базу данных каждые 20 мс ( Я могу увеличить это время до 100 мс и все равно надежно воссоздать проблему).
Я не использую ResourceOptions.loadTilePacksFromNetwork . В созданном мной образце приложения я могу воспроизвести проблему, используя все настройки Mapbox по умолчанию. В моем приложении нет кода, использующего сопоставление памяти.
Я удалял и переустанавливал приложение много раз, и каждый раз я могу надежно воспроизвести повреждение.
Я оценил, что Mapbox делает большое количество запросов, установив для Logcat значение Verbose. Затем я получаю большое количество сообщений, подобных этому:
Я рвал на себе волосы, пытаясь получить собственную автономную карту Mobile Atlas Creator OSMDroid SQLite, работающую с OSMDroid 3.0.8, но безуспешно. Прошло долгих 3 дня. Попробую объяснить на клипах из моего приложения.Я расширил ItemizedIconOverlay и OverlayItem, поэтому надеюсь, что это не слишком запутывает.
Я создал свой собственный файл карты OSMDroid SQLite с 3 различными уровнями масштабирования для небольшого участка, например, 10 квадратных километров. Я скопировал полученный файл «base.sqlite» в каталог проекта /res/raw/. Обратите внимание, что GeoPoints в моем приложении должны находиться в пределах диапазона фрагментов карты. Файл base.sqlite должен быть сохранен в каталоге данных конкретного приложения.
Затем я очистил каталог /osmdroid на своем телефоне, чтобы удалить ранее сохраненные в кеше карты. Я думал, что мои собственные автономные карты работают, пока я не включил режим полета и не заметил, что кэшированные карты все еще доступны.
Теперь все, что я получаю, это пробелы. Я понятия не имею, как это сделать. Я видел пару примеров, но после множества экспериментов мне не удалось заставить ни один из них работать.
2 ответа 2
Хорошо! Я знаю, что я делаю неправильно, и теперь у меня все работает! (Я взволнован :)
Во-первых, у меня возникли проблемы с записью файла карты необработанных ресурсов в каталог конкретного приложения (например, openFileOutput()). Я использую Galaxy Nexus, в котором нет слота SD, поэтому я не могу сбросить карту. файл на SD. Убедитесь, что файл карт, который вы собираетесь использовать, имеет размер байта по сравнению с исходной копией. Перспектива Eclipse DDMS полезна для просмотра файловой структуры устройства.
Я также переключился на формат OSMdroid Zip. Затем я убедился, что имя XYTileSource() соответствует каталогу, созданному в Zip-файле с помощью MOBAC, а также удостоверился, что размер плитки и уровни масштабирования совпадают.
MOBAC по умолчанию создает фрагменты размером 256 пикселей. Я создал файл атласа с уровнями масштабирования 16, 17 и 18. PNG — это формат изображения плитки MOBAC по умолчанию.
Кроме того, если в вашем файле карты есть какие-либо проблемы, ArchiveFileFactory.getArchiveFile() обнаружит их даже раньше, чем MapTileFileArchiveProvider.
Вот мое использование. Просто приложите все усилия, чтобы правильно настроить IArchive, и все будет в порядке:
Возможно, я единственный, у кого были проблемы с этим, но osmdroid четко не документирует, как это сделать, и когда я открыл проблему, я не смог заставить их прокомментировать мое использование. Если бы они сказали, что я правильно реализую MapTileFileArchiveProvider или включили хороший пример автономного сопоставления, я бы сначала сосредоточился на всем остальном.
Пожалуйста, предположим, что у меня нет понимания внутренней работы файлов SQLite.
Я изо всех сил пытаюсь понять, почему некоторые приложения и программы правильно отображают объекты SQL, которые я экспортирую из растровых данных, в то время как другие приложения и программы отображают фрагменты в нечетных местах с неправильными уровнями масштабирования. Почему это?
Чтобы узнать подробнее, я использую ГИС-программу Global Mapper для экспорта растровых данных в файлы SQLite, обычно фрагменты PNG. Обычно я использую SQLite в OsmAnd, картографическом приложении с открытым исходным кодом для Android. OsmAnd правильно отображает SQLite из более ранних версий Global Mapper. SQLite, экспортированные из более поздних версий GM, неправильно отображаются в OsmAnd. Locus Maps для Android корректно отображает как более ранние, так и более поздние экспорты.
У меня такой же опыт с MBTiles. OpenCPN для Android некорректно отображает более поздние версии экспорта файлов MBTiles, в отличие от Locus Maps. Это та же проблема?
Спасибо за ваше время!
(2) Автор Уоррен Янг (wyoung) 17 мая 2020 г., 18:22:12 в ответ на 1 [ссылка] [источник]
Я предполагаю, что вы искажаете данные PNG при импорте или экспорте и что некоторые из этих приложений имеют более устойчивые декодеры PNG, чем другие.
Однако если вы хотите большего, чем предположения, вам придется предоставить гораздо больше деталей. Например, рассмотрите возможность совместного использования однострочной базы данных SQLite, содержащей плитку, которая, по вашему мнению, неправильно отображается в некоторых приложениях. Тогда мы сможем хотя бы помочь вам проверить совместимость файловых данных.
(3) Кит Медкалф (kmedcalf) 17 мая 2020 г., 18:26:56, в ответ на 1 [ссылка] [источник]
Да, основная причина та же. Приложения "глючат".
SQLite просто сохраняет и извлекает данные. Что-то вроде секретарши и картотеки этой секретарши. Однако секретарь не несет ответственности за содержание файлов, хранящихся и извлекаемых. Если босс запрашивает кучу файлов для создания доски с картинками, и это выглядит дерьмово, это не вина секретаря. Это вина того, кто подготовил содержимое файлов для хранения секретарем в первую очередь или кто обрабатывал файлы после того, как секретарь их получил.
Приложение обрабатывает данные для хранения, а затем снова обрабатывает их для отображения. Это махинации (в приложении), которые испорчены.
osmdroid обеспечивает готовую поддержку нескольких различных типов автономных кэшей фрагментов карты.
- разновидность базы данных sqlite от osmdroid (рекомендуется)
- ZIP-файл osmdroid
- MBTiles
- ГЭМФ
- GeoPackage (все еще в разработке)
Есть несколько вариантов.
Упаковщик листов карты OSM
osmdroid поставляется с инструментом, позволяющим загружать фрагменты и сохранять их для автономного использования, который называется OSM Map Tile Packager . Дополнительную информацию см. в файле readme.md.
Создатель мобильных атласов (MOBAC)
MOBAC – это самый простой в использовании инструмент, который поддерживает огромное количество источников входных карт и выходных форматов (и имеет открытый исходный код).
- Создайте новый атлас, используя поддерживаемые типы (osmdroid SQLite)
- Выберите источник карты
- Выберите ограничивающую рамку для нужной области и уровни масштабирования, которые вы хотите получить.
- Нажмите "Добавить выбор".
- Нажмите "Создать атлас".
- После этого скопируйте файл атласа (.sqlite, .zip и т. д.) на устройство с osmdroid в папку /sdcard/osmdroid/.
- Укажите osmdroid не использовать сетевое подключение и установите источник фрагмента карты. **
Использовать диспетчер кэша osmdroid на устройстве (> версии 5.2)
- кэш загруженных фрагментов – это кеш тайлов с истекающим сроком действия, который osmdroid загрузил из онлайн-источника тайлов. Он истекает. Срок действия по умолчанию основан на том, что указано онлайн-источником плитки, или на двух неделях. Кэш также имеет ограничения в отношении того, сколько места ему разрешено использовать на устройствах пользователя. Обе эти настройки можно изменить и переопределить с помощью OpenStreetMapTileProvideConstants для версии. Архивы плиток являются постоянными, срок действия хранилищ плиток не истекает. Это отлично подходит для офлайн-пользователей, однако необходимо соблюдать осторожность, чтобы понять, какие права на использование онлайн-источника плитки предоставляются для плиток. Многие онлайн-источники прямо запрещают вам создавать постоянное хранилище плиток. Внимательно прочитайте права на использование.
Диспетчер кеша может выполнять ряд задач, в том числе
- Скачивание всех фрагментов в заданной ограничивающей рамке и с заданными уровнями масштабирования.
- Загрузить все фрагменты, которые пересекают заданный набор точек (например, маршрут из точки А в точку Б) и уровни масштабирования.
- Очистить все фрагменты для заданных границ, уровня масштабирования и источника фрагментов.
- Очистить все плитки для заданного набора точек (опять же, точки от A до B)
Для работы диспетчеру кеша необходимы две вещи. Онлайн-источник плитки и автор плитки. Для программ записи тайлов по умолчанию для API 8–9 используется кеш на основе файловой системы (запись в формате архива zip с использованием файловой системы). API10 и более поздние версии по умолчанию используют SqlTileWriter, который использует базу данных sqlite для хранения плиток (что быстрее и позволяет избежать ряда проблем с максимальным количеством плиток в папке).
Примеры диспетчера кеша
Важное примечание об именах источников тайлов.
При загрузке источников карт с использованием MOBAC и с использованием одного из следующих форматов
В обоих этих случаях имя источника карты закодировано в формате базы данных или zip-файла и используется для сохранения уникальности (более одного источника тайлов в одном архиве). Поэтому вы ДОЛЖНЫ сообщить osmdroid точное имя источника карты при запросе автономных плиток.
Подсказки
MOBAC накладывает ограничение на количество плиток, загружаемых за один раз. Этого можно избежать, изменив исходный код.
MOBAC, особенно с огромными наборами фрагментов, может потреблять много памяти. Это алгоритмы, по крайней мере, от 1.8 до 1.9.x, которые высвобождают как можно больше кешей в памяти, пока не достигнут потолка JVM, а затем выполняют пакетные вставки в sqlite. Хотя это способ сделать вставки SQLite максимально быстрыми, это может привести к проблемам со стабильностью с MOBAC.
Многие источники карт имеют заявления об отказе от ответственности и юридические положения, в которых конкретно указано, что НЕ следует кэшировать и повторно размещать изображения карты. У некоторых может быть формулировка, запрещающая вам использовать их изображения карты в автономном режиме или загружать большие части мира. Убедитесь, что вы прочитали мелкий шрифт! osmdroid не несет ответственности за неправильное использование изображений карты. Это между вами и владельцем изображения.
Мы с радостью примем запросы на вытягивание. Тем не менее, довольно просто создать новый источник тайлов для osmdroid. Вот основные шаги:
- Создайте класс, реализующий IArchiveProvider. На самом базовом уровне IArchiveProvider необходимо преобразовать координаты плитки OSM (масштаб, координаты X и Y) в InputStream, представляющий плитку, если он доступен.
- Зарегистрируйте IArchiveProvider в ArchiveFileFactory
- Создайте, разверните и запустите osmdroid
Да! Однако ответ зависит от того, какую версию osmdroid вы используете.
См. setCachePath и TILE_PATH_BASE . Несмотря на то, что класс называется Constants, многие поля доступны для записи. Вы можете использовать это, чтобы настроить ряд параметров в соответствии с вашими потребностями.
Из коробки имеем следующее (и проверяются именно в таком порядке)
- Ресурсы, вы можете поместить разобранные ZIP-архивы в папку с ресурсами вашего приложения.
- Локальная файловая система (архивы, такие как zip, sqlite и т. д.)
- Кэш сетевых источников — по умолчанию /sdcard/osmdroid/tiles/cache.db
- Сетевые источники — загружайте то, что вам нужно, когда вам это нужно
Место хранения
Эта часть довольно проста. Скопируйте свои плитки в базовый путь osmdroid (по умолчанию /sdcard/osmdroid). Это расположение можно изменить программно (обратите внимание, что это поведение изменится в версии 5.6). У вас должна быть следующая структура директора
Итак, теперь, когда у вас есть архивы, есть несколько вариантов и механизмов, которые можно использовать, чтобы помочь вам на пути к блаженству без связи. Следующим шагом является информирование поставщика фрагментов карты osmdroid о фрагментах карты.
Параметры поставщика фрагментов карты
По умолчанию Map Tile Provider для osmdroid автоматически сканирует базовый путь osmdroid (опять же /sdcard/osmdroid/) на наличие известных ему архивов фрагментов, а также выполняет поиск в папке «Активы» вашего APK (только фрагментированные фрагменты), а затем, наконец, в сети. источники.
Если это вас не утоляет, есть еще OfflineOnlyTileProvider . Дополнительную информацию см. в документе Javadoc.
Но у меня есть собственный формат тайлового архива, который я должен был использовать!
Отлично, реализуйте интерфейс IArchiveFile, а затем зарегистрируйте свою реализацию в ArchiveFileFactory
Установите источник плитки
Теперь вам нужно указать osmdroid, какое имя источника плитки использовать. Это необходимо, поскольку файловые архивы могут иметь более одного источника листов, а источники листов могут быть распределены по нескольким архивам. Если вы заранее знаете имя источника, вы можете использовать следующее.
Если вы заранее не знаете имя источника плитки или планируете часто его менять, вы можете узнать доступные имена источников плитки во время выполнения. Интерфейс IArchiveFile имеет метод, который можно использовать для запроса в архиве «имени источника плитки». См. getTileSources. См. пример использования SampleOfflineOnly.
Предостережения и исключения
MBTiles не сохраняет имя источника тайла в базе данных. В этом случае вызов IArchiveFile.getTileSources вернет пустой набор. С другой стороны, файлы MBTiles будут отображаться на карте независимо от того, какой источник тайлов установлен в mapView.
Можно удалить все проверки сравнения имен источников плиток для автономных плиток, что в результате приведет к созданию составного источника плиток. Это может отлично сработать, если ваши архивы не пересекаются. Для этого расширьте существующие провайдеры IArchiveFile, чтобы удалить проверки, а затем зарегистрируйте их как с помощью ArchiveFileFactory
Добавление нового поставщика файлового архива
У вас есть собственный формат автономного хранения плиток? Отлично.
Создайте новый класс, реализующий org.osmdroid.tileprovider.modules.IArchiveFile . Есть только несколько методов для реализации, и реализация собственного должна быть тривиальной. Имейте в виду, что для каждого файла архива будет один экземпляр этого класса и что каждый экземпляр может быть вызван из нескольких потоков одновременно. Старайтесь избегать ситуаций, когда необходима синхронизация.
Зарегистрируйте его перед созданием карты. Это значит перед раздуванием макета. Хорошее место было бы где-нибудь в вашем классе приложений.
Читайте также: