ArcGIS for Android离线数据编辑实现原理
来自:http://blog.csdn.net/arcgis_mobile/article/details/7565877
ArcGIS for Android中现已经提供了离线缓存图片的加载功能,极大的提高了我们访问地图的效率,对于离线的数据编辑暂时还不支持,而现在对于离线数据编辑操作的需求越来越多,那我们如何才能实现离线数据编辑功能呢?下面我们介绍一下,通过sqlite来实现离线数据编辑的解决方案。
一、离线数据编辑解决方案
离线编辑无非就是将所需的数据下载到我们的手持端进行存储,当无法连接网络时,数据的读取、显示、编辑、保存都是通过本地数据库完成的;而后,当可以连接网络时,再将编辑的数据从手持端的数据库中提取出来进行在线数据提交。
二、离线数据编辑实现步骤
根据上面的流程图我们来分析一下,实现离线数据编辑的步骤:
1、 通过ArcGIS Server来发布一个FeatureService服务用于数据下载或上传;
2、 手持端编写通过服务请求业务数据的代码;
在手持端编写下载数据的代码,通过FeatureService服务进行数据的下载,代码如下:
Query query = new Query();
query.setOutFields(new String[] {"*" }); query.setInSpatialReference(featureLayer.getSpatialReference());
query.setWhere("objectid in ("+where+")");
flayer.selectFeatures(query, ArcGISFeatureLayer.SELECTION_METHOD.NEW,new CallbackListener<FeatureSet>() {
publicvoid onError(Throwable e) {
}
publicvoid onCallback(FeatureSet queryResults) {
}
});
3、 在手持端创建数据库和业务数据表;
在手持端中,我们需要数据库来存储业务数据,因此我们需要创建Sqlite数据库和相应的业务表。
在创建数据库时,我们可以通过扩展Android的帮助类SQLiteOpenHelper来维护和操作数据库和表,创建的表要与我们下载的业务数据的表结构一致。
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String SYSTEM_TABLE = "sqlite_master";
private static final int VERSION=1;
public static final String TABLEORFIELDS = "tableOrfields";
public static final String TABLENAME = "Environment";
public DatabaseHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
public DatabaseHelper(Context context, String name){
this( context, name,VERSION);
}
public DatabaseHelper(Context context, String name,int version){
this(context,name,null,version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建的表结构
String sql = "CREATE TABLE IF NOT EXISTS "+TABLENAME+"(OBJECTID INTEGER,CODE INTEGER,省名 TEXT,县区名 TEXT,土地覆盖 TEXT, SHAPE TEXT, MARK INT) ";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
4、 将下载的数据存储到创建的数据库中;
将第2步下载的要素数据,储存到事先创建好的数据库中,要素的属性我们可以直接存储到我们创建的表中,由于sqlite数据库不支持空间数据类型,因此对于要素的空间几何的存储成为要点,对此,我们可以将空间几何解析拼凑成定制的字符串进行存储,我们可以按照WKT格式拼字符串,如,点:point ( 10.05 10.28 ),线:linestring ((10.0510.28 , 20.95 20.89 )),面:polygon ((10 10, 10 20, 20 20, 20 15, 10 10))。
将空间几何对象转成WKT的核心代码如下:
/** * 将几何对象生成wkt字符串 */ public static String GeometryToWKT(Geometry geometry){ if(geometry ==null){ return null; } String geoStr = ""; Geometry.Type type = geometry.getType(); if("Point".equals(type.name())){ Point pt = (Point)geometry; geoStr = type.name()+"("+pt.getX() +" "+pt.getY()+")"; }else if("Polygon".equals(type.name()) ||"Polyline".equals(type.name())){ MultiPath pg = (MultiPath)geometry; geoStr = type.name()+"("+""; int pathSize = pg.getPathCount(); for(int j=0;j<pathSize;j++){ String temp = "("; int size = pg.getPathSize(j); for(int i=0;i<size;i++){ Point pt = pg.getPoint(i); temp +=pt.getX() +" "+pt.getY()+","; } temp = temp.substring(0, temp.length()-1)+")"; geoStr +=temp+","; } geoStr = geoStr.substring(0, geoStr.length()-1)+")"; }else if("Envelope".equals(type.name())){ Envelope env = (Envelope)geometry; geoStr = type.name()+"("+ env.getXMin() +","+env.getYMin()+","+env.getXMax()+","+env.getYMax()+")"; }else if("MultiPoint".equals(type.name())){ }else{ geoStr = null; } return geoStr; } |
将查询的数据插入到sqlite的核心代码:
//数据批量插入 private void insertGraphics(Graphic[] gps){ //开启事务,使用事务为了提高数据操作的效率 db.beginTransaction(); for(Graphic gp : gps){ ContentValues values = new ContentValues(); String[] attributs = gp.getAttributeNames(); for(String att : attributs){ Object attStr = gp.getAttributeValue(att); String temp = ""; if(attStr ==null){ }else{ temp = gp.getAttributeValue(att).toString(); } values.put(att,temp ); } Geometry gt = gp.getGeometry(); String wktStr = GeometryToWKT(gt); values.put("shape",wktStr); values.put("mark", 0); db.insert(DatabaseHelper.TABLENAME,null, values); } db.setTransactionSuccessful();//设置事务成功 db.endTransaction();//结束事务 |
插入数据时启用Sqlite的事务机制,可以提高批量插入数据的速度。
5、 离线状态时,查询手持端数据库中的数据在设备上展示;
当我们要显示数据时,可以将数据库的数据查询出来,将查询的每条记录生成空间要素对象属性,将我们上面拼凑的字符串反解析生成空间要素对象,也就是将WKT数据格式解析成为一个空间要素对象。
将WKT数据字符串解析成空间几何对象的核心代码:
/** * 将wkt字符串拼成几何对象 */ public static Geometry WKTToGeometry(String wkt){ Geometry geo = null; if(wkt ==null || wkt ==""){ return null; } String headStr = wkt.substring(0, wkt.indexOf("(")); String temp = wkt.substring(wkt.indexOf("(")+1, wkt.lastIndexOf(")")); if(headStr.equals("Point")){ String[] values = temp.split(" "); geo = new Point(Double.valueOf(values[0]),Double.valueOf(values[1])); }else if(headStr.equals("Polyline") || headStr.equals("Polygon")){ geo = parseWKT(temp,headStr); }else if(headStr.equals("Envelope")){ String[] extents = temp.split(","); geo = new Envelope(Double.valueOf(extents[0]),Double.valueOf(extents[1]),Double.valueOf(extents[2]),Double.valueOf(extents[3])); }else if(headStr.equals("MultiPoint")){ }else{ return null; } return geo; } private static Geometry parseWKT(String multipath,String type){ String subMultipath = multipath.substring(1, multipath.length()-1); String[] paths; if(subMultipath.indexOf("),(") >=0 ){ paths = subMultipath.split("),(");//多个几何对象的字符串 }else{ paths = new String[]{subMultipath}; } Point startPoint = null; MultiPath path = null ; if(type.equals("Polyline")){ path = new Polyline(); }else{ path = new Polygon(); } for(int i=0;i<paths.length;i++){ String[] points = paths[i].split(","); startPoint = null; for(int j=0;j<points.length;j++){ String[] pointStr = points[j].split(" "); if(startPoint ==null){ startPoint = new Point(Double.valueOf(pointStr[0]),Double.valueOf(pointStr[1])); path.startPath(startPoint); }else{ path.lineTo(new Point(Double.valueOf(pointStr[0]),Double.valueOf(pointStr[1]))); } } } return path; } |
6、 在设备上编辑要素数据;
对于要素的编辑可以分为两方面,一方面是属性的编辑,另一方面是空间编辑,对于这两方面的操作,官方提供的例子中提供了类似的功能(AttributeEditor和GeometryEditor两个例子)。
1)属性编辑
对于属性修改无非就是对Graphic对象的中的属性进行修改, Graphic不能添加事件监听,所以不能像按钮一样,添加一个点击事件弹出该要素的相关信息,我们可以通过GraphicsLayer的getGraphicIDs(float x, float y,int tolerance)方法来获取要素及其要素的相关属性,可悲是Graphic中没提供修改属性的接口,只能新建一个Graphic对象并在他的构造方法中来添加更新后的属性或者是通过GraphicsLayer的updateGraphic(int id,Map<String,Object> attributes)的方法来更新Graphic的属性,并且将修改的要素属性更新到本地sqlite数据库中及其修改表中mark字段的状态。
2)空间编辑
对于Graphic对象我们不仅可以改变他的属性还可以修改它的空间位置信息,对于点、线、面的修改略有不同。
点修改时,直接更新Graphic的Geometry即可,不过Graphic没有提供修改Geometry的接口,我们只能通过GraphicsLayer的updateGraphic(int id,Geometry geometry)方法来实现更新它的空间位置。
线和面的空间位置改变主要指的是线或面的节点的位置修改,我们可以点击线或面上的一个节点进行拖动用GeometryEngine.getNearestVertex()可以得到我们点击的点,距离几何体的哪个节点最近,并返回一个Proximity2DResult对象,通过这个对象我们可以得到这个节点Index位置,再通过线或面对象的setPoint(int index,Point point)方法更新节点,这时我们的图形就可以改变了,将更新后的Graphic的空间对象重新解析成定义的格式入库及其修改表中mark字段的状态。
7、 将编辑后的数据更新到设备数据库中;
将编辑后的数据通过第4步的方式更新到本地数据库中,更新数据的代码如下:
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
db.update(table, values, whereClause, whereArgs);
db.setTransactionSuccessful();
db.endTransaction();
如果要多次更新时,可以使用sqlite数据库的事务机制,来提高执行效率。
8、 在线时通过ArcGIS Server的服务提交业务数据;
通过sqlite查询,将本地数据库中的数据查询出来,并将数据拼成空间要素对象,再通过FeatureService服务将数据更新到图层上。
更新数据代码如下:
Graphic[] gps = new Graphic[list.size()];
gps = list.toArray(gps);
featureLayerupdate.applyEdits(null, null, gps, null)
List为Graphic对象的列表,上面的操作是更新操作,如果需要添加或删除只需将Graphic数组放到不同的参数位置上即可。
到此,离线数据编辑操作基本完成,待日后spatialite空间数据库日渐完善后,离线编辑将变的更加简单,期待中。
ArcGIS for Android离线数据编辑实现原理的更多相关文章
- Arcgis for android 离线查询
参考.. 官方API demo ... 各种资料 以及.. ArcGIS for Android示例解析之高亮要素-----HighlightFeatures ttp://blog.csdn.net/ ...
- arcgis for android常见问题回答
Q:arcgis for android最新版本是多少?(2014-7-18) Arcgis for android 10.2.3 sdk 百度盘下载地址:http://pan.baidu.com/s ...
- ArcGIS For Android 的标绘与可视化
参考 1. CSDN 相关博文 2. ArcGIS for Android 离线数据空间分析--叠加分析 3. ArcGIS for Android Runtime100 基本操作(五)——绘制图层和 ...
- Arcgis For Android之离线地图实现的几种方式
为什么要用,我想离线地图的好处是不言而喻的,所以很多人做系统的时候都会考虑用离线地图.在此,我给大家介绍几种Arcgis For Android下加载离线地图的方式. 在Arcgis For Andr ...
- ArcGis for Android 工作与学习
ArcGis安装 需求 windows7(32/64) Eclipse3.6以上版本 Android Sdk 2.2以上 Jdk 7 安装步骤 Eclipse安装 下载ArcGis插件 在Eclips ...
- 外业数据采集平台(GPS+Android Studio+Arcgis for android 100.2.1)
外业数据采集平台 1. 综述 在室外,通过平板或者手机接收GPS坐标,实时绘制点.线.面数据,以便为后续进行海域监测.土地确权.地图绘图提供有效数据和依据. 2. 技术路线 Android studi ...
- 【Arcgis for android】相关教程收集自网络
请加入qq群:143501213 一起交流和学习 推荐博客: 张云飞VIR http://www.cnblogs.com/vir56k/tag/arcgis%20for%20android/ arcg ...
- Android端代码染色原理及技术实践
导读 高德地图开放平台产品不断迭代,代码逻辑越来越复杂,现有的测试流程不能保证完全覆盖所有业务代码,测试不到的代码及分支,会存在一定的风险.为了保证测试全面覆盖,需要引入代码覆盖率做为测试指标,需要对 ...
- 创建一个ArcGIS for Android 新项目并显示出本地的地图
1.准备工作:首先要配置好android的开发环境,然后在Eclipse中安装ArcGIS for Android的开发控件:在ArcCatalog中发布好本地的地图服务. 2.安装完ArcGIS f ...
随机推荐
- 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)
本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...
- 洛谷——P2680 运输计划
https://www.luogu.org/problem/show?pid=2680 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每 ...
- 异常详细信息: System.ComponentModel.Win32Exception: 信号灯超时时间已到
- ARP是如何工作的?
我们知道,当我们在浏览器里面输入网址时,DNS服务器会自动把它解析为IP地址,浏览器实际上查找的是IP地址而不是网址.那么IP地址是如何转换为第二层物理地址(即MAC地址)的呢? 在局域网中,这是通过 ...
- Asp.Net MVC中Controller、Action、View是如何激活调用的
上篇我们介绍了MVC的路由,知道在注册路由的时候会创建一个MvcHandler将其和Url规则一起放入到了RouteCollection中,之后请求通过UrlRoutingModule,根据当前的UR ...
- zabbix4.2学习笔记--监控tomcat
zabbix提供了一个java gateway的应用去监控jmx(Java Management Extensions,即Java管理扩展)是一个为应用程序.设备.系统等植入管理功能的框架 环境 主机 ...
- 奇异值分解 SVD 的数学解释
奇异值分解(Singular Value Decomposition,SVD)是一种矩阵分解(Matrix Decomposition)的方法.除此之外,矩阵分解还有很多方法,例如特征分解(Eigen ...
- iOS Development Sites
iOS Development Sites 学习iOS开发有一段时间了,虽然还处于迷茫期,但相比以前的小白痴状态,现在还是蛮有改观的.期间接触了一些很好的网站和博客,现在摘录下来,就当建个索引,没 ...
- 关键字搜索高亮jQuery插件
// textSearch.js v1.0 文字,关键字的页面纯客户端搜索// 2010-06-23 修复多字母检索标签破碎的问题// 2010-06-29 修复页面注释显示的问题// 2013-05 ...
- python 语法之 装饰器decorator
装饰器 decorator 或者称为包装器,是对函数的一种包装. 它能使函数的功能得到扩充,而同时不用修改函数本身的代码. 它能够增加函数执行前.执行后的行为,而不需对调用函数的代码做任何改变. 下面 ...