ArcGIS for Android 开发教程


1 文档编号 PTM01_ Dt 101010001 版本号 V1.1 ArcGIS for Android 2.0 开发教程 基础版 Esri 中国信息技术有限公司 2012 年 12 月 2 《版权声明》 本文档版权为 Esri 中国信息技术有限公司所有。未经本公司书面许可,任何单位和个 人不得以任何形式摘抄、复制本文档的部分或全部,并以任何形式传播。 ——制定及修订记录—— 版本 完成日期 编写/修订纪要 编写者 备注 V0.10 2012-10-26 创建文档并撰写第 1~2 章 崔福东 V0.20 2012-12-7 撰写第 3~11 章 汤怀玉 V0.30 2012-12-12 撰写第 12~15 章 刘升容 V1.0 2012-12-18 内容合并,第 1~15 章审核、补充和修正 刘升容 3 目录 第一章. 基本概念 ...................................................................................................................................................... 1 1. Android 简介 ........................................................................................................................................................ 1 2. ArcGIS Runtime for Android 简介 .......................................................................................................................... 2 第二章. 开发环境配置 .............................................................................................................................................. 4 1. 系统要求 .............................................................................................................................................................. 4 2. Android 配置 ........................................................................................................................................................ 5 3. ArcGIS Runtime for Android 配置 .......................................................................................................................... 7 4. 使用 Android 模拟器开发 .................................................................................................................................... 8 5. 使用 Android 设备开发 ...................................................................................................................................... 10 第三章. 创建第一个 HelloWorld Map ................................................................................................................ 12 1. 创建项目 ............................................................................................................................................................ 12 2. 项目结构 ............................................................................................................................................................ 14 3. 编码实现 ............................................................................................................................................................ 16 第四章. 地图、图层及空间参考 ............................................................................................................................. 18 1. MapView 地图组件 ............................................................................................................................................ 18 2. 地图图层(Layer) ............................................................................................................................................ 21 3. SpatialReference ................................................................................................................................................. 26 第五章. 地图事件 .................................................................................................................................................... 28 1. MapOnTouchListener.......................................................................................................................................... 28 2. OnLongPressListener........................................................................................................................................... 29 3. OnPanListener .................................................................................................................................................... 29 4. OnPinchListener .................................................................................................................................................. 30 5. OnSingleTapListener ........................................................................................................................................... 30 6. OnStatusChangedListener ................................................................................................................................... 31 7. OnZoomListener ................................................................................................................................................. 31 第六章. 空间要素可视化 ......................................................................................................................................... 32 1. Graphic ............................................................................................................................................................... 32 2. Geometry ........................................................................................................................................................... 33 3. 符号渲染 ............................................................................................................................................................ 38 4 4. 信息窗口 ............................................................................................................................................................ 43 第七章. 查询检索 .................................................................................................................................................... 48 1. IdentifyTask ........................................................................................................................................................ 48 2. QueryTask .......................................................................................................................................................... 51 第八章. 几何计算(GeometryEngine) ............................................................................................................. 53 第九章. 定位 ............................................................................................................................................................ 55 第十章. 在线编辑 .................................................................................................................................................... 57 第十一章. 地理处理 ................................................................................................................................................ 59 第十二章. Portal API ............................................................................................................................................ 62 1. Portal API 概述 ................................................................................................................................................... 62 2. 连接 Portal ......................................................................................................................................................... 65 3. 获取组织的信息 ................................................................................................................................................ 65 4. 获取 user、group 和 items 的信息 .................................................................................................................... 66 5. 搜索 Portal ......................................................................................................................................................... 68 6. 使用 WebMap .................................................................................................................................................... 68 第十三章. 应用程序部署 ......................................................................................................................................... 71 1. 应用程序签名 .................................................................................................................................................... 71 2. 应用程序分发 .................................................................................................................................................... 73 第十四章. 学习资源 ................................................................................................................................................ 76 第十五章. 附录 ........................................................................................................................................................ 77 1. 如何制作离线地图数据 ..................................................................................................................................... 77 2. 如何发布 Feature Service ................................................................................................................................... 82 3. 如何发布 GP 服务 .............................................................................................................................................. 85 4. 如何向 ArcGIS Online 发布和共享服务 .............................................................................................................. 88 1 第一章. 基本概念 1. Android 简介 2007 年 11 月,Google 推出移动操作系统 Android,并宣称 Android 是首个为移动终端打造的真正开放和 完整的移动操作系统。自此,基于 Android 的手机和平板电脑开始陆续出现,并迅速占领市场。 Android 基于 Linux 内核,开放源代码,由 Linux 内核、系统运行库、应用程序框架和应用程序组成, 如下图所示:  Android 核心系统服务基于 Linux 内核,如安全性、内存管理、进程管理、网络协议栈和驱动模型。 内核作为一个抽象层,介于软件层和硬件层之间。  系统运行库包括系统库和运行库。系统库包含一些 C/C++库,能被 Android 系统中不同组件使用。 它们通过 Android 应用程序框架为开发者提供服务。运行库由核心库和 Dalvik 虚拟机构成。核心库 提供了 Java 编程语言核心库的大多数功能,每个 Android 应用程序都在自己的进程中运行,都拥有 一个独立的 Dalvik 虚拟机实例。  应用程序框架为应用程序开发者提供各种 API,Android 应用程序架构中的各种控件、服务都可以被 复用。 2  应用程序就是 Android 系统上提供各种功能,能与用户进行交互的软件了。Android 系统提供了拨 打电话、收发短信、联系人、桌面等基本应用程序。开发人员基于应用程序框架提供的 API,就可 以开发各式各样的应用程序了。 现在,基于 Android 系统的手机和平板电脑已经随处可见。兴许此刻,您就是在用 Android 平板电脑浏 览 ArcGIS_Mobile(http://blog.csdn.net/arcgis_mobile)博客,了解 ArcGIS Runtime for Android 开发 有关的内容。互联网上关于 Android 的资源也非常丰富。此处不再继续展开关于 Android 的介绍,具体请参 考 Android 开发者网站(http://developer.android.com)。 2. ArcGIS Runtime for Android 简介 ArcGIS Runtime SDKs for Smartphones and Tablets 是 Esri 为开发者提供的移动应用开发包,目前 支持 iOS、Android、Windows Phone 三大主流移动操作系统。只要注册了 Esri 全球账号,就可以免费下载各 个版本的开发包以及其它相关资料。ArcGIS Runtime SDK for Android 官方页面如下图所示。 在 ArcGIS Runtime SDK for Android 官网,可以在线浏览帮助页面、下载开发包、查看开发包对系统的 要求、如何安装开发包等等。另外,页面会列出新的博客和应用信息,为用户提供最新的技术资源。 3 ArcGIS Runtime SDK for Android 通过 ArcGIS Server REST 服务获取数据和服务资源。Esri 发布了 GeoServices REST Specification,这一标准规定了 ArcGIS REST Service 各种接口的访问参数及返回数据的 结构,ArcGIS Runtime SDK for Android 正是基于这一标准封装的。其实,ArcGIS 基于 REST 接口的 API,包 括 ArcGIS Runtime SDK for Android/IOS/Windows Phone,ArcGIS API for Flex/ Silverlight/ JavaScript, 以及 ArcGIS Runtime SDK for Java/.NET,都是基于这一标准进行封装的。尽管不同平台、不同语言的开发 包有其自己的特性,但其对应服务端的编程模型是一致的。下图能很好的说明这一点。 除了 ArcGIS Server,ArcGIS Runtime SDK for Android 还可以通过 Portal API 轻松访问 ArcGIS Online 上的资源。有关 Portal API,后面章节会详细介绍。 截止目前,ArcGIS Runtime SDK for Android 最新版本是 2.0。与 0.9 版本比较,1.0 以后的版本,SDK 架构发生了很大的变化。主要变化在于核心功能改由 C/C++编写,SDK 层(Java)通过 JNI 的方式调用,以此 提高效率。因此,需要支持 OpenGL ES2.0 的 GPU。之前已经有基于 0.9 版本的开发教程,但是已经不适用于 1.0 及以后的版本。这也是基于 2.0 版本,重新编写开发教程的原因。 4 第二章. 开发环境配置 1. 系统要求 1) 支持的操作系统: A. Windows XP(32 位)、Vista(32/64 位)、Windows 7(32/64 位) B. Mac OS X 10.5.8 以上版本(仅支持 x86) C. Linux(Ubuntu、Lucid Lynx)  GNC C Library 2.7 以上  Ubuntu Linux 8.04 以上  64 位系统需要运行 32 位应用程序的能力 2) Eclipse IDE: A. Eclipse 3.6.2(Helios)以上 B. Eclipse JDT 插件(已在大多数 Eclipse 包中安装) C. Eclipse 有用于多种开发目的的软件包,建议使用如下软件包:  Eclipse IDE for Java EE Developers;  Eclipse IDE for Java Developers;  Eclipse Classic D. JDK6 及以上版本(需要 JDK,仅仅有 JRE 是不够的) E. 在安装 Esri 提供的开发插件之前,需要安装 ADT 插件 3) 支持的 Android SDK SDK 平台 Android 2.2,API 8 及以上 4) 支持的 ArcGIS for Server 版本 ArcGIS for Android 支持 ArcGIS Server 9.3.1 及以上:  ArcGIS Server for Java Platform  ArcGIS Server for .NET Platform 5) OpenGL ES 2.0 ArcGIS Runtime SDK for Android 使用 OpenGL ES 2.0。如果用模拟器开发,需要使用 Android 4.0.3 以上版 本的模拟器(支持 GPU),具体在后面介绍。 6) 准备工作 5 A. 操作系统:Windows 7 旗舰版 B. JDK:JDK7(安装及配置过程不再赘述) http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u3-download-1501626.html C. Eclipse IDE:Eclipse 3.7.2(Indigo)for Java EE Developers http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr2 D. Android SDK installer:installer_r20.0.3-window.exe 官方地址:http://dl.google.com/android/installer_r20.0.3-windows.exe CSDN 下载地址:http://download.csdn.net/detail/arcgis_mobile/4684836 2. Android 配置 1) 下载 Android SDK for Windows 安装包,下载地址见上面,这里使用 installer_r20.0.3-window.exe; 2) 运行 installer_r20.0.3-window.exe,完成安装,安装结束后默认会打开 Android SDK Manager,如下图所示: 6 3) 选择 3.1 和 4.1.2(在使用模拟器进行开发时会用到)进行安装,默认情况下 Android SDK Platform-tools 和 Google USB Driver 会被同时安装。在 4.1.2 中,ARM EABI v7a System Image 必须勾选,这是一个核心镜像, 提供对 NDK 使用的支持。不安装该镜像,无法创建 AVD。 4) 接下来安装 Android Development Tools(ADT)插件。打开菜单 Help >> Install New Software,将 ADT 插件 地址添加到 Available Software Sites 列表,地址为:https://dl-ssl.google.com/android/eclipse,并命名为 ADT, 在 Available Software Sites 中选择 ADT,Eclipse 将会获取 ADT 的相关信息,如下图所示。当前版本为 20.0.3, 值得注意的是,该版本提供了 NDK Plugin,用于 JNI 方式开发。 除了在线安装还可以本地安装,先下载 ADT,官网地址:http://dl.google.com/android/ADT-20.0.3.zip, CSDN 下载地址:http://download.csdn.net/detail/arcgis_mobile/4684776 5) 选中 Android DDMS 和 Android Development Tools,其它可不选,完成安装,并重启 Eclipse。 6) Eclipse 重启后,打开菜单 Windows >> Preferences,会发现 Preferences 中已经有了 Android 相关的内容。 只需指定 SDK 安装路径即可,如下图所示: 7 3. ArcGIS Runtime for Android 配置 1) 首先下载插件,官网地址:http://resources.arcgis.com/en/communities/runtime-android/,或者 ArcGIS_Mobile 博客下载地址:http://download.csdn.net/detail/arcgis_mobile/4459474。 2) 打开菜单 Help >> Install New Software,点击 Add 按钮,在弹出窗口中点击 Archive 按钮,从本地安装已经 下载的 ArcGIS Android 插件压缩包,完成安装即可。如下图所示: 8 3) 安装完成并重启 Eclipse 后,打开菜单 File >> New >> Project…,可以看到在 New Project 中,已经有 ArcGIS for Android 可供选择,说明 ArcGIS for Android 已经安装成功,如下图所示: 4. 使用 Android 模拟器开发 在使用 Android 模拟器进行开发时,由于对 OpenGL ES 2.0 的要求,需要模拟器支持 GPU。Android 4.0.3 及以上版本的模拟器提供对 GPU 的支持。 此处使用 Android 4.1.2 版本的模拟器。在 Eclipse 中打开 Android Virtual Device Manager,新建一 个模拟器。Android(Target)版本选择 4.1.2,CPU 会自动选择 2.3 中安装的 ARM(armeabi-v7a)。需要注 意的是在 Hardware 参数中,要添加 GPU emulation,并且设置开启状态(添加 GPU 的详细步骤请参见博文“教 你 5 步学会 ArcGIS Android 模拟器调试”),如下图所示: 9 运行模拟器,在模拟器上运行 HelloWorld,运行结果如下图所示: 目前在基于 ARM 的模拟器上开发 ArcGIS Android 程序,效率不高。Android 在 4.0.3 以后,支持 Intel x86 cpu,Intel 也发布了 Intel x86 模拟器的加速器。笔者经过测试发现,加速器对 Android 模拟器的加速效果 明显。但是 ArcGIS Android SDK 目前还不支持 Intel x86,所以还无法享受 Intel 加速器带来的体验上的提 升。如何安装和使用 Intel 加速器此处也就不再介绍。 10 5. 使用 Android 设备开发 ArcGIS Runtime SDK for Android 对 Android 设备有些基本要求:Android 版本 2.2 及以上,支持 OpenGL ES2.0。除此之外,与一般 Android 项目在真机上开发没有区别。下面演示一下如何用 Android 设备进行开发。 首先,新建 ArcGIS Android 项目,简单起见,直接使用 ArcGIS Android Eclipse 插件中自带的例子程 序。新建项目,导航到 ArcGIS Samples for Android,如下图所示: 点击 Next,从例子程序中选择最简单的 HelloWorld,如下图所示。点击 Finish,HelloWorld 示例程序 创建成功。由于插件自带示例程序基于 Android 2.2,所以对项目使用的 Androd SDK 版本进行重新设置。这 里,设置成 Android 3.1; 11 将 Android 设备通过数据线与电脑 USB 接口连接,初次连接,电脑会自动安装驱动程序。在 Android“系 统设置”的“开发”选项中,选中“USB 调试”。运行 HelloWorld,程序会上传到已连接好的 Android 设备, 并自动安装、运行。运行效果如下图所示: 12 第三章. 创建第一个 HelloWorld Map 通过上面章节,已经了解如何配置一个 ArcGIS Runtime for Android 开发环境,下面将介绍如何使用 Eclipse 创建一个 ArcGIS 移动项目 Hello World Map,并且分析项目的相关结构。 1. 创建项目 打开已经配置好的 Eclipse 工具,在的工作区右键创建 ArcGIS 移动项目,如图: 右键工作区NewOther…,点击 Other…选项后在弹出的窗体中选中 ArcGIS Project for Android 选 项,如图所示: 13 在上面的窗体中点击 Next 按钮跳转到创建项目界面如图: 在 Project Name 输入框中输入要创建的项目名称,如:HelloWorldMap;输入完项目名称点击 Next 按钮 跳转到应用设置界面如图: 14 需要修改 Package Name 输入框的包结构名,如:com.esri.demo;修改完点击 Finish 按钮,此时的项目 已经创建完毕了。 2. 项目结构 15 根据上图,可以发现 ArcGIS 项目与普通的 Android 项目基本相同,下面来整体介绍一下 ArcGIS 的项目 结构:  这个不用多说,大家都应该知道,这是存放 java 源码的目录,目录里的文件是根据 package 结构管理的。  /gen 也是一个源代码目录,但里面的 Java 文件是由 android 平台自动生成的,而这个目录下的 R.java 类文件是由 Android Framework 负责管理的,不需手动操作,在 gen 中你可能会发现有一个 BuildConfig.java 文件,在早先的版本中是没有这个文件,它是 Android ADT 更新后来添加的,它的作用是检查你的代码,不 断运行调试。  这里是项目中所需要的 java 函数库,比普通的 Android 项目多了 ArcGIS 的函数库。  可以将所需的文件放在 assets 目录中进行存储,方便访问。/assets 中的资源文件与/res 中的功能很相 似,都是存放资源文件目录,但/assets 中的资源不会像/res 中的资源那样为每个资源文件生成 ID 标识。  对于/bin 并不陌生,这个目录是存放编译后生成的应用程序,如:HelloWorldMap.apk 就是编译生成的 应用程序安装文件。 16  /libs 目录下存放的是一些项目所需的动态链接库,对于 ArcGIS 项目中它默认存放了两个 GIS 所需的动 态链接库,当然也可以添加一些所需的其他动态链接库。  /res 目录存放了所需的大部分的资源,默认目录下有三类资源:drawable 目录主要存放一些图片、layout 目录主要放一些布局文件、values 目录主要存放一些项目中所需的参数值文件;当然除了这些还有一些其他 分类,如 anim 和 xml 目录等等,在此不再一一介绍。  这个文件应该不会陌生,这个 xml 文件是项目的一个系统配置文件,它包含了 activity(行为)、view (视图)、service(服务)之类的信息,以及运行这个 android 应用程序需要的用户权限列表,同时也详细 描述了 android 应用的项目结构。 3. 编码实现 介绍完 ArcGIS 的项目结构,来分析一下代码区,看看如何才可以让正常显示地图。 打开 HelloWorldMapActivity.java 文件,简单修改一下代码,代码如下: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMapView = new MapView(this);//实例化MapView对象 mMapView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); ArcGISTiledMapServiceLayer tileLayer = new ArcGISTiledMapServiceLayer("http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");//实例化图层 mMapView.addLayer(tileLayer);//添加图层到地图窗口中 setContentView(mMapView); 17 } 通过上面代码可以了解到,要想显示地图,首先必须创建一个 MapView 对象,然后创建一个 Layer 图层 对象,并将其添加到 Mapview 中进行显示。在本示例中添加的一个 ArcGISTiledMapServiceLayer 图层,显示 的效果,如下图所示: 18 第四章. 地图、图层及空间参考 1. MapView 地图组件 MapView 是 ArcGIS Runtime SDK for Android 的核心组件,通过 MapView 可以呈现地图服务的数据,并 且在 MapView 中定义了丰富的属性、方法和事件,用户通过 MapView 可以操作设备的触摸屏,默认 MapView 可以响应用户的各类手势的操作,GIS 的开发中,什么时候都少不了地图操作。MapView 是 Android中 ViewGroup 的子类,也是 ArcGIS Runtime SDK for Android 中的地图容器,与很多 ArcGIS API 中的 Map、MapControl 类作用是一样的。 1.1 MapView 功能介绍 MapView 的强大不仅仅是因为它是呈现地图数据的容器,MapView 为提供丰富的功能,下面来分析 MapView 为提供哪些功能。 首先,MapView 具有呈现地图能力,MapView 可以添加一个或多个图层,图层又分很多种,如:切片图层、 动态图层、本地图层等等;图层只有添加到 MapView 容器中才能进行显示。 其次,通过 MapView 可以设置地图的显示范围、是否允许被旋转、地图背景、地图的最大/最小分辨率及 其指定当前显示的分辨率/比例尺。 最后,MapView 提供了丰富的手势监听接口,通过这些监听器,可以监听各种手势动作,如点击、双击、 移动或长按等操作。 1.2 MapView 添加方式 有两种方式可以将 MapView 添加到应用当中:一个是 XML 方式,另一个是硬编码方式;一般多采用 XML 方式,方便调整布局及其属性相关设置。  XML 方式: 19  硬编码方式: MapView map = new MapView(this); map.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); tileLayer = new ArcGISTiledMapServiceLayer("http://services.arcgisonline.com/ArcGIS/rest/services/World_Street _Map/MapServer"); map.addLayer(tileLayer); setContentView(map ); 1.3 地图缩放、旋转和坐标转换 地图缩放,是地图中最基本的功能,MapView 提供了多种地图缩放的方式,如代码所示: mMapView.zoomin(); mMapView.zoomout(); mMapView.zoomToResolution(centerPt, res); mMapView.zoomToScale(centerPt, scale); 对于上面几种缩放方式,前两种主要功能是逐级缩放,调用一次 zoomin()方法地图将放大一级,调用一 次 zoomout()方法地图将缩小一级。 后两种缩放是按照不同的分辨率或比例尺进行的,调用 zoomToResolution(centerPt, res)方法进行缩放 时需要传入两个参数,第一参数 centerPt 为要按照哪个中心点进行缩放,因此需要传入一个 Point 对象才行, 第二个参数为要缩放到的分辨率;zoomToScale(centerPt, scale)和 zoomToResolution(centerPt, res)很类 似,两个方法第一个参数是相同的,而第二个参数不再是分辨率,而是传入地图的比例尺。 这里的分辨率或比例尺值与发布的服务密切相关,发布的地图服务如果生成了缓存切片,则在服务目录 中可以看到不同级别对应的比例尺和分辨率,如图: 20 服务地址:http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer MapView 还可以设置地图的显示范围、比例尺、分辨率、旋转角度和地图背景色,如: map = (MapView)findViewById(R.id.map); …… Envelope env = new Envelope(12957628.58241, 4864247.2803126, 12958114.4225065, 4864490.20036087);//范围 map. setExtent(env)//设置地图显示范围 map. setScale(295828763);//当前显示的比例尺 map. setResolution(9783.93962049996);//设置当前显示的分辨率 //上面三个方法都可以改变地图的显示范围,在代码中是不会同时使用的 map.setMapBackground(0xffffffff, Color.TRANSPARENT, 0, 0);//设置地图背景 map.setAllowRotationByPinch(true); //是否允许使用Pinch方式旋转地图 map.setRotationAngle(15.0); //初始化时将地图旋转15度,参数为正时按逆时针方向旋转。 除了上面的功能,MapView 还有一主要的功能:“坐标转换”,这里所说的坐标转换是指,把屏幕坐标转 换成空间坐标或将空间坐标转换成屏幕坐标,示例代码如下: //给地图添加一个点击事件监听 21 map.setOnSingleTapListener(new OnSingleTapListener() { public void onSingleTap(float x, float y) { // TODO Auto-generated method stub Point pt = map.toMapPoint(x,y);//屏幕坐标转换成空间坐标 Point screenPoint = map. toScreenPoint(pt);//转换成屏幕坐标对象 } }); 更多关于地图控件的更多操作说明,可参考博文“ArcGIS for Android 地图控件的 5 大常见操作”,地 址:http://blog.csdn.net/arcgis_mobile/article/details/7801467。 1.4 地图监听器 移动端手势的监听是一个重要的环节。地图的手势操作由 MapView 来管理,主要有以下几种监听:  地图单击监听:OnSingleTapListener  平移监听:OnPanListener  长按监听:OnLongPressListener  缩放监听:OnZoomListener  状态监听:OnStatusChangedListener  pinch 监听:OnPinchListener 有了这些监听用户就可以与地图进行多种交互,详细的监听用法请参看第五章“地图事件”。 到此,所有关于 MapView 的介绍告一段落,下面进入 Layer 世界。 2. 地图图层(Layer) 在 GIS 中图层是很重要的概念,图层是空间数据的载体,通过它可将各种类型的地图数据进行加载显示, 但图层只有添加到 MapView 对象中才能使用。在 ArcGIS Runtime for Android 中有许多种图层,不同图层有 不同的作用,下图是图层的继承关系图: 22 2.1 ArcGISTiledMapServiceLayer 在 ArcGIS for Server 中可以发布多种地图服务,移动端需要有不同的图层来对应这些服务。 ArcGISTiledMapServiceLayer 图层对应 ArcGIS for Server 服务中的切片服务,于切片都是事先做好的, ArcGISTiledMapServiceLayer 不能对图层中的数据进行更改,除非更新服务缓存,在 arcgis for android 中,也不允许对此类型的数据查询,通常用做底图使用。同时,因为加载的是缓存切片,这个类型的图层是 arcgis for android 中相应请求最快的图层之一,它采用多个线程,通常是每个图片使用一个线程来处理请 求和绘制图片,并且异步处理。用法如下: MapView mv = new MapView(this); mv.addLayer(new ArcGISTiledMapServiceLayer( "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer ")); setContentView(mv); 2.2 ArcGISDynamicMapServiceLayer ArcGISDynamicMapServiceLayer 图层对应 ArcGIS for Server 服务中的动态服务,动态地图服务的地图 数据是按照移动设备范围读取的,用法与 ArcGISTiledMapServiceLayer 图层相同。 ArcGISDynamicMapServiceLayer 图层通常包含多个图层,这些图层由 server 根据请求来渲染并以 raster image 形式返回,并且返回的 raster 并不包含 feature 的额外信息。它的功能特点是更新非常方便,并能及 时呈现给用户,同时,图层的可视性和空间参考可以改变,可以给图层添加单独的 layer definition,ArcGIS Server 为每个 image 动态投影。而地图的空间参考是由第一个加载的图层决定。 23 它的性能特点:它的渲染时间取决于请求数据的数量和复杂度,因此一般都比 tiled map server 要慢, 因此,它适合数据经常发生改变、或者需要针对不同的用户呈现不同的数据,且要素信息(如 attributes, geometry,symbol 等)不需要的情况。 示例代码如下: MapView mv = new MapView(this); mv.addLayer(new ArcGISDynamicMapServiceLayer( "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics /ESRI_Population_World/MapServer")); setContentView(mv); 2.3 ArcGISImageServiceLayer ArcGISImageServiceLayer 图层对应 ArcGIS for Server 服务中的影像服务,调用影像服务也非常简单, 同调用上述服务一样,示例代码如下: MapView mv = new MapView(this); mv.addLayer(new ArcGISImageServiceLayer( "http://myserver/arcgis/rest/services/MyImage/ImageServer",null)); setContentView(mv); 2.4 ArcGISFeatureLayer ArcGISFeatureLayer 图层对应 ArcGIS for Server 服务中的 Feature Service,该图层包含了要素最丰 富的信息,因此与其它图层类型相比具有最丰富的功能,其中的每个要素都能被查询,和通过空间查询或者 SQL 语句过滤,它继承自 GraphicsLayer,因此也具有该图层的所有操作。 该图层可以是空间图层,也可以是非空间的表,它包含了很多要素的信息,每个要素都单独渲染,从 ArcGIS Server Feature Service 或者 map service(此种 feature layer 不能编辑)中请求要素,并返回 JSON 格式 的数据并绘制。虽然需要一定的响应时间,如 ArcGIS Server 处理请求的时间,请求返回的时间,渲染速度 等,但仍然值得你使用它完成各种丰富的功能。 只有 Feature Service 才可以具备在线数据编辑功能,因此,如果想要对某个数据进行在线编辑或同步, 需要将其发布成 Feature Service,并在移动端新建一个 ArcGISFeatureLayer 图层以加载该服务。该图层有 一些设定,这些设定能影响图层的性能,包括请求时间,返回大小、处理和响应时间等(设置需要在图层 initialized 完成之后进行)。 24 Out fields:可以通过 outFields()方法来限制返回的属性字段的数量,可以减少网络传输和响应处理的 时间; Max Allowable offset:使用 Max Allowable offset()方法可以限制要素返回的顶点数量,以地图单 位设置的数值将用来在 server 返回要素之前简化要素的顶点,当你正在编辑要素时不应该使用此方法,可能 会导致顶点丢失和 topo 关系的破坏。 ArcGISFeatureLayer 在调用时可以设置 3 种模式(mode),不同模式返回数据的方式和执行的效率不同: Snapshot mode:快照模式能从 server 上快速取回要素,能减少响应时间,但如果图层包含大量、复杂的要素时,可 能会导致设备停止响应,因为有大量的要素需要绘制,也会导致 arcgis server 达到它返回要素数量的上线。Arcgis server 9.3.1 的默认限制是 500,10.0 是 1000,当然,这个数据可以在 server 端进行配置。建议小数据量的 dataset 才使用 snapshot mode。 On demand mode:On demand mode 需要在客户端和服务器之间传递更多的请求,适合展示变化的数据,该 mode 适 合包含复杂要素的大数据量的 dataset,因为它只请求和返回需要的要素,不过,为图层设置比例尺限制仍然是有必要的。 Selection mode:该模式下,一开始并不向服务器请求任何要素,只有当选择集出现时,要素才被加载,这种 mode 适合于不需要将所有要素展示在客户端,而只是强调一些特殊的要素,如,有一个 road 图层,使用了 feature layer 不支 持的自定义的符号,但是又需要对该图层进行 web edit,此时,你可以使用一个 dynamic map service layer 和一个 feature layer in selection mode,将需要编辑的 road 选择出来,以简单的符号绘制并存储在 feature layer 以实现编辑,当编辑完成 后,清除选择并刷新 dynamic map service 来查看更新。 示例用法如下: String url = "https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/TrailConditions/FeatureS erver/0"; MapView mv = new MapView(this); mv.addLayer(new ArcGISFeatureLayer(url,MODE.SNAPSHOT));//按照快照方式 setContentView(mv); 2.5 ArcGISLocalTiledLayer ArcGISLocalTiledLayer 是用来添加离线数据包的图层,该图层目前支持两种格式的离线数据:一个是紧 凑型的缓存切片,另一个是打包的 tpk 格式的数据,对于这两种数据的制作方法可以参照附录“如何制作离 线数据附录”章节,图层用法如下: MapView mv = new MapView(this); ArcGISLocalTiledLayer local = new ArcGISLocalTiledLayer("file:///mnt/sdcard//Layers");//离线图层,将缓存的地址作为参数传入 mv.addLayer(local); setContentView(mv); 25 2.6 GraphicsLayer GraphicsLayer 是 ArcGIS Runtime for Android 中比较重要的图层类型,也是使用最为频繁的一个。 GraphicsLayer 可以包含一个或多个 Graphic 对象,查询的返回结果和动态标绘的 Graphic 数据都要通过它呈 现。建议在 MapView 中添加图层时不要第一个添加该类型的图层,因为 MapView 加载图层时先要初始化一些 地图参数,而该图层不具备这些参数,其具体用法如下: MapView mv = new MapView(this); mv.addLayer(new GraphicsLayer());//可以看到,创建GraphicsLayer无需任何参数 setContentView(mv); 除了可以呈现 Graphic 对象外,它还具备了一些其他有用的功能,如要素更新与要素获取等等,由类 GraphicsLayer 处理,GraphicsLayer 是由应用程序来定义的图层,专门用来绘制有空间参考的要素,并不适 合绘制 non-geographical 要素,如指北针或 copyright text。可以用屏幕坐标来查询图层中的要素并且使用 getGraphics()方法返回要素,并且支持设置图层比例尺。 不推荐在 graphics layer 中存放太多的要素,但是,它有着不错的性能,并且是 feature layer class 的基类,如果必须要处理大量的要素,建议使用 feature collection 来存储在 feature layer 中。  要素更新 这个功能在开发经常用到,如实时更新坐标位置或者进行标绘。以标绘为例,在移动设备上用到 GraphicsLayer 的 updateGraphic()方法进行实时更新,这时地图上绘制的几何要素将被不断绘制出来,如: public boolean onDragPointerMove(MotionEvent from, MotionEvent to) { if (startPoint == null) {//判断是否已经存在第一个点 graphicsLayer.removeAll(); poly = new Polyline(); startPoint = mapView.toMapPoint(from.getX(), from.getY()); poly.startPath((float) startPoint.getX(), (float) startPoint.getY()); uid = graphicsLayer.addGraphic(new Graphic(poly,new SimpleLineSymbol(Color.BLUE,5))); } poly.lineTo((float) mapPt.getX(), (float) mapPt.getY());//增加线点 graphicsLayer. updateGraphic(uid,poly);//更新数据显示 return true; } 26  要素获取 ArcGIS Runtime for Android 中与其他 Web API 有所不同,其他 API 中 Graphic 对象是可以设置监听的, 而在 ArcGIS Runtime for Android 中 Graphic 不能添加任何监听,所以当在地图上点击一个 Graphic 对象时 需要其他方式间接的获取这个对象。可以通过 GraphicsLayer 的 getGraphicIDs(float x, float y, int tolerance)方法来获取要素,其中 x 和 y 是屏幕坐标,tolerance 是容差,通过这个方法可以间接的获取所需 的 Graphic 对象,如: public boolean onSingleTap(MotionEvent e) { Graphic graphic = new Graphic(mapView.toMapPoint(new Point(e.getX(), e.getY())),new SimpleMarkerSymbol(Color.RED,25,STYLE.CIRCLE)); return false; int[] getGraphicIDs(float x,float y, int tolerance) } 2.7 BingMapsLayer ArcGIS Runtime for Android中也可以添加 Bing 地图服务,首先必须注册账户并获取 Bing map 的 App ID, 有了这个 ID 就有了使用 Bing 地图的权限,具体的账户申请和操作步骤可以参照以下地址: 地址:https://www.bingmapsportal.com/ 详细说明:http://msdn.microsoft.com/en-us/library/ff428642.aspx 将申请的 ID 填入上面代码 appId 属性即可正常访问 Bing 地图服务。 3. SpatialReference 可以通过 MapView 或图层来获取空间参考对象,每一个地图服务都有对应的空间参考系,当做查询检索 或坐标投影转换时会经常用到该对象,用法如下: 27 double locy = loc.getLatitude();//纬度 double locx = loc.getLongitude();//经度 Point wgspoint = new Point(locx, locy); //将经纬度坐标转换成地图坐标系 Point mapPoint = (Point) GeometryEngine .project(wgspoint, SpatialReference.create(4326), map.getSpatialReference()); Unit mapUnit = map.getSpatialReference().getUnit(); double zoomWidth = Unit.convertUnits( SEARCH_RADIUS, Unit.create(LinearUnit.Code.MILE_US), mapUnit); Envelope zoomExtent = new Envelope(mapPoint,zoomWidth, zoomWidth); map.setExtent(zoomExtent); 28 第五章. 地图事件 ArcGIS Runtime sdk for Android 提供了丰富的事件监听器,本章将主要介绍经常使用的监听器,及通 过这些监听器可以实现哪些功能,下图中的监听器中只有 MapOnTouchListener 是类,其他皆为接口类型: 1. MapOnTouchListener MapOnTouchListener 是 MapView 最为重要的监听器之一,它实现了 OnTouchListener 和 MapGestureDetector.OnGestureListener 接口,对于地图的所有操作 MapOnTouchListener 都可以进行响应, 使用非常方便,在使用前只需扩展这个类并重写该类中的方法即可。用法如下 myListener = new MyTouchListener(this, mapView); mapView.setOnTouchListener(myListener); /* * MapView's touch listener */ class MyTouchListener extends MapOnTouchListener { public MyTouchListener(Context context, MapView view) { super(context, view); } public void setType(String geometryType) { this.type = geometryType; } public String getType() { return this.type; } public boolean onSingleTap(MotionEvent e) { return true; 29 } public boolean onDragPointerMove(MotionEvent from, MotionEvent to) { return super.onDragPointerMove(from, to); } @Override public boolean onDragPointerUp(MotionEvent from, MotionEvent to) { return super.onDragPointerUp(from, to); } } 通过上面代码的方式就可以监听到不同的手势操作,对于不同的手势操作将执行不同的方法,通过这些 方法可以添加所需的操作功能。如,当在地图上点击时弹出一个窗体,只需在 onSingleTap()方法中完成点的 获取、窗体的创建及其弹出操作即可。 2. OnLongPressListener OnLongPressListener 接口主要用于监听地图长按事件,用法如下: //为地图添加一个长按监听器 mapView.setOnLongClickListener(new View.OnLongClickListener() { //长按后自动执行的方法 public boolean onLongClick(View v) { // TODO Auto-generated method stub return false; } }); 3. OnPanListener OnPanListener 接口用于监听 MapView 的地图平移事件,用法如下: //为地图添加一个平移监听器 mapView.setOnPanListener(new OnPanListener() { public void prePointerUp(float fromx, float fromy, float tox, float toy) { } public void prePointerMove(float fromx, float fromy, float tox, float toy) { } public void postPointerUp(float fromx, float fromy, float tox, float toy) { } public void postPointerMove(float fromx, float fromy, float tox, float toy) { } }); 30 4. OnPinchListener OnPinchListener 接口也经常用到,用于对地图进行两指或多次操作时监听事件,比如可以通过该接口实 现两指夹/捏的地图缩放。用法如下: //为地图添加夹/捏监听器 mapView.setOnPinchListener(new OnPinchListener() { public void prePointersUp(float x1, float y1, float x2, float y2, double factor) { } public void prePointersMove(float x1, float y1, float x2, float y2, double factor) { } public void prePointersDown(float x1, float y1, float x2, float y2, double factor) { } public void postPointersUp(float x1, float y1, float x2, float y2, double factor) { } public void postPointersMove(float x1, float y1, float x2, float y2, double factor) { } public void postPointersDown(float x1, float y1, float x2, float y2, double factor) { } }); 5. OnSingleTapListener OnSingleTapListener 接口是对地图进行点击操作时的事件监听器,用法如下: //为地图添加单击事件监听 mapView.setOnSingleTapListener(new OnSingleTapListener() { //点击地图后自动执行的方法 public void onSingleTap(float x, float y) { // TODO Auto-generated method stub } }); 31 6. OnStatusChangedListener OnStatusChangedListener 接口用于监听 MapView 或 Layer 状态变化,用法如下: //添加状态监听器 mapView.setOnStatusChangedListener(new OnStatusChangedListener() { public void onStatusChanged(Object source, STATUS status) { if(status == STATUS.INITIALIZED){ }else if(status == STATUS.LAYER_LOADED){ }else if((status == STATUS.INITIALIZATION_FAILED)){ }else if((status == STATUS.LAYER_LOADING_FAILED)){ } } }); 从上面的代码可以清晰看到,对于 MapView 的状态变化主要有四种: 1) STATUS.INITIALIZED 初始化成功 2) STATUS.LAYER_LOADED 图层加载成功 3) STATUS.INITIALIZATION_FAILED 初始化失败 4) STATUS.LAYER_LOADING_FAILED 图层加载失败 7. OnZoomListener OnZoomListener 接口主要监听地图的缩放事件,用法如下: mapView.setOnZoomListener(new OnZoomListener() { //缩放之前自动调用的方法 public void preAction(float pivotX, float pivotY, double factor) { } //缩放之后自动调用的方法 public void postAction(float pivotX, float pivotY, double factor) { } }); 32 第六章. 空间要素可视化 此节主要介绍要素的可视化,不管以什么方式获取数据,将其正确的展现到地图中才更具意义。在 ArcGIS Runtime for Android 中空间要素一般都将添加到 GraphicsLayer 图层中进行展示,对于空间要素无非就那么 几种:点、线、面和文字类型等等,本节将主要介绍 Graphic、Geomtry 和 Symbol,展示效果如图: 1. Graphic Graphic 是承载空间几何要素的载体,Graphic 对象可以添加到 GraphicsLayer 图层中进行展示。 Graphic 主要有四部分组成:Geomtry、Symbol、Attributes(类型 Map)和 InfoTemplate, 通过这 4 个部分可以获取 Graphic 对象的 Geometry、符号、属性信息和模板信息,但查看 Graphic 的 API 文 档时会惊讶的发现,通过这个对象可以获取相应的属性信息,却没有相应的方法来修改这些属性。这是因为, Graphic 对象一经构造就不可修改,构造成功后会为没个 Graphic 生成唯一的 UID 以便调用。 33 要想修改 Graphic 的属性,也不是没有办法,通常使用 GraphicsLayer 的 updateGraphic()方法可以间接 的修改 Graphic 对象的属性,用法如下: public boolean onSingleTap(MotionEvent e) { if (type.length() > 1 && type.equalsIgnoreCase("POINT")) { //创建Graphic对象,添加几何结构,样式 Graphic graphic = new Graphic(mapView.toMapPoint(new Point(e.getX(), e .getY())),new SimpleMarkerSymbol(Color.RED,25,STYLE.CIRCLE)); graphicsLayer.addGraphic(graphic); //添加到图层中 return true; } return false; } 2. Geometry Geometry 表示一个空间要素对象,它定义了空间位置和几何形体关系。它是所有空间对象的基类,直接 子类有 Envelope, MultiPath, MultiPoint, Point, Segment。Geometry 的继承关系图如下: 2.1 Point Point 针对于空间要素的点对象,point 既可代表二维的点也可以是三维点对象,可以通过它自身的方法 获取 x 或 y 坐标。用法如下: Point point = new Point();//创建点对象 Point.setX(114);//设置x坐标 Point.setY(32);//设置y坐标 Graphic gp = new Graphic(point, new SimpleMarkerSymbol(Color.RED,25,STYLE.CIRCLE)); graphicsLayer.addGraphic(gp);//添加到图层中显示 Point 常用接口介绍: 34 序号 接口 说明 1 copyTo(Geometry dst) 复制自身并将其附给另一个几何对象 2 setXY(double x,double y) 设置点对象的 x 和 y 的坐标 3 equals(Object other) 判断两个点是否相同,当类型,属性,坐标相同时返回 true 4 getType() 返回几何对象的类型 5 getX()或 setX(double x) 获取或设置 x 坐标值 6 getY()或 setY(double y) 获取或设置 y 坐标值 2.2 MultiPoint MultiPoint 表示多点对象,MultiPoint 通常存储一系列的基础点,这些点按照一定的顺序存储并且每个 点都可以获取它的索引位置。可以通过每个点的索引位置对 MultiPoint 对象进行增、删或改操作,用法如下: Point point1 = new Point(114,32);//创建点对象 Point point2 = new Point(112,28);//创建点对象 MultiPoint multipoint = new MultiPoint(); multipoint.add(point1);//添加点 multipoint.add(point2);//添加点 multipoint.removePoint(1);//移除第二点 MultiPoint 常用接口介绍: 序号 接口 说明 1 add(double x, double y)或 add(Point point) 添加一个点到多点对象里 2 insertPoint(int beforePointIndex,Point pt) 在某个位置之前插入一个点对象 3 removePoint(int pointIndex) 移除某个位置上的点 4 setPoint(int index, Point pointSrc) 替换某个位置上的点 5 queryEnvelope(Envelope env) 计算多点覆盖的矩形范围,env 参数为计算后的结果 6 getType() 返回几何对象的类型 35 2.3 MultiPath MultiPath 是 polygons 和 polylines 的基类,MultiPath 与 MultiPoint 很类似,只不过 MultiPoint 存 储点数据集,而 MultiPath 存储一条或多条轨迹线,MultiPath 为提供了丰富操作接口。可以通过这些接口来 操作 MultiPath 对象里的任何轨迹上的点。用法如下: Point startPoint = new Point(114,28); MultiPath path = new MultiPath(); path.startPath(startPoint);//设置路径的初始位置 path.lineto(new Point(113,32));//给路径添加点 MultiPath 常用接口介绍: 序号 接口 说明 1 add(MultiPath src,boolean bReversePaths) 将 src 对象中的所有 paths 添加到自身中去,bReversePaths 为 true 时将 src 中的 paths 反向再添加 2 addPath(MultiPath src, int srcPathIndex, boolean bForward) 将 src 中 srcPathIndex 位置的 path 取出添加到自身中去,bForward 为 false 时 path 中的点将被反向 3 addSegment(Segment segment,boolean bStartNewPath) 将 segment 添加到自身中,bStartNewPath 为 true 时重新创建一个 path 并将 segment 添加。 4 insertPath(int pathIndex, MultiPath src, int srcPathIndex, boolean bForward) 与 addPath 功能很类似,多了一个添加的位置参数 5 insertPoint(int pathIndex, int beforePointIndex,Point pt) 在 path 的 beforePointIndex 节点之前添加一点 6 getPathCount() 统计本身 paths 的数量 7 startPath(double x,double y)或 startPath(Point point) 创建一个 path 并设置其起点坐标 8 lineTo(double x, double y)或 lineTo(Point endPoint) 在最后一个点上添加一个线的片段 36 2.4 Envelope Envelope 代表一个矩形要素,可以通过 Envelope 对象获取矩形窗口的中心点、矩形的上下四个点、宽和 高等等。用法如下: Envelope env = new Envelope(112,28,113,32);//创建矩形对象 map.setExtent(env);//设置地图显示范围 Point point= env.getCenter();//获取矩形框的中心点 Envelope 常用接口介绍: 序号 接口 说明 1 setCoords(double xmin,double ymin, double xmax,double ymax) 设置 Envelope 对象的最小 x,最小 y,最大 x,最大 y 值 2 getCenterX()或 getCenterY() 获取 Envelope 对象的中心点的 x,y 值 3 centerAt(Point c, double w,double h) 设置 Envelope 对象的中心点和宽高 4 getLowerLeft()、getUpperRight()、 getLowerRight()、getUpperLeft() 返回 Envelope 的对象的四个点的坐标点 5 contains(Point p) 返回 true 表示 p 点在这个 Envelope 对象之内 6 getXMin()、getYMin()、getXMax()、 getYMax()、setXMin(double x)、 setXMax(double x)、setYMin(double y)和 setYMax(double y) 设置或获取 Envelope 对象的最大或最小 x/y 值 2.5 Polygon Polygon 是 MultiPath 子类,表示多边形或多多边形,Polygon 里的所有 path 都是闭合的环。Polygon 对象也 是 ArcGIS for Android 开发中常用的对象,如标绘多边形或做空间查询时,Polygon 对象中至少存在三个点并且 不能同时在一条直线上。具体用法如下: Polygon poly = new Polygon();//创建多边形对象 poly.startPath(new Point(0,0));//添加初始点 poly.lineto(new Point(10,0)); 37 poly.lineto(new Point(10,10)); poly.lineto(new Point(0,0));//多边形是闭合的因此最后还要添加初始点的位置 Polygon 常用接口介绍: 序号 接口 说明 1 calculateRingArea2D(int ringIndex) 计算 ringIndex 对应 的 2D 面积 2 getType() 返回本身的对象的类型 3 queryEnvelope(Envelope env) 计算 line 线段所占据的矩形范围,env 参数为计算后的结果 2.6 Polyline Polyline 也是 MultiPath 子类,Polyline 表示一条或多条线路径,Polyline 跟 Polygon 用法基本相同,只不 过 Polyline 的最后一个点不必跟初始点坐标相同,即 Polyline 不必闭合。 Polyline 常用接口介绍: 序号 接口 说明 1 addSegment(Segment segment, boolean bStartNewPath) 为 Polyline 对象添加一节线段,当 bStartNewPath 为 true 时,创 建一个新的 path 并将 segment 添加到上面去。 2 getType() 返回本身的对象的类型 3 equals(Object other) 判断对象是否相等,如果几何类型、属性、坐标都相同返回 true 2.7 Line Line 与 Polyline 存在一定的关系,可以说 Line 是 Polyline 的组成部分,Line 表示两点之间生成的线段。 用法如下: Line line = new Line() line.setStart(new Point(113,32));//起始点 line.setEnd(new Point(114,28));//终止点 38 Polyline poly = new Polyline(); poly.addSegment(line,true);//添加线段到Polyline对象中 Line 常用接口介绍: 序号 接口 说明 1 calculateLength2D() 计算 line 对象的 2D 长度 2 getType() 返回本身的对象的类型 3 equals(Object other) 判断对象是否相等,如果几何类型、属性、坐标都相同返回 true 3. 符号渲染 3.1 Symbol Symbol 是对 Graphic 对象进行符号样式设置的接口,所有符号样式类都实现了 Symbol 接口,Symbol 接口关 系图如下: 39 3.1.1 PictureMarkerSymbol PictureMarkerSymbol 是对于点或多点要素的 Graphic 对象进行样式设置的类,PictureMarkerSymbol 主要通 过图片的 url 或 Drawable 等方式来设置图片符号,对于 PictureMarkerSymbol 还可以设置图片符号的旋转角度和 位置偏移,具体用法如下: //创建图片样式符合 PictureMarkerSymbol pic = new PictureMarkerSymbol(getResources().getDrawable(R.drawable.icon)); Point pt = new Point(113,32);//创建一个点对象 Graphic gp = new Graphic(pt,pic);设置样式 graphicsLayer.addGraphic(gp);添加到图层中 3.1.4 SimpleMarkerSymbol SimpleMarkerSymbol 也是针对点状要素的 Graphic 对象进行样式设置的类,SimpleMarkerSymbol 与 PictureMarkerSymbol 类很相似,只不过一个渲染成矢量点,另一个通过图片来替换该点。使用 SimpleMarkerSymbol 可以设置点的样式,如点的大小,颜色和类型,用法如下: Point point = new Point();//创建点对象 Point.setX(114);//设置x坐标 Point.setY(32);//设置y坐标 //设置点样式的颜色,大小和点类型 SimpleMarkerSymbol sms = new SimpleMarkerSymbol(Color.RED,25,STYLE.CIRCLE) Graphic gp = new Graphic(point,sms); graphicsLayer.addGraphic(gp);//添加到图层中显示 3.1.3 SimpleLineSymbol SimpleLineSymbol 是针对线状要素的 Graphic 对象进行样式设置的类,通过它可以设置线状要素的样式,包 括线型、线颜色、线宽和线的透明度等,具体用法如下: Polyline poly = new Polyline ();//创建多边形对象 poly.startPath(new Point(0,0));//添加初始点 poly.lineto(new Point(10,0)); poly.lineto(new Point(10,10)); SimpleLineSymbol sls = new SimpleLineSymbol(Color.RED,25, SimpleLineSymbol.SOLID);//线样式对象, 包括颜色、线宽和线型等参数 sfs.setAlpha(50);//设置透明度 Graphic gp = new Graphic(poly, sls); 40 graphicsLayer.addGraphic(gp);//添加到图层中 3.1.2 SimpleFillSymbol SimpleFillSymbol 是对于面状要素的 Graphic 对象进行样式设置的类,通过它设置面状要素的填充颜色和透 明度,另外也可以为面状要素添加边界的样式设置,SimpleFillSymbol 用法非常简单,如下: Polygon poly = new Polygon();//创建多边形对象 poly.startPath(new Point(0,0));//添加初始点 poly.lineto(new Point(10,0)); poly.lineto(new Point(10,10)); poly.lineto(new Point(0,0));//多边形是闭合的因此最后还要添加初始点的位置 SimpleFillSymbol sfs = new SimpleFillSymbol(Color.RED);//面样式对象 sfs.setAlpha(50);//设置透明度 Graphic gp = new Graphic(poly,sfs); graphicsLayer.addGraphic(gp);//添加到图层中 3.1.5 TextSymbol TextSymbol 也是针对点状要素的 Graphic 对象进行样式设置的类,它将点的位置替换成文字进行标绘显示, 通过 TextSymbol 可以设置文字的大小、颜色、内容和排列方式。标绘的文字排列方式有两种:横向排列和纵向排 列,默认横向居中显示。用法如下: Point point = new Point();//创建点对象 Point.setX(114);//设置x坐标 Point.setY(32);//设置y坐标 //设置点样式的颜色,大小和文本内容 TextSymbol ts = new TextSymbol (12,”点样式”,Color.RED); Graphic gp = new Graphic(point,ts); graphicsLayer.addGraphic(gp);//添加到图层中显示 3.2 Renderer Renderer 是一个接口类型,该接口主要用于 Graphic 对象的样式渲染,它目前有四个实现类,关系图如下所 示: 41 3.2.1 SimpleRenderer SimpleRenderer 是最简单的一个渲染类,通过这个渲染类可以把图层中某一类型的要素同时进行渲染,如想 将图层中的所有点同时渲染成相同的样式,用法如下: SimpleRenderer renderer = new SimpleRenderer(new SimpleMarkerSymbol(Color.RED,25,STYLE.CIRCLE)); graphicsLayer.setRenderer(renderer);//为图层设置渲染 3.2.2 ClassBreaksRenderer ClassBreaksRenderer 是 Renderer 接口的实现类,使用 ClassBreaksRenderer 可以将 GraphicsLayer 图层中 的某一类型的 Graphic 对象进行分段渲染,用法如下: ClassBreaksRenderer renderer = new ClassBreaksRenderer(); renderer.setMinValue(0.0);//设置最小值 renderer.setField("POP07_SQMI");//渲染依附的字段 ClassBreak cb1 = new ClassBreak();//定义第一段渲染范围和样式 cb1.setClassMaxValue(25); cb1.setSymbol(new SimpleFillSymbol(Color.argb(128, 56, 168, 0))); cb1.setLabel("First class"); ClassBreak cb2 = new ClassBreak();//定义第二段渲染范围和样式 cb2.setClassMaxValue(75); cb2.setSymbol(new SimpleFillSymbol(Color.argb(128, 139, 209, 0))); cb2.setLabel("Second class"); ClassBreak cb3 = new ClassBreak();//定义第三段渲染范围和样式 cb5.setClassMaxValue(Double.MAX_VALUE); cb5.setSymbol(new SimpleFillSymbol(Color.argb(128, 255, 0, 0))); renderer.addClassBreak(cb1); renderer.addClassBreak(cb2); 42 renderer.addClassBreak(cb3); graphicsLayer.setRenderer(renderer);//为图层设置渲染 通过上面的代码可以发现分段渲染很简单,只需简单几步: 1) 创建 ClassBreaksRenderer 对象 2) 设置渲染的字段和最小值 3) 创建多个分段渲染对象(ClassBreak),设置最大值和样式 4) 将分段渲染对象添加到 ClassBreaksRenderer 对象中 5) 为图层设置 Renderer 对象 3.2.3 UniqueValueRenderer UniqueValueRenderer 是唯一值渲染类,该渲染方式是对某一字段进行唯一值渲染,如一个面状图层,其中一 个字段是对该图层的数据分类,这时就可以对该分类字段进行唯一值渲染:类型为住宅楼的为黄色,工厂的为紫 色,商业区的为红的等等,也可以对多个字段进行联合唯一值渲染,最多联合三个字段进行渲染,用法如下: UniqueValueRenderer uvr = new UniqueValueRenderer(); uvr.setField("TYPE"); UniqueValue uv1 = new UniqueValue(); uv1.setValue(new String[]{"Residential"}); uv1. setSymbol(new SimpleFillSymbol(Color.argb(128, 255, 100, 0))); UniqueValue uv2 = new UniqueValue(); uv2.setValue(new String[]{"Industrial"}); uv2. setSymbol(new SimpleFillSymbol(Color.argb(128, 255, 200, 0))); UniqueValue uv3 = new UniqueValue(); uv3.setValue(new String[]{"Commercial"}); uv3. setSymbol(new SimpleFillSymbol(Color.argb(128, 255, 150, 0))); uvr.addUniqueValue(uv1); uvr.addUniqueValue(uv2); uvr.addUniqueValue(uv3); graphicsLayer.setRenderer(uvr);//为图层设置渲染 43 4. 信息窗口 ArcGIS Runtime SDK for Android 中信息窗口的展示主要有两种:Callout 和 PopupContainer,前者用于在 Mapview 中展示一个信息窗口,类似于 Web 端的 infowindow 窗体后者使用非常方便,无需自己创建布局, PopupContainer 会根据要素的属性信息自己创建布局。 4.1 Callout 1) 功能介绍 Callout 类似于 Web 端的 infowindow 窗体,即在地图上显示一个弹出窗体。Callout 对象在整个 MapView 中 是唯一的,在整个 MapView 中只能显示一个 Callout 对象。 Callout 对象无需自己创建,需要通过 MapView 对象的方法来获取 Callout 对象实例,对于 Callout 的使用主 要掌握以下两点即可: 2) Callout 的样式文件 对于 Callout 的外观样式,需要事先设置好一个样式文件,通过样式文件可以控制弹出窗体的状态,如可以 控制弹出窗体的背景颜色、背景透明度、框架颜色和锚点位置等等,样式文件如下所示: 3) Callout 的布局文件 44 可以将 Callout 窗体比喻成一个相框,而相框里的照片就相当于 Callout 中需要显示的内容, 相框是一定的, 而里面的照片可以随时更换,这就像 Callout 对象,Callout 唯一存在但里面的内容可以随时更换,更换照片的过 程,也就是更换 Callout 内容的过程。Callout 的内容其实就是一个简单的布局文件,可以根据自身喜好来定制不 同的布局内容和排列方式,如下所示: 效果图如下: 4) 示例 上面已经介绍如何通过样式文件来控制 Callout 窗体的外观以及如何设计一个 Callout 窗体的内容布局文件, 下面展示在代码如何使用 Callout 弹出框控件: . . . . . . callout = map.getCallout();//通过MapView获取Callout实例对象 callout.setStyle(R.xml.calloutstyle);//为Callout设置样式文件 content = (View) findViewById(R.layout.calloutlayout);//弹出窗口布局文件对象 45 map.setOnSingleTapListener(new OnSingleTapListener() { private static final long serialVersionUID = 1L; public void onSingleTap(float x, float y) { callout.hide(); int[] graphicIDs = graphicsLayer.getGraphicIDs(x, y, 25); if (graphicIDs != null && graphicIDs.length > 0) { //Graphic gr = graphics[0]; Graphic gr = graphicsLayer.getGraphic(graphicIDs[0]); updateContent((String) gr.getAttributeValue("Rating"), (String) gr.getAttributeValue("Title")); Point location = (Point) gr.getGeometry(); callout.setOffset(0, -15);//设置偏移量 callout.show(location, content);//设置弹出窗显示的内容 } } }); . . . . . . . callout.hide();//隐藏信息窗口 通过上面示例可以发现,使用 Callout 进行信息展示只需注意两个部分即可: Callout 的样式设置和内容布 局设计,这两部分直接影响信息展示的效果。 4.2 PopupContainer 1) 功能介绍 PopupContainer 是另一种信息展示窗口,它提供了一个基础的 UI 界面用于显示和编辑 Graphics对象的信息, 使用该信息窗口时无需关注它的布局,该类会自动、合理的布局要素的所有属性。在使用时,只需设置好 PopupContainer 所需的数据即可。 PopupContainer 保存并管理一个或者多个 PopupView 对象,每一个 PopupView 对象展示一个 Graphic 对象的 属性信息。可以把 PopupContainer 对象看做是一本书,书的每一页可看做是一个 PopupView 对象,展示的效果如 下图所示: 46 上图中的PopupContainer添加了多个PopupView对象(共 14个),每一个PopupView对象代表了一个Graphic。 信息的展示只是 PopupContainer 的功能之一,通过 PopupContainer 还可以实时编辑 Graphic 对象的属性信 息并管理其附件,进行编辑的前提是:图层必须是 ArcGISFeatureLayer 类型。PopupContainer 会根据不同的图层 类型自动判别要素是否可以进行编辑。上图展示的数据是从 MapServer 服务器上获取的,因此添加到 PopupContainer 后没有编辑工具栏,如果访问的数据是从 FeatureServer 服务器上获取的,添加到 PopupContainer 容器中,界面上会多出个编辑工具栏,展示的效果如下图所示: 对于 Popup,主要注意以下几个对象的使用即可:  PopupContainer,所有要显示要素的容器  PopupView,每个要素展示界面  PopupInfo,包含了用户是否可以编辑要素的相关信息,弹出信息中是否可以展示附件等等。 47  Graphic,弹出窗体中需要显示的属性字段以及属性值。  WebMap,加载的地图应是一个 WebMap 地图,因为显示哪些信息是在 Webmap 中设置的。 2) 示例 //该方法中graphics[]对象是通过查询获得的,popupInfo是通过图层提供的方法取得的 private void createPopupViews(Graphic[] graphics, PopupInfo popupInfo, final int id) { final ArrayList popupViewList = new ArrayList(); for (int i = 0; i < graphics.length; i++) { PopupView popupView = new PopupView(map.getContext(), popupInfo, graphics[i]); popupViewList.add(popupView); } // Add the PopupViews to PopupContainer and display the popups. if ( id != popupContainer.hashCode() ) { // Dismiss spinner if (progressDialog != null && progressDialog.isShowing() && count.intValue() == 0) progressDialog.dismiss(); return; } // Add PopupViews and set colors for the popup popupContainer.addPopupViews(popupViewList.toArray(new PopupView[0])); popupContainer.setPopupBackgroundColor(Color.WHITE); popupContainer.setPopupTextColor(Color.BLACK); popupContainer.setPopupSelectorColors(Color.BLACK, Color.WHITE, Color.RED, Color.GRAY); if (popupDialog == null) { // Dismiss spinner. if (progressDialog != null && progressDialog.isShowing()) progressDialog.dismiss(); // Create a dialog for the popups and display it. popupDialog = new PopupDialog(map.getContext(), popupContainer); popupDialog.show(); } } 48 第七章. 查询检索 查询检索在 ArcGIS Runtime for Android 中是不可或缺的一部分,本节将介绍两种常用的查询检索任务: IdentifyTask 和 QueryTask。IdentifyTask 用来识别图层中的要素的, QueryTask 用来查询图层要素。 1. IdentifyTask IdentifyTask 顾名思义即一个识别任务类,当通过手指点击地图时获取地图上的要素信息,当然在识别操作 前必须为 IdentifyTask 事先设置好一组参数信息,IdentifyTask 接受的输入参数必须是 IdentifyParameters 类 型的对象,在参数 IdentifyParameters 对象中可以设置相应的识别条件。 IdentifyTask 是针对于服务中的多个图层的识别,返回的结果是 IdentifyResult[]数组,并且该任务存在三 种模式:  ALL_LAYERS 该模式表示在识别时检索服务上的所有图层的要素。  VISIBLE_LAYERS 该模式表示在识别时只检索服务上的可见图层的要素。  TOP_MOST_LAYER 该模式表示在识别时只检索服务上最顶层的要素。 IdentifyParameters 常用接口介绍: 序 号 接口 说明 1 setDPI(int dpi) 设置 map 的分辨率值 2 setGeometry(Geometry geometry) 设置空间几何对象 3 setLayerMode(int layerMode) 设置模型,主要有三种模型: ALL_LAYERS、VISIBLE_LAYERS 和 TOP_MOST_LAYER 4 setLayers(int[] layers) 设置识别的图层数组 49 5 setMapExtent(Envelope extent) 设置当前地图的范围 6 setMapHeight(int height) 设置地图的高 7 setMapWidth(int width) 设置地图的宽 8 setReturnGeometry(boolean returnGeometry) 指定是否返回几何对象 9 setSpatialReference(SpatialReference spatialReference) 设置空间参考 10 setTolerance(int tolerance) 设置识别的容差值 IdentifyTask 的具体用法示例代码如下: params = new IdentifyParameters();//识别任务所需参数对象 params.setTolerance(20);//设置容差 params.setDPI(98);//设置地图的DPI params.setLayers(new int[]{4});//设置要识别的图层数组 params.setLayerMode(IdentifyParameters.ALL_LAYERS);//设置识别模式 //为地图添加点击事件监听器 map.setOnSingleTapListener(new OnSingleTapListener() { private static final long serialVersionUID = 1L; public void onSingleTap(final float x, final float y) { if(!map.isLoaded()){ return; } //establish the identify parameters Point identifyPoint = map.toMapPoint(x, y); params.setGeometry(identifyPoint);//设置识别位置 params.setSpatialReference(map.getSpatialReference());//设置坐标系 params.setMapHeight(map.getHeight());//设置地图像素高 params.setMapWidth(map.getWidth());//设置地图像素宽 Envelope env = new Envelope(); map.getExtent().queryEnvelope(env); params.setMapExtent(env);//设置当前地图范围 MyIdentifyTask mTask = new MyIdentifyTask(identifyPoint); mTask.execute(params); } }); ……………………… private class MyIdentifyTask extends AsyncTask { 50 IdentifyTask mIdentifyTask; Point mAnchor; MyIdentifyTask(Point anchorPoint) { mAnchor = anchorPoint; } @Override protected IdentifyResult[] doInBackground(IdentifyParameters... params) { IdentifyResult[] mResult = null; if (params != null && params.length > 0) { IdentifyParameters mParams = params[0]; try { mResult = mIdentifyTask.execute(mParams);//执行识别任务 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return mResult; } @Override protected void onPreExecute() { mIdentifyTask = new IdentifyTask("http://services.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Average_Hous ehold_Size/MapServer");//指定识别的图层 } } 通过上面代码可以知道,在执行识别任务需要以下几个步骤: 1) 创建识别任务所需的参数对象 IdentifyParameters 2) 为参数对象设置识别条件 3) 定义 MyIdentifyTask 类并继承 AsyncTask 4) 在 MyIdentifyTask 的 doInBackground()方法中执 IdentifyTask 的 execute(); 注:在上面示例中,识别任务是在 AsyncTask 的子类中执行的,因为识别任务请求是一个不定时操作,为了不影响 UI 中的操作,因此使 用该类来异步执行识别任务。 51 2. QueryTask QueryTask 查询任务也是 ArcGIS for Android 开发过程中经常使用的一种查询。QueryTask 可以对图层进行 属性查询、空间查询以及属性与空间联合查询,在执行查询前需要构建 Query 参数对象,该参数主要包含了查询 的设置条件。QueryTask 只针对服务中的一个图层进行查询。 Query 常用接口介绍: 序 号 接口 说明 1 setGeometry(Geometry geometry) 设置空间几何对象 2 setInSpatialReference(SpatialReference inSR) 设置输入的空间参考 3 setObjectIds(int[] objectIds) 设置要查询要素的 ObjectID 数组 4 setOutFields(String[] outFields) 设置返回字段的数组 5 setOutSpatialReference(SpatialReference outSR) 设置输出的空间参考 6 setReturnGeometry(boolean returnGeometry) 设置是否返回几何对象 7 setReturnIdsOnly(boolean returnIdsOnly) 设置是否只返回 ObjiectID 字段 8 setSpatialRelationship(SpatialRelationship spatialRelationship) 设置查询的空间关系 9 setWhere(String where) 设置设置查询的条件 下面通过示例代码我来看一下 QueryTask 的使用方法: targetServerURL = "http://services.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Average_Household_Size/MapServe r"; String targetLayer = targetServerURL.concat("/3");//指定查询的服务图层 String[] queryParams = { targetLayer, "AVGHHSZ_CY>3.5" };//创建查询参数 AsyncQueryTask ayncQuery = new AsyncQueryTask(); ayncQuery.execute(queryParams); private class AsyncQueryTask extends AsyncTask { 52 protected FeatureSet doInBackground(String... queryParams) { if (queryParams == null || queryParams.length <= 1) return null; String url = queryParams[0]; Query query = new Query();//创建查询参数对象 String whereClause = queryParams[1]; SpatialReference sr = SpatialReference.create(102100); query.setGeometry(new Envelope(-20147112.9593773, 557305.257274575, -6569564.7196889, 11753184.6153385));//设置空间查询条件 query.setOutSpatialReference(sr);//设置输出坐标系 query.setReturnGeometry(true);//指定是否返回几何对象 query.setWhere(whereClause);//设置属性查询条件 QueryTask qTask = new QueryTask(url); FeatureSet fs = null; try { fs = qTask.execute(query);//执行查询任务 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return fs; } return fs; } } } 通过上面代码可以了解 QueryTask 使用流程,步骤如下: 1) 创建 Query 参数对象 2) 为参数对象设定查询条件 3) 通过 AsyncTask 的子类来执行查询任务 53 第八章. 几何计算(GeometryEngine) GeometryEngine 是几何操作的工具类,功能类似于 ArcGIS for Server 发布的 GeometryService 服务,主要 用来实现常见的移动端编辑操作,如缓冲、切割、并、交、差的计算、面积和长度测量、投影转换等,这个工具 类中定义了 n 多种有用的接口供: 序号 接口 说明 1 buffer(Geometry[] geometries, SpatialReference spatialReference, double[] distances, Unit unit, boolean toUnionResults) 为多个几何对象生成缓冲区,最后一个参 数确定生成的多个缓冲区是否融合成为一 个几何对象 2 buffer(Geometry geometry, SpatialReference spatialReference, double distance, Unit unit) 为某个几何对象生成缓冲区 3 clip(Geometry geometry, Envelope envelope, SpatialReference spatialReference) 用 envelope 对象来切割一个几何对象 4 contains(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 判断两个几何体是否为包含关系 5 crosses(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 判断两个几何体是否是交叉关系 6 difference(Geometry inputGeometry, Geometry substractor, SpatialReference spatialReference) 二个几何体交叉,返回第一个几何体的剩 余部分,也就是刨除与第二个几何体相交 而剩余的部分 7 distance(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 技术两个几何体直接的距离 8 equals(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 判断两个几何对象是否相等 9 geodesicLength(Geometry geometry, SpatialReference spatialReference, LinearUnit lengthUnit) 返回几何对象的测量长度 geometryToJson(SpatialReference spatialReference, Geometry geometry) 将几何对象转成 JSON 数据格式 getNearestVertex(Geometry geometry, Point inputPoint) 返回输入点距 geometry 对象最近的顶点 54 getNearestVertices(Geometry geometry, Point inputPoint, double searchRadius, int maxVertexCountToReturn) 输入点在指定半径范围内获取顶点,最后 参数确定顶点最多个数 intersect(Geometry inputGeometry, Geometry intersector, SpatialReference spatialReference) 返回两个几何对象交叉后共同部分 jsonToGeometry(org.codehaus.jackson.JsonParser json) 将 JSON 数据转成几何对象 project(double x, double y, SpatialReference sr) 将经纬度坐标转换成指定坐标系下的坐标 project(Geometry geometry, SpatialReference inputSR, SpatialReference outputSR) 将几何对象成一个坐标系下转换到另一个 坐标系下。 simplify(Geometry geometry, SpatialReference spatialReference) 简化几何对象的顶点 touches(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 判断两个几何对象是否存在接触关系 union(Geometry[] geometries, SpatialReference spatialReference) 将多个几何对象进行联合操作生成一个全 新的几何对象 within(Geometry geometry1, Geometry geometry2, SpatialReference spatialReference) 判断几何对象 1 是否在几何对象 2 的里面 GeometryEngine 用法代码示例: Geometry clipResult = GeometryEngine.clip(clipTarget,clipEnv,mapView.getSpatialReference); Graphic graphic = new Graphic(clipResult,new SimpleFillSymbol(Color.GREEN)); graphicsLayer.addGraphic(graphic); 该示例演示了通过 GeometryEngine 提供的接口 clip 将两个几何对象切断的操作,其中 clipTarget 对象为被 切割的几何对象,clipEnv 对象为用于切割的几何对象,返回的结果为切割后共同的部分。 55 第九章. 定位 Android 中自身提供了三种定位方式:GPS 定位,网络定位以及基于基站定位方式。ArcGIS Runtime SDK for Android 中提供的定位接口本质是 GPS 的定位方式,不过将 Android 的 GPS 定位方式进行了一次封装,使得在 MapView 使用时更加方便。 使用 MapView 可以获取一个 LocationService 定位服务,通过这个 LocationService 定位服务可以开启/关闭 GPS,还可以设置一些有用的属性,如:定位后是否将地图进行平移使定位点剧中显示;设置定位点显示的样式, 可以给该定位点设置一个自定义的符号样式;设置定位的精度范围等等。显示效果如下图所示: LocationService 定位服务的常用接口: 序 号 接口 说明 1 getLocation() 获取位置对象 2 getPoint() 获取当前定位的点对象 3 setAccuracyCircleOn(boolean accuracyCircleOn) 是否显示精度范围 4 setAllowNetworkLocation(boolean allowNetworkLocation) 是否允许网络定位 5 setAutoPan(boolean autoPan) 是否自动平移 6 setBearing(boolean bearing) 是否启动方位计算 7 setMaxAccuracyCircleSize(int maxSize) 设置精度范围 56 8 setSymbol(Symbol symbol) 设置定位的样式符号 9 start() 启动定位服务 10 stop() 关闭定位服务 示例如下: LocationService ls = map.getLocationService();//通过map对象获取定位服务 ls.setAutoPan(false);//设置不自动平移 ls.setLocationListener(new LocationListener() {//设置定位监听器 boolean locationChanged = false; //当坐标改变时触发该方法 public void onLocationChanged(Location loc) { if (!locationChanged) { locationChanged = true; double locy = loc.getLatitude(); double locx = loc.getLongitude(); Point wgspoint = new Point(locx, locy); Point mapPoint = (Point) GeometryEngine .project(wgspoint, SpatialReference.create(4326), map.getSpatialReference()); Unit mapUnit = map.getSpatialReference() .getUnit(); double zoomWidth = Unit.convertUnits( SEARCH_RADIUS, Unit.create(LinearUnit.Code.MILE_US), mapUnit); Envelope zoomExtent = new Envelope(mapPoint, zoomWidth, zoomWidth); map.setExtent(zoomExtent); } } public void onProviderDisabled(String arg0) { } public void onProviderEnabled(String arg0) { } public void onStatusChanged(String arg0, int arg1, Bundle arg2) { } }); ls.start(); 57 第十章. 在线编辑 在线编辑是 ArcGIS Runtime SDK for Android 中的很重要的一块功能,要想实现在线编辑功能,首先必须拥 有一个 Feature Service 服务,在此基础上实现手持端数据编辑。 在手持端,通过 ArcGISFeatureLayer 图层进行要素的增、删、改以及查询操作,还可以为每一个要素添加附 件,进行要素的附件管理,前提是发布的 Feature Service 服务支持附件的功能。 ArcGISFeatureLayer 图层的常用接口: 序号 接口 说明 1 addAttachment(int objectId, File file, CallbackListener callback) 为某个要素添加附件 2 applyEdits(Graphic[] adds, Graphic[] deletes, Graphic[] updates, CallbackListener callback) 添加、删除或更新要素 3 clear() 清理图层上的所有要素 4 clearSelection() 清理当前选择的要素 5 deleteAttachments(int objectId, int[] attachmentids, CallbackListener callback) 删除某个要素上的附件 6 getGeometryType() 得到图层的几何类型 7 hasAttachments() 判断图层是否支持附件管理 8 queryAttachmentInfos(int objectId, CallbackListener callback) 查询某个要素的要素 9 queryFeatures(Query query, CallbackListener callback) 通过条件查询要素 10 selectFeatures(Query query, ArcGISFeatureLayer.SELECTION_METHOD selectionMethod, CallbackListener callback) 通过条件选取要素 11 setSelectionSymbol(Symbol selectionSymbol) 设置选取的要素显示的符号样式 通过上面的接口可以知道,如果想对数据进行在线数据编辑其实很简单,只需把要操作的要素数组通过 ArcGISFeatureLayer 图层的 applyEdits()接口提交,即可实现编辑操作,使用 applyEdits()接口可以实现要素的 添加、删除以及要素的更新操作。示例如下: 58 Map attrs = oldGraphic.getAttributes();//从图层上获取的要素 attrs.put("OBJECTID", attrs .get("OBJECTID"));//更新要素需要 Objectid 这个字段 attrs.put(“NAME", “JACE"); //修改属性值 attrs.put(“AGE”, 11); Point pt= new Point(115,23);//要更新的点 Graphic newGraphic = new Graphic(pt , null, attrs, null);//重新创建 Graphic 对象 //更新 featureLayer.applyEdits(null, null, new Graphic[] { newGraphic }, createEditCallbackListener(updateMapLayer)); 通过上面简单的几句代码即可实现要素的更新。前面章节已经介绍了 ArcGISFeatureLayer 图层的使用,每一 个 ArcGISFeatureLayer 图层对应服务中的一个要素图层,并且该图层有三种获取数据的方式(ONDEMAND,SNAPSHOT, SELECTION),详细内容请参看第四章第 2 节的第 2.4 小节。 59 第十一章. 地理处理 地理处理适合 ArcGIS 的各类用户,无论你是初学者还是高级用户,地理处理都可能是你日常使用 ArcGIS 的 重要组成部分。地理处理的基本目的是提供用于执行分析和管理地理数据的工具和框架。地理处理所提供的建模 和分析功能使得 ArcGIS 成为一个完整的地理信息系统。 地理处理提供了大量成套工具,用于执行从简单的缓冲区和面叠加到复杂的回归分析和影像分类等各项 GIS 任务。也可以使用模型构建器或 Python 创建你自己的工具,并且通过 ArcGIS for Server 将这些工具发布成地 理处理服务供 Web 端使用。 在 ArcGIS Runtime SDK for Android 中也提供了相应的地理处理功能,使用 Geoprocessor 类可以调用地理 处理服务,在 Geoprocessor 类中提供了两个主要的操作方法:  execute,执行一个同步的 GP 操作。  submitJob,执行一个异步的 GP 操作。 执行 Geoprocessor 处理时,需要按照服务的需求传入相应的参数,在 ArcGIS Runtime SDK for Android 中 为 Geoprocessor 定义了多种参数类型,如下: GPParameter GPBoolean GPDataFile GPDate GPDouble GPFeatureRecordSetLayer GPLinearUnit GPLong GPMultiValue GPRasterData GPRasterDataLayer GPRecordSet GPString 60 使用 execute 和 submitJob 执行 GP 操作时,需要传入一组参数,参数类型必须是 GPParameter 或其子类。如 果使用 execute 接口,需要使用 AsyncTask 异步类或者多线程等方式来执行 GP 操作,这样避免 GP 操作影响 UI 线 程的操作。 下面的示例代码是官方提供的示例 ViewShed 中的一部分,该示例主要的功能是通过 GP 服务计算指定点和范 围内所能观察的视觉区域。 //创建GP参数 GPFeatureRecordSetLayer gpf = new GPFeatureRecordSetLayer("Input_Observation_Point"); gpf.setSpatialReference(map.getSpatialReference()); gpf.setGeometryType(Geometry.Type.POINT); // Add the point selected by the user Graphic f = new Graphic(mPoint,new SimpleMarkerSymbol(Color.RED,25,STYLE.DIAMOND)); gpf.addGraphic(f); // 第二个所需的参数 GPLinearUnit gpl = new GPLinearUnit("Viewshed_Distance"); gpl.setUnits("esriMeters"); gpl.setDistance(8046.72); // 添加参数 params = new ArrayList(); params.add(gpf); params.add(gpl); new ViewShedQuery().execute(params); class ViewShedQuery extends AsyncTask, Void, GPParameter[]> { GPParameter[] outParams = null; @Override protected void onPostExecute(GPParameter[] result) { if (result == null) return; for (int i = 0; i < result.length; i++) { if (result[i] instanceof GPFeatureRecordSetLayer) { GPFeatureRecordSetLayer fsl = (GPFeatureRecordSetLayer) result[i]; for (Graphic feature : fsl.getGraphics()) { Graphic g = new Graphic(feature.getGeometry(),new SimpleFillSymbol(Color.CYAN)); gLayer.addGraphic(g); } } } uiHandler.sendEmptyMessage(CLOSE_LOADING_WINDOW); } @Override 61 protected GPParameter[] doInBackground(ArrayList... params1) { gp = new Geoprocessor("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/ GPServer/Viewshed"); //创建GP对象 gp.setOutSR(map.getSpatialReference()); try { GPResultResource rr = gp.execute(params1[0]);//执行GP任务 outParams = rr.getOutputParameters(); } catch (Exception e) { e.printStackTrace(); } return outParams; } } 62 第十二章. Portal API 1. Portal API 概述 ArcGIS Online 是 Esri 建设的公有云 GIS 平台,同时也是一个大众化的制图平台,通过它,用户可以轻松的实现 业务数据的快速上图、分享和企业间的协作。ArcGIS Online 为用户提供了免费、高质量的、全球范围内的大量底 图和专题图数据,包括全球各种精度的 DEM、地图和影像,美国的人口密度图、地质图等。Esri 在全球的合作伙 伴,比如微软,美国地质调查局等等,也在此提供了很多高精度、优质的数据。 Portal for ArcGIS 则是一个私有云平台,允许用户将地图和数据等地理资源部署在企业局域网中,并通过一个 具有用户、用户组和分享能力的门户来提供服务。 ArcGIS Portal API 是一种 REST 风格的 API,开发者通过这些 API 可以访问 ArcGIS Portal(包括 ArcGIS Online 和 Portal for ArcGIS)上的信息,包括用户、用户组和用户制作的内容。为了在各种端中更方便的使用,ArcGIS Portal API 已经在已有的 API 中进行了集成,如 ArcGIS Web APIs,ArcGIS Runtime APIs,以及 Mobile Runtime APIs 中都提供了 相应的操作 Portal 的类和接口,用户使用这些 APIs 能构建 web、desktop、mobile 等类型的应用。 这里先明确几个概念,以助于大家理解: 1、Portal。 Esri 的私有云平台叫“Portal for ArcGIS”,在下面的内容中提到的这个 Portal 是“门户”的概念,并不专门指 “Portal for ArcGIS”。门户是进入某个资源的入口,比如,通过 ArcGIS.com 门户可以访问 ArcGIS Online 上的资源, Portal for ArcGIS 也有专门的综合门户网站,通常在安装好 Portal for ArcGIS 之后,通过输入 localhost/home 可以打 开该门户网站。如我本机的“Portal for ArcGIS”的综合门户网站页面如下: 63 2、组织(Organization)、群组(Groups)和用户(Users) 在 ArcGIS Online 和 Portal for ArcGIS 中,通常是为特定的群体而创建门户网站,这个特定的群体称为组织。在 ArcGIS Online 上,通过企业级订阅,就可以为企业创建一个可配置的、安全的门户网站,用来存储企业的空间数 据,这个企业就称为组织。 群组是将企业内部有相同业务关系和处理目标的人进行分组管理,并在不同组之间共享资源和成果,通常是 企业内的一个部门可以创建一个或多个群组。 用户是指企业和群组内的个体,是使用和创造资源的人。用户可以属于某个组织和群组,也可以不属于任何 组织和群组,不属于任何组织和群组的用户只具备浏览公共资源的权限。 3、Items(项目) Items 是指 Portal 中的各种类型的资源,如用户信息、群组信息、托管的服务、Web Map、Application,等等, 如我的 ArcGIS Online 个人账户中的 Items 包括(但不限于)地图/要素/影像服务、GP 工具包、移动应用程序包、 WebMap 等: 64 上述内容都可以称为 Items,它是门户中包含的资源的统称。目前,移动端能够获取的 items 主要有用户信息、 群组信息以及 Web Map。 刚才讲到,ArcGIS Portal API 已经集成在 Mobile Runtime APIs,那么在 ArcGIS for Android 的 API 中,可以看到 “Portal”及“Portal”开头的一系列类,如下图所示,就是使用这些类来访问 ArcGIS Portal(包括 ArcGIS Online 和 Portal for ArcGIS)上的资源。 *如何在 ArcGIS Online 发布服务见附录 65 2. 连接 Portal 获取门户资源的第一步是连接至 Portal。 API 中的 Portal 类是最主要的类,通过实例化 Portal 类的对象,并传递门户的 url,完成门户的连接。 连接有 2 种方式,匿名连接和口令连接,区别取决于 UserCredentials 参数,如果访问的是一个组织的门户且 允许用户匿名访问,而实例化 Portal 对象时又没有提供用户口令,那么将用匿名用户的身份连接该 Portal,否则, 就需要正确的用户名和密码才能成功登陆。 代码如下: //匿名方式连接 Portal String url = new String(http://arcgis.com); //定义门户的 url Portal.newInstance(url, null);//实例化 Portal 对象,url 作为参数传递 //口令方式连接 Portal UserCredentials credentials = new UserCredentials(); credentials.setUserAccount("user login", "password");//实例化 UserCredentials 对象, Portal.newInstance(portalUrl, credentials); //实例化 Portal 对象,并将门户 url 和口令作为参数传递 如果连接返回错误信息“STRINGErrorServerCertificateUntrusted”,尝试添加该 URL 到受信任的列表中。 3. 获取组织的信息 PortalInfo 对象包含了 Portal 中所有的信息,包括用户和组织信息,专题组名称和信息,组织门户的名称、缩 略图等信息。如果连接 Portal 时采用的是口令方式并且登录的用户是该组织中的一员,则以上所有信息都会返回 到 PortalInfo 对象中;反之,如果是以匿名方式访问(匿名用户没有权限看见组织未共享的资源),则只返回门户 的属性信息并存储在 PortalInfo 中。 PortalInfo 提供了许多封装好的、即拿即用的方法,可以用来获取 Portal 的组织信息,包括组织的名称、缩略 图,简介、组织的主页上呈现的专题图等,常用的方法如 getOrganizationName()、fetchOrganizationThumbnail()、 getOrganizationDescription()等。 获取组织的名称、缩略图、简介等的示例代码如下: private class OrgTask extends AsyncTask { @Override protected Void doInBackground(Void... params) { UserCredentials credentials = new UserCredentials(); credentials.setUserAccount(username, password); final Portal portal = new Portal(url, credentials); 66 try {//获取PortalInfo的内容 portalInfo = portal.fetchPortalInfo(); //获取组织的名称,使用portalInfo.getOrganizationName() if (portalInfo.getOrganizationName() != null) { //使用portalInfo. fetchOrganizationThumbnail()获取组织门户的缩略图 byte[] data = portalInfo.fetchOrganizationThumbnail(); ByteArrayInputStream bytes = new ByteArrayInputStream(data); final BitmapDrawable bmd = new BitmapDrawable(bytes); if (bmd != null) { OrganizationInfoActivity.this.runOnUiThread(new Runnable() { @Override public void run() { //使用portalInfo. getOrganizationDescription()获取组织的描述信息 descriptionTxtView.setText(portalInfo.getOrganizationDescription()); id.setText(portalInfo.getOrganizationId()); //使用portalInfo. getOrganizationName()获取组织的名称 orgNameTxtView.setText(portalInfo.getOrganizationName()); isSharedTxtView.setText(String.valueOf(portalInfo.isCanSharePublic())); Envelope e = new Envelope(); portalInfo.getDefaultExtent().getGeometry().queryEnvelope(e); extentTxtView.setText(e.getXMin() + " "+ e.getYMin() + " " + e.getXMax() + " "+ e.getYMax()); basemapURLTxtView.setText(portalInfo.getDefaultBaseMap().getTitle()); organizationThumbnail.setImageBitmap(bmd.getBitmap()); try { thumbnailNameTxtView.setText(portal.fetchPortalInfo().getOrganizationThumbnailFileName()); } catch (Exception e1) { e1.printStackTrace();} } }); } }// if } catch (Exception e1) { e1.printStackTrace();} return null;} 4. 获取 user、group 和 items 的信息 用户通过邀请加入某个组织,成为组织的成员后可以查看其它成员共享的资源,并可以将自己的资源共享给 组织内的其它成员。PortalUser 类就用来记录组织内一个注册的用户,通常在成功初始化 Portal 类之后就会返回 PortalUser,PortalUser 有以下三种状态:  Private:在搜索和邀请中隐藏用户; 67  Account:只有在同一个组织内的用户才能搜索用户、内容和组;  Public:用户能够被所有人搜索到。默认使用这种权限。 获取某个组织的用户如下: group.getUsers();//得到组里的用户 group.getAdmins();//得到组的管理员 portalUser.getPortalUser fetchContent();//获取某个注册用户的内容(items) Portal API 中也提供了 query 字符串用来查找组织的 feature group、items 等内容,通过 PortalQueryParams 类 构建查询参数,并执行 Portal 对象的 findGroupsWithQueryParams 和 findItemsWithQueryParams 来获取用户组和内 容。 //call the async task new MyTask.execute(); Private class MyTask extends AsyncTask{ protected void doInBackGround(Void… params) {//连接 portal Portal portal = new Portal(portalUrl, credentials); PortalInfo portalInfo = null; try{//获取 portal 的内容 portalInfo = portal.fetchPortalInfo(); }catch(Exception e){} //定义 query 字符串 List querys = portal.getPortalInfo().getFeaturedGroupsQueries(); for (String query : querys) { PortalQueryResultSet results = null; try {//通过 queryParms 查找 groups results = portal.findGroups(queryParams); } catch (Exception e3) {e3.printStackTrace();}} } return null; } //构建 queryparams 查询参数,查找专题组 PortalQueryParams queryParams = new PortalQueryParams(portal.getPortalInfo().getFeaturedItemsGroupQuery()); PortalQueryResultSet results = portal.findItems(new PortalQueryParams(portal.fetchPortalInfo().getFeaturedItemsGroupQuery())); for(PortalItem item:results.getResults()) { item.getTitle()); } //构建 queryparams 查询参数,查找主页里的专题内容组 68 PortalQueryParams queryParams = new PortalQueryParams(portal.getPortalInfo().getHomepageFeaturedContentGroupQuery()); PortalQueryResultSet results = portal.findGroups(new PortalQueryParams(homepage)); for(PortalGroup r:results.getResults()) { group.getTitle()); } 5. 搜索 Portal 同上所述,想要搜索 portal 里面的内容,需要使用不同的参数来构建 query 字符串。PortalQueryParams 类提 供了系列方法,用来查询感兴趣的内容,如查找特定的用户和组,group ID,查找包含指定关键字的内容,等等, 通过 PortalQueryParams 类构建查询参数,并执行 Portal 对象的 findGroupsWithQueryParams 和 findItemsWithQueryParams 来获取用户组和内容 查找特定组的内容的示例代码如下: PortalQueryParams queryParams = new PortalQueryParams(); //通过 groupId 在指定的组里查找内容,构建查询参数 queryParams.setQueryForItemsInGroup(groupId); //使用构建的查询参数在 portal 中查找内容 portal.findItems(queryParams, portalListener); 还可以构建自定义的查询语句,如以下示例是查询包含“San Francisco”关键字、类型为 layer package 的 items: String queryString = “ title:\"San Francisco\" AND type:\"layer package\" “ ; PortalQueryParams queryParams = new PortalQueryParams(queryString); 6. 使用 WebMap Web Map 是 ArcGIS 10.1 中新推出的概念,指通过 ArcGIS Online 在线制图功能制作的 web 地图。Web Map 并 不是单独的图层,而是存储于 ArcGIS Online 上的多个图层和服务的组合,Web Map 不仅包含各种图层,还包含图 层和地图的配置信息,如图层的透明度,图层名称,顺序,地图初始化范围等等。每个 Web Map 都有自己的 Uniform Resource Locator (URL),在 ArcGIS Online 中打开该 Web Map 时就能看到,如以下是其中某个 Web Map 的地址,可 以看到,地址中就包含了其 id 号: http://yangtzue.maps.arcgis.com/home/item.html?id=186f9b54665242ecb37d92b5e9b7931a 69 Web Map 的优点在于:它的修改可以在应用程序和 code 之外进行,并且多种属性,如图层初始化范围和比例 尺、弹出框中包含的字段和内容、图层的渲染风格,等等,都可以通过 ArcGIS Online 来进行编辑和配置,并且这 种配置不影响已有程序的正常运行。正是基于这一优点,Web Map 具备了成为移动跨平台解决方案的优秀方案的 潜力,可以将关键的服务、数据和功能通过 Web Map 来进行配置,并为多种客户端设计统一的对象模型,这样, 在多种平台的客户端下使用 Web Map 时,就会具备一致的用户体验,并且极大的减轻了跨平台开发的工作量。 Web Map 也是 Portal 的 items 中最重要的内容,Portal API 中也提供了专门的 WebMap 类来获取 Web Map,其 中,最关键的参数还是要获取到 WebMap 的 id。示例代码如下: public class MapActivity extends Activity { MapView map; String appId = "AssFrEsFVlvF7XSZ7MyIwFX0BZOkcUof2Qly0BtXtml70r1D7NiK8_4KGh5qIxf7"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get the position of the item in the itemlist String itemId = getIntent().getExtras().getString("itemid"); Log.i(TAG, "itemid = " + getIntent().getExtras().getString("itemid")); Log.i(TAG, "itemid = " + itemId); //创建一个webmap的实例,该webmap将在callback函数中被创建 WebMap.newInstance(itemId, FeaturedGroupListActivity.myPortal, new CallbackListener() { @Override public void onError(Throwable e) {e.printStackTrace();} @Override public void onCallback(final WebMap webmap) { // Add the mapview in the ui thread. MapActivity.this.runOnUiThread(new Runnable() { @Override public void run() { if (webmap != null){ map = new MapView(MapActivity.this, webmap, appId, null); map.setOnStatusChangedListener(new OnStatusChangedListener() { private static final long serialVersionUID = 1L; @Override public void onStatusChanged(Object source, STATUS status) { if(status.getValue() == EsriStatusException.INIT_FAILED_WEBMAP_UNSUPPORTED_LAYER) { Toast.makeText(MapActivity.this, 70 "Webmap failed to load", Toast.LENGTH_SHORT).show(); } } }); setContentView(map); } } }); …… 71 第十三章. 应用程序部署 1. 应用程序签名 经过一系列开发和调试过程,应用程序最终进入部署阶段,这时需要对应用程序进行签名。签名的主要作用 在于:  区分应用程序。众多开发人员完全有可能使用相同的类名和包名,容易引起混淆,签名之后就能区分相同或相似的应 用程序;  保证应用程序的安全。应用程序如果使用一个 key 进行了签名,那么使用另一个 key 签名的文件将无法安装和替换老 版本,可以防止已安装的应用被第三方恶意覆盖或替换;  签名也是开发者身份的一种标识,能够保证交易的有序进行。 有几个条说明有助于理解应用程序的签名:  所有的 Android 应用都必须有数字签名,Android 系统不会安装没有数字证书的应用,没有不存在数字签名的应用, 包括模拟器上运行的(Eclipse 会默认创建一个调试证书,所以在使用模拟器调试时并没有要求开发者对程序进行签名, 但实际上也是存在签名的)。  签名的数字证书不需要权威机构来认证,是开发者自己产生的数字证书,即所谓的自签名。  正式发布一个 Android 应用时,必须使用一个合适的私钥生成的数字证书来给程序签名,不能使用 ADT 插件或者 ANT 工具生成的调试证书来发布。  数字证书都是有有效期的,Android 只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中, 即使证书过期也不会影响程序的正常功能。 应用程序签名其实挺简单的,步骤如下: 1)打开 Eclipse->选择要签名的项目->右击->android tools->Export signed Application package,弹出如下窗口: 72 2)选中你要签名的项目,然后 next,因如果是第一次签名,还没有签名证书,选择 create new keystore,如 果已经创建过,就不用再创建了,直接选择已存在的证书。选择证书保存的位置,填入密码,然后 next: 3)在下一步的界面中,填写签证的信息,包括:别名,密码,有效期,姓名,组织,组织名称,所在城市, 所在省份,国家等,点击 next: 4)最后弹出一个窗口,选择你要保存 apk 包的位置: 73 5)点击 finish 之后,稍等片刻就生成了自签名的 app 安装包了: 2. 应用程序分发 使用 ArcGIS Runtime SDK for Android 开发的移动应用面向装载了 Android 操作系统的各种智能移动终端,常见 的如 Google 的 GPhone 系列、摩托罗拉的里程碑系列、三星的 Nexus 和 Galaxy 系列、HTC 的智能手机和平板电脑 等。在开发的最后阶段,应用程序在经过数字签名之后,打包成后缀为.apk 的安装文件,接下来就需要将这个应 用程序部署到多个客户端。 有人会说,android 的程序部署很简单,有 apk 再加上 android 的设备的越狱,直接将 apk 拷贝到设备上,运 行就可以了。但是如果开发的是面向大众用户,或者企业内部几百个用户的应用程序时,要求每个用户越狱拷贝 安装文件的方式明显不现实,此时,最好的办法就是将 app 向电子市场中发布,通过电子市场为用户提供统一的 应用程序下载入口。接下来,为大家介绍如何在名目繁多的电子市场中选择合适的市场来发布应用。 74 首先,分发 ArcGIS for Android 的应用程序,请关注以下的许可和授权信息: 使用 ArcGIS for Android 开发的应用程序,分发需要遵守 Esri 公司的许可分发协议,即,如果是非商业用途,则可以免 费分发,但需要在地图中打上 esri 的 logo;如果是商业用途,要求应用发布方具有 ArcGIS for Server 许可,详细信息请咨 询 Esri 中国公司(联系电话:010-57632288); Android 的应用分发有很多渠道,官方的渠道有谷歌的“Google Play”,它与苹果的“App Store”性质完全一 致,所有的 android 应用程序都可以上传到 Google Play 中供用户下载,同时,它也具备类似 app store 的商业模式, 开发者可以设定应用程序的费用。但此种方式需要注册成为 Google 开发者账号,费用约 25 美元/年,经过大约 2~3 天的账号审核,就可以向账号中上传应用。值得注意的问题是,目前 Google Play 尚不支持大陆信用卡,因此,在 支付费用时,需要使用具有国际支付能力的信用卡。 当然,Google Play 中的应用面向全球用户,你的应用国内、外用户都可以搜索和下载,并且用户终端不必越 狱。用户可根据需要选择是否上传应用到 Google Play 中。 除了官方的 Google Play,国内其实有名目繁多的电子市场,在搜索引擎中搜索“Android 电子市场”,排名比 较靠前的有机锋市场、3G 安卓市场、木蚂蚁、安卓市场、91 手机助手、应用汇、安致市场等等,各个厂商在定制 android 智能手机和平板时,也会在系统中嵌入自己的电子市场,如三星电子市场,其中也有很多应用可以下载。 开发者也可以考虑通过国内的电子市场渠道来发布应用,无需开发者账号的费用,但一般也都需注册账号并通过 应用审核。值得注意的是,这些应用市场中的应用大部分免费,收费应用的分成方式各个市场也不一样,笔者没 有一一去了解,如果需要对应用收费,建议考虑官方的 Google Play。 至于应用上传至哪个市场,需要考虑的因素包括审核通过的时间、更新审核通过的时间、市场的用户群体和 活跃用户量,以及可以用于帮助推广应用的资源及其收费情况,等等。尤其是如奥运场馆地图、圣诞节热点地图 等等针对特定时间和事件推出的应用,时效性很强,生命周期也很短,因此上述因素都需要着重考虑。Esri 中国在 今年(2012 年)8 月份的时候推出了针对 2012 年第十届用户大会的掌上参会指南,这款免费的应用也曾探索性的 发布在了多个电子商场中,现将发布的数据公布如下: 市场 机锋市场 3G安卓市场 木蚂蚁 91手机助手 Google Play AppChina应用汇 百度开发者中心 豌豆荚 安卓市场 下载量 1340 730 1542 207 3 46 25 35 40 总体来说:  木蚂蚁市场的 app 审核过程最快,基本一天之内就可发布,这对为 app 争取发布时间十分有力。当时掌上参会指南 app 中因使用到了新浪微博的 API 而需要通过新浪的审核,而新浪审核的条件之一就是 app 已经发布在一个电子市场 中。在同步上传的这些电子市场中,木蚂蚁最先通过审核。 75  从最后的下载数据来看,木蚂蚁上的活跃用户很多,下载量也是很客观的。值得注意的一个地方在于,木蚂蚁无需注 册账户而直接上传 app,导致在更新 app 时无法准确定位到旧的版本,而只能采用同样的流程上传一个新的版本,并 且通过相同的应用程序名称去替换旧的版本,而这个更新审核的过程是由木蚂蚁工作人员来完成。  机锋市场上的下载量也很可观,并且机锋市场的整个上传、审核和更新的流程感觉上都比较规范,也是笔者推荐给大 家的一个电子市场。账号审核和 app 上传和更新审核的时间约为 2 天左右;  3G 安卓市场和 91 手机助手其次。这些市场的账号审核和通过时间大同小异,均约在 2~3 天,用户活跃量一般。其它 的电子市场从掌上参会指南的下载数据上讲基本可以忽略,这些市场本身的应用也较少,知名度不高。  Google Play 官方市场,由于不支持中文,app 的关键字和描述信息都是英文,不利于国内用户搜索到应用,另外, 由于各种原因,Google Play 上的中国用户也相对较少,下载量并不乐观,所以如果是免费 app 并主要面向国内用户, 不建议采用 Google Play 来发布。 以上信息是笔者根据 Esri 中国 2012 年的一款免费的用户大会掌上参会指南的发布经验得出的,在此列出仅供 大家参考,提出一个发布 app 的建议。用户在实际发布 app 时需要结合 app 自身的特点和定位,以及各个电子市 场的特点来选择合适的平台。 76 第十四章. 学习资源 1、Android Developers,关于 Android 开发的参考资料、帮助、SDK 等都可以在该网站获取到,地址: http://developer.android.com; 2、ArcGIS for Android 帮助、示例、API 说明、开发包下载链接都可以在 ArcGIS Resource Center 上找到, 地址:http://resources.arcgis.com/content/arcgis-android; 3、ArcGIS_Mobile 新浪官方微博,分享产品动态、ArcGIS 移动技术、ArcGIS 移动应用的最直接窗口,欢迎关 注:http://weibo.com/arcgismobiles 4、ArcGIS_Mobile 官方博客,专注 ArcGIS 移动技术,分享技术研究成果,欣赏移动应用,地址: http://blog.csdn.net/arcgis_mobile/ 5、ArcGIS 在线体验中心提供了各行业大量的演示系统,均可在线免费体验,并提供大量的操作和案例视频供 下载,地址:http://tm.arcgisonline.cn/; 6、Esri 中国社区移动板块中,可以和来自各界的移动 GIS 高手交流问题,并分享自己的经验,地址: http://bbs.esrichina-bj.cn/ESRI; 7、ArcGIS Online 中国,提供大量免费的基础地图,包括全国范围和 31 个市的基础底图,地址: http://www.arcgisonline.cn; 8、ArcGIS 4 Android QQ 群交流群:167467748、250106494; 9、技术支持网站,为用户提供最新的补丁包、插件下载,以及常见问题和解答,地址: support.esrichina.com.cn; 10、ArcGIS 官方技术博客,涵盖了 ArcGIS 各个产品,是用户了解 ArcGIS 技术的统一入口,地址: http://blog.csdn.net/arcgis_all。 77 第十五章. 附录 1. 如何制作离线地图数据 tpk 是 ArcGIS 10.1 推出的一种新的数据文件类型,主要是用于将切片文件打包形成离线地图包,tpk 可以在 ArcGIS Runtime 或者 ArcGIS for Android/iOS 中作为切片底图被加载,下面介绍 3 种制作 tpk 的方法。 1) 使用 ArcMap 制作 tpk 在 ArcGIS 10.1 中 tpk 的生成被集成在了 ArcGIS for Desktop 中,制作方法如下: a) 打开 ArcMap,将数据加载进来,选择菜单 Customize-》ArcMap Options,在弹出的对话框中选择“sharing” 选项卡,勾选“Enable ArcGIS Runtime Tools”; b) 此时,在 File 文件菜单中的“share as…”菜单下就多了一个选项“Tile Package…”,选择该菜单,弹出“Tile Package”对话框,设置各个标签页中的参数,基本都和发布 ArcGIS for Server 地图服务时的参数相同, 78 填写完成后点击“Analyze”,如果报错则根据错误提示重新修改各个参数,最后点击 Share,开始制作 tpk 文件: 2) 使用 GP 工具制作 tpk 另外一种方法是直接通过 GP 工具完成 tpk 的制作。选择“ArcToolbox”-》“ Data Management Tools ”-》“ Create Map Tile Package”,如下: 79 运行该 GP 工具,弹出如下对话框: 选择要制作 tpk 的地图文档 mxd,指定 tpk 保存的位置,切片格式默认使用 PNG,级别根据需要设置,点击“ok “即可完成的 tpk 制作。 3) 使用已有的紧凑型切片制作 tpk a) Tpk 文件的组成 tpk 文件其实是一个 zip 文件,通过解压缩 Tpk 文件,可以得到 tpk 文件的内部结构,由 esriinfo 和 V101 两个 文件夹组成,如下图: 80 其中"Trchive"可以替换为你自己项目中的实际名称,其它文件夹名称或文件名称均不能更改。thumbnail 文件 夹中存放的是切片的一个缩略图,其余文件是描述文件或者说是 tpk 文件的配置信息文件,尽管有一个文件的后缀 名 pkinfo,都是 XML 结构的;V101 文件夹中就是熟悉的紧凑型切片数据和一个.layer 文件。 熟悉了 tpk 的结构,制作 tpk 数据集就容易了,先按照其组成在项目文件夹下新建两个目录 esriinfo 和 V101, 之后制作其它文件,需要制作的文件共有四个:一个缩略图,两个描述文件,以及一个 layer 文件; b) 制作 thumbnail(缩略图) 为切片制作一个 200×133 大小,格式为 png 的缩略图,并保存至 esriinfo 目录下的 thumbnail 文件夹下(在实 际过程中,没这个文件也是可以的)。 c) 生成 item.pkinfo 文件 在 esriinfo 目录下新建文件 item.pkinfo,文件内容如下,红色部分需修改(其实 Culture='zh-CN'这个也可以修 改,不同的国家这个是不一样的,因为都在中国,所以这个我就略过了): F24BC58B-F4A6-4414-921D-B762DE9545F3 Test 10.1 Pre-release -1 Tile Package false d) 生成 iteminfo.xml 文件 在 esriinfo 目录下新建文件 iteminfo.xml,文件内容如下,红色部分必须修改,蓝色部分为一些描述信息,可 随意填写: Test F24BC58B-F4A6-4414-921D-B762DE9545F3 Test 81 Test Test Test Test Tile Package Tile Package ArcGIS Runtime .tpk thumbnail/thumbnail.png -179.999999999987 -86.3842826037127 179.999999999987 86.3842826106563 WGS_1984_Web_Mercator_Auxiliary_Sphere Tips:可能你已经注意到,这两个配置文件中,红色部分的标签的值是一样的,对,它们的值必须一一对应,name 为.mxd 的名字,guid 则是全球唯一标识号,可使用一些软件自动生成。关于 guid 的生成网络上有很多介绍,在此不赘述。 e) 制作 layer 文件 打开 ArcMap,添加切片文件到 ArcMap 中,设置文档保存属性为相对路径,将添加的切片图层另存为 layer 文件,同时,将生成的切片文件和 layer 文件拷贝至 V101 目录下。 f) 打包为 tpk 将整个项目目录打包为 zip,打包时选择存储。将文件后缀名更改为 tpk 就得到所需要的 tpk 文件了。 82 2. 如何发布 Feature Service ArcGIS for Server 的帮助中指出,要素服务可用来通过 Internet 提供要素,并提供显示要素时所要使用的符 号系统。之后,客户端可执行查询操作以获取要素,并执行相应的编辑操作。要素服务提供了可用于提高客户端编辑体 验的模板。此外,要素服务也可以对关系类和非空间表中的数据进行查询和编辑。简单理解,就是将矢量数据通过 ArcGIS for Server 发布成服务,桌面、web 和移动等多种客户端通过 Internet 和要素服务的 url 来访问这些矢量数据中的要 素,查询要素的信息,执行编辑和修改要素等操作。下面一张图清晰的反应出了要素服务的制作和使用流程: 发布要素服务对数据有要求,如下: 1) 所有数据必须来自单个 ArcSDE 地理数据库。 2) 所有数据必须通过地理数据库注册。 3) 如果要允许编辑数据,将需要 ArcSDE 数据的写入权限。使用 OS 身份验证时,必须向 ArcGIS Server 帐户授予这些权限。 4) 支持版本化和未版本化数据;但是,如果需要使用服务编辑非简单类型(例如,网络边),则需要进行 版本化。 按照上述要求准备好数据之后,执行以下步骤发布要素服务: 83 1)菜单 File ->share as ->service,出现以下界面; 2)选择“publish a service”,点击“下一步”,在“publish a service”对话框中选择要发布服务的服 务器以及服务的名称,并点击“下一步”: 3)选择服务保存位置,使用已有的目录和新建目录均可,点击“Continue”: 84 4)在弹出的“Service Editor”界面中,选择“Capabilities”选项卡,在右侧的 Capabilities 列表中选中 “Feature Access”: 5)选中“Feature Access”之后,在左侧的“Capabilities”列表下会多一个“Feature Access”标签, 选择该标签,可以设置要素服务的能力,如允许创建、删除、更新和查询等。 85 其它参数设置与发布地图服务相同,不赘述,之后点击“Analyze”,如果有报错,按照提示修改错误,知 道没有错误之后,点击“Publish”,直到服务发布完成。至此,要素服务的发布顺利完成。 3. 如何发布 GP 服务 GP 服务是 Geoprocessing 服务的简称,Geoprocessing 包含了一系列地理数据处理的功能,像做缓冲区 分析、叠加分析、以及对栅格数据制作阴影图等等。在桌面软件中可以通过 ArcToolbox 中的工具直接调用 86 Geoprocessing 的功能,而如果期望通过 web 来调用 GP 的功能,就必须借助于 GP 服务了。在 ArcGIS 10 中, 发布 GP 服务有两种方式:直接发布一个 GP 工具,或将 GP 工具作为一个工具图层(tool layer)和地图文档一 起发布,这样会同时得到同名的一个地图服务和一个 GP服务。这里地图服务中的图层可以当做GP任务的数据源, 也可以利用工具图层得到的结果来控制最后输出图层的符号。 但在 ArcGIS 10.1 中,发布 GP 服务的方式有了一些新的变化,不再支持 ArcGIS 10 中的发布方式,而要 求先在 ArcMap 中运行 GP 工具,得到正确的处理结果,然后在 Results 窗口中,选择运行结果->右键->share as->Geoprocessing service。 接下来的对话框跟发布要素、地图等服务一样,选择“publish a service”,点击“下一步”; 选择发布的服务器,设置服务的名称,点击下一步: 87 可以看到,这个界面与发布其他服务的界面十分相似,在“Capabilities”标签页中可以设置 GP 服务的能力, 查看 GP 服务的 url 等信息: 88 设置好一些参数之后,点击“Analyze”,如果有错误则按照提示处理,直到没有错误: 点击“publish”,直到提示服务发布完成,GP 服务即成功发布,并可通过上述 url 地址进行调用。 4. 如何向 ArcGIS Online 发布和共享服务 前面相关章节已经介绍了 ArcGIS Online,它是 Esri 的公有云 GIS 平台,也是面向大众的在线制图平台, 使用它可以将服务托管在 ArcGIS Online 上,并将其共享给其它用户,步骤如下: (1)打开 ArcMap,载入数据; (2)登录 ArcGIS Online。点击“file”-“sign in”,输入用户名和密码,点击登录; 89 (3)从这步开始才真正的开始发布服务,点击“file”-“share as”-“Service”。在弹出的对话框中选 择“Public a service”,点击“下一步”; (4)选择”My Hosted Services (**)“,括号里面的内容是登录账户的名称。输入服务名称。点击“continue”; 90 (5)Parameters 参数这一块,都是灰色的,不能调节; (6)Capabilities 功能,可以选择“Tiled Mapping”、“Feature Access”两种服务方式。“Tiled Mapping” 是托管“切片服务”,“Feature access”是托管 Feature Service。一般来说,两个不同时选中。以托管“切 片服务”为例,选择“Tiled Mapping”; 91 (7)点击“Tiled Mapping”。虽然这里没有变灰,但是不能进行更改; (8)点击“Caching”,这里可以设置切片的各种参数,如切片等级、切片方案、切片格式、各级比例尺等; 92 (9)点击“Advanced setting”,如果是选择“ArcGIS Online/Bing Maps/ Google Maps”的话,“Enter Scale”、“Enter Pixel Size”、“Add”、“Delete”、“Suggest”都是灰色的,因为这些比例尺是预先已 经定义好了,只能增加级别。如果选择其他的选项,都可以自己增加和删除相关的比例尺和级别。如果有需要, 还可以点击“Advanced”。设置切片原点,切片大小; (10)点击”Item Description“填入“Summary”、“Tags”,其他的可以不填; 93 (11)点击“Sharing”,选择对谁共享; (12)点击“Analyze”,如果没有出现“Error”,就可以发布了; 94 (13)点击“Publish”按钮,等待服务发布完成,最后提示“The service has been publisher successfully” 即表示发布和共享成功。此时,使用刚才的 ArcGIS Online 账户登陆,可以看到刚才托管的服务。
还剩97页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

sacredon

贡献于2016-03-09

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf