如何在Android上使用Xamarin与Spatialite

6

我想在Xamarin Android上使用Spatialite来管理和显示地理数据,而不是普通的SQLite。内置的SQLite不允许加载扩展。我该怎么做?

1个回答

7
简短回答:您需要使用自定义 SQLite 作为 Android 原生库,就像使用其他 NDK 库一样。棘手的部分是获取有用的不那么琐碎的 C# API 用于数据库。Xamarin 文档似乎仅适用于非常简单的单个方法 API 的指南。
由于我比 .Net 更熟悉 Java,所以我使用了 Android Java 库 (.jar) 和 Android 原生库 (.so) 的组合。Android Java 库已经有了数据库的 Java API 包装器,它与普通的 Android Java 应用程序中可以使用的包装器完全相同。当然,在技术上也可能直接从 C# 访问原生库,因此可以排除 java/jar。如果您知道好的工具,请告诉我。
步骤如下:
1. 为 Xamarin 创建 .jar 绑定项目,并将其添加到与 Android 项目相同的解决方案中 2. 将 jsqlite.jar 添加到 bindings 项目的 Jars 文件夹中。从此处获取它:jsqlite.jar 3. 将本地库二进制文件 (libjsqlite.so 和 libproj.so) 添加到您的应用程序项目中,并为此创建 libs/armeabi 文件夹。从此处获取它们:Nutiteq AdvancedMap3D 项目 4. 将 .so 文件定义为 AndroidNativeLibrary,并将其设置为“复制到输出目录” 5. 修复绑定定义以消除构建错误。在 bindings 项目的 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>

这应该会为您生成一个能够捆绑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);
    }
}

最后,现在我们使用Nutiteq 3D Maps SDK for 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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接