Intereting Posts
Диспетчер тегов: как загрузить двоичный контейнер по умолчанию? Разница между андроидами Android: обрезать изображение после его съемки с камерой с фиксированным соотношением сторон Как загрузить ImageView по URL в Android? Как получить идентификатор facebook у пользователя через API ContactsContracts? Получил эту ошибку с помощью retrofit2 & OkHttp3. Не удалось разрешить хост «<имя-хоста>»: нет адреса, связанного с именем хоста Почему криптообъект необходим для проверки подлинности отпечатка пальца андроида? Могу ли я использовать AlarmManager с LocalBroadcastManager на Android? Как установить рынок Android на эмулятор для всех api's Не удалось развернуть приложение с помощью Device Chooser после обновления Android Studio до версии 1.4 Лучшая практика для внедрения пары ключ-значение в android Spinner Звук HTML5 не воспроизводится несколько раз в устройстве Android 4.0.4 Собственный браузер Как обернуть заголовок предпочтения? (В самом деле) Соединение wifi изменило действие в android Как узнать, отображается ли вид на экране в Android?

Как использовать Spatialite с Xamarin на Android

Я хочу использовать Spatialite вместо простого SQLite с Xamarin на Android, чтобы управлять и отображать географические данные. Встроенный SQLite не позволяет загружать расширения. Как мне это сделать?

Короткий ответ: вам нужно использовать собственный настраиваемый SQLite в качестве базовой библиотеки Android, например, с другими библиотеками NDK. Сложная часть – получить полезный не такой простой API C # для базы данных. Документы Xamarin, похоже, имеют руководства только для простых простых API-интерфейсов.

Поскольку я более привык к Java, чем .NET, тогда я использовал комбинацию Android Java library (.jar) и родной библиотеки Android (.so). В библиотеке Android Java уже есть оболочка API Java для базы данных, это точно такая же оболочка, которая может использоваться в обычных приложениях Java Java. Разумеется, также возможен технически прямой доступ к родной библиотеке из C #, поэтому java / jar можно исключить из истории. Если вы знаете хорошие инструменты для этого, дайте мне знать.

  1. Создайте проект привязки jar для Xamarin, добавьте его в то же решение, что и ваш Android-проект
  2. Добавьте jsqlite.jar в папку Jars проекта bindings . Получите это отсюда: jsqlite.jar
  3. Добавьте в свой проект приложения собственные библиотеки (libjsqlite.so и libproj.so), создайте для этого папку libs / armeabi. Получите их от проекта Nutiteq AdvancedMap3D
  4. Определите файлы .so в качестве AndroidNativeLibrary и установите Copy to Output Directory
  5. Исправьте определения привязки, чтобы удалить ошибки сборки. Добавьте в Transforms / Metadata.xml проект ваших привязок:
<remove-node path="/api/package[@name='jsqlite']/class[@name='Backup']/field[@name='handle']" /> <remove-node path="/api/package[@name='jsqlite']/class[@name='Database']/field[@name='handle']"/> <attr path="/api/package[@name='jsqlite']" name="managedName">jsqlite</attr> 

Это должно сгенерировать ваш рабочий C # API в комплекте SQLite вместе с Spatialite, Proj.4 и GEOS . Сам API DB jsqlite отличается от других API-интерфейсов C # SQLite, вам нужно использовать классы обратного вызова. См. Следующие примеры. Чтобы проверить версии модулей:

 try { db.Open ("/sdcard/mapxt/estonia-latest-map.sqlite", Constants.SqliteOpenReadonly); // show versions to verify that modules are there db.Exec ("SELECT spatialite_version(), proj4_version(), geos_version(), sqlite_version()", new GeneralQryResult ()); } catch (jsqlite.Exception ex) { Log.Error( ex.LocalizedMessage ); } ... // prints query results as text public class GeneralQryResult : Java.Lang.Object, ICallback { public bool Newrow (string[] rowdata) { string row = ""; foreach (var data in rowdata) { row += data + " | "; } Log.Info(row); return false; } public void Types (string[] types) { // never called really } public void Columns (string[] cols){ Log.Debug ("Query result:"); string row = ""; foreach (var col in cols) { row += col + " | "; } Log.Info (row); } } 

Наконец, теперь запрос реальных пространственных данных, используя Nutiteq 3D Maps SDK для Xamarin, чтобы визуализировать его:

 // Spatialite query, show results on map // 1. create style and layer for data LineStyle.Builder lineStyleBuilder = new LineStyle.Builder (); lineStyleBuilder.SetColor (NutiteqComponents.Color.Argb(0xff, 0x5C, 0x40, 0x33)); //brown lineStyleBuilder.SetWidth (0.05f); LineStyle lineStyle = lineStyleBuilder.Build (); GeometryLayer geomLayer = new GeometryLayer (view.Layers.BaseLayer.Projection); view.Layers.AddLayer (geomLayer); // 2. do the query, pass results to the layer Database db = new Database (); try { db.Open ("/sdcard/mapxt/estonia-latest-map.sqlite", Constants.SqliteOpenReadonly); // spatial query. Limit to 1000 objects to avoid layer overloading String qry = "SELECT id, HEX(AsBinary(Transform(geometry,3857))), sub_type, name FROM ln_railway LIMIT 1000"; db.Exec (qry, new SpatialQryResult (geomLayer, lineStyle)); } catch (jsqlite.Exception ex) { Log.Error( ex.LocalizedMessage ); } ... // adds query results to given layer, with given style public class SpatialQryResult : Java.Lang.Object, ICallback { GeometryLayer _geomLayer; Style _geomStyle; public SpatialQryResult(GeometryLayer geomLayer, Style geomStyle){ _geomLayer = geomLayer; _geomStyle = geomStyle; } public bool Newrow (string[] rowdata) { string id = rowdata [0]; string geomHex = rowdata [1]; string type = rowdata [2]; string name = rowdata [3]; Label label; if (name != null && name.Length > 1) { label = new DefaultLabel (name, type); } else { label = null; } Geometry[] lineGeoms = WkbRead.ReadWkb(new ByteArrayInputStream(Utils .HexStringToByteArray(geomHex)), rowdata); // following fails if not Line, change for other geometries foreach (Line lineGeom in lineGeoms) { _geomLayer.Add(new Line(lineGeom.VertexList, label, (LineStyle)_geomStyle, _geomLayer)); } return false; } }