我想在Android上的Xamarin中使用Spatialite而不是普通的SQLite来管理和显示地理数据。内置的SQLite不允许加载扩展。我该怎么做?
简短答案:您需要像其他NDK库一样使用自己的自定义SQLite作为Android本机库。棘手的部分是获得有用的而不是琐碎的C#API。Xamarin文档似乎仅具有非常简单的单方法API的指南。
由于我对Java的熟悉程度远超过.Net,因此我使用了Android Java库(.jar)和Android本机库(.so)的组合。Android Java库已经为数据库提供了Java API包装器,它与通常的Android Java应用程序中使用的包装器完全相同。当然,从C#技术上直接访问本机库也是可能的,因此可以将Java / jar从故事中排除。如果您知道用于此目的的好的工具,也请告诉我。
<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>
这将为您生成绑定捆绑的SQLite的有效C#API,以及Spatialite,Proj.4和GEOS。jsqlite DB API本身与其他C#SQLite API不同,您需要使用回调类。请参阅以下示例,以检查模块的版本:
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);
}
}
最后,现在使用Xamarin的Nutiteq 3D Maps SDK可视化真实的空间数据:
// 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;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句