显示标签为“Mobile”的博文。显示所有博文
显示标签为“Mobile”的博文。显示所有博文

2009年2月2日星期一

ArcGIS Mobile 的被动消息接收

设想一下GPS特种车辆监控,如果采用ArcGIS Mobile开发了一个移动端程序,诚然可以达到导航监控的目的,控制中心也可以获得车辆运行的状态,但是控制中心是无法对车辆发送信息的,除非通过其它途径,比如SMS;另外比如,要做一个自动控制系统,让管理者在某地的控制中心就可以自动控制远端移动的目标,比如对火车车厢进行施封解封等等……这些仅仅靠ArcGIS Mobile是做不到的。

要达到上述的效果,就需要使用Socket通讯,原理很简单,相当于集成了一个微型的IM,每个移动的客户端联网的时候注册到控制中心,在控制中心就可以随时面向某个移动终端发送指令。

移动端连接到控制中心:

控制中心随时对移动端发送指令:

移动端收到指令(后续可以跟进其它操作):

2008年12月23日星期二

扩展 ArcGIS Server 在移动平台/互联网应用的可达性

其姊妹篇《扩展 ArcGIS Server 在移动平台/互联网应用的可达性补遗 —— 使用WFS-T

【环境】ArcGIS Server 9.3

在ArcGIS Server 9.3中焕然一新的ArcGIS MobileSDK让ArcGIS Server的魅力延伸到了WindowsMobile平台上,填补了ArcGIS企业级移动平台应用的空白;稍后推出的ArcGIS API forFlex/JS又在让ArcGIS在WebGIS领域浓妆重彩,带来良好的用户体验。无疑,在ArcGIS ServerADF提供完善功能的同时,这些不同平台、快速开发、体验良好的SDK和API扩展了ArcGIS的应用领域,深合以正合以奇胜的兵法之道。

然而,这几支奇兵初次露面,未免有些青涩。ArcGIS Mobile SDK与WindowsMobile和.Net的死死绑定限制了它的应用范围,市场份额远大于WindowsMobile的 Symbian+iPhone+RIM被华丽地无视了;而在互联网应用上,ArcGIS API forFlex构建与REST之上,也使得空间数据的提交被忽视,这在后Web2.0时代几乎是不可被容忍的。本文讨论的主要目标就是另辟蹊径,在这些缺 憾之处加以弥补,延伸ArcGIS Server的触角,使之尽量可以扩展到各个平台、各个应用的死角。

本文主要涉及两方面内容,一方面是数据的获得,一方面是数据的提交。事实上关于数据的获得我前面的一些文章已经有所阐述,这里就简而言之;而在数据提交上,本文将从REST出发,详细叙述通过REST和Geoprocessing构建“万能”的数据提交方法。

首先看一下数据的获得,对于ArcGISServer强大的服务发布功能,获得数据相当容易。比如我比较喜欢kml服务,你需要在(移动)客户端或者其他 地方需要处理的无非就是一个kmz(zip)的解压缩问题,这几乎在所有的平台上都有解决方案。当然,ArcGIS还提供很多的服务种类,你大可以选择自 己喜欢的类型。

下面是一个Android的应用,地图采用了Google Map组件,底图是Google卫星影像图,再次基础上叠加ArcGIS Server发布的kml服务,关于如何从ArcGIS Server获得kmz并进行解析,详细可查看我的另外一篇文章:http://wu-yongfeng.blogspot.com/2008/10/androidkml.html

对于数据的提交,我们最好需要一种不受SDK限制,不受防火墙限制的方法。好在ArcGISServer的核心就是服务,充分地利用这些服务是我们发挥想 象的空间。这里,我的方法是REST+GeoprocessingService。下面,让我还是在Android平台上先走一遍这个技术流程:

首先,编写一个python脚本,实现根据参数保存Feature到FeatureClass的功能:
import string, os, sys, locale, arcgisscripting

gp = arcgisscripting.create()

def createPoint(point, x, y):
    try:
        point.x = x
        point.y = y
        return point
    except:
        raise Exception, "Create point error."

try:
    if len(sys.argv) < 2:
        raise Exception, "No enough parameters."

    outputFC = sys.argv[1]
    inputString = sys.argv[2]
   
    outDesc = gp.describe(outputFC)
    shapefield = outDesc.ShapeFieldName
    rows = gp.insertcursor(outputFC)
    pnt = gp.createobject("point")
   
    values = inputString.replace("\n", "").split(",")
    row = rows.newrow()
    pnt = createPoint(pnt, values[0], values[1])
    row.SetValue(shapefield, pnt)
    row.SetValue("CaseDetail", values[2])
    rows.insertrow(row)
   
    del rows
    del row
   
except Exception, ErrorDesc:
    if ErrorDesc[0] != "":
        gp.AddError(str(ErrorDesc))


新建一个Toolbox,添加这个脚本并命名为AddTrafficCase,给脚本附上两个参数:需要保存的FeatureClass和传入的字符串 (包含坐标信息和某字段的属性值)。这个时候你可以先测试一下功能是否正常。在需要发布成Geoprocessing服务的Toolbox中的新建一个 Model,加入这个AddTrafficCase脚本,并定义Model的输入参数(字符串)和保存到的FeatureClass,如图:
当模型构建完成后,你可以将其发布成一个Geoprocessing服务。简单起见,我这个模型是没有返回值、仅提交一个点数据的服务,当然,你可以做很多扩展,万变不离其宗了。

让我们打开这个GP服务REST地址,检查它的功能是否正常:

下面我在Android的Map组件上开发一个小Demo,可以点击选择当前的坐标,再输入一些字符串作为信息一起提交到ArcGIS Server上来。

比如在Android平台,通过输入一些文本信息,通过如下的REST URL可以提交用户输入的信息:

                String detail = editTextCaseDetail.getText().toString();
String strURL ="http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase/submitJob?String="+x+","+y+","+detail;
    try
    {
                  URL url = new URL(strURL);
                  HttpURLConnection uc = (HttpURLConnection)url.openConnection();
                  uc.connect();
                  uc.getInputStream();
    }
    catch(Exception e){}


点击确定提交以后,刷新Map以后,我们可以看到地图上多了一个事件点,点击这个事件点,出现提示信息——刚才在文本框中输入的“arcgis”:

下面让我们在ArcGIS API for Flex中再走一下这个流程,其实本质是一致的:

    var parms : Object = new Object();
    parms.String = x+","+y+",这是Flex保存的";

    var geoprocessTask : Geoprocessor = new Geoprocessor();
    geoprocessTask.url = "http://192.168.200.157/ArcGIS/rest/services/GPService/FeatureService/GPServer/AddTrafficCase";
    geoprocessTask.submitJob( parms );


提交完成后查看一下结果:

从这两个例子可以看到,通过ArcGIS Server的REST和GeoprocessingService的组合,可以在任何满足联网条件的平台和应用上获取和提交数据,而不局限于 ArcGIS提供的SDK和API。也就是说,不管是移动平台、富因特网应用或是其他互联网应用都可以采用这种“万能”的方法进行空间数据的交互。在移动 领域,除了Android,移动市场份额最大的Symbian也已经选择了开源,可以看到以后在移动平台上进行开发绝非难事,通过本文你或许也可以感觉 到,ArcGISServer完全可以在这些地方大展身手。我们不用为ArcGISServer目前提供的仅有几个SDK和API而耿耿于怀,相信 LINING的这句断语:一切皆有可能!

2008年12月9日星期二

总结 ArcGIS Mobile 9.3 图层可编辑的条件

1. 数据源必须是 SDE
2. 数据必须包含 GlobalIDs
3. 不可含有 M and Z 值
4. 没有使用FeatureClass的 area或length字段进行渲染
5. 编辑多边形的第一部分必须按顺时针方向走,逆时针方向会形成洞从而引发一个异常。

2008年11月26日星期三

Windows Mobile程序获取google map切片时候需要注意的问题

如果始终提示403错误,可能需要检查一下HttpWebRequest的UserAgent的属性,可以随便设置一个,比如“Microsoft Internet Explorer”欺骗一下。

2008年11月13日星期四

ArcGIS Mobile 9.3 SP1的更新

1. ArcGIS Mobile Application支持smartphone版本,包括Windows Mobile 5.0 SmartPhone和Windows Mobile 6.0/6.1 Standard。
2. 修正了存储二进制块到Blob字段的bug。
3. 完善对PostgreSQL的支持,9.3原版本不支持数据提交。
4. 修正了GpsDisplay的问题

2008年11月11日星期二

ArcGIS Mobile 的 GPS Setting

前几天有人问我ArcGIS Mobile 的GPS Setting问题,关键就是在ArcGIS Mobile中是否实现了各种GPS的算法。在ArcGIS Mobile中,GPS Setting设置的是正在使用的GPS连接的状态,但是这里的设置并不改变GPS连接本身。ArcGIS Mobile是从NMEA信号中提取GPS信息,本身并不包含任何GPS算法(如差分、RTK等等)。

2008年11月6日星期四

Android 中文Google Map地图程序演示

与Android Google Map的区别:
1.无需API key,无限制
2.中文地图

以下录像展现了地图浏览功能:


如不能播放,试试这个链接

2008年10月29日星期三

Android解析KML

KML服务有两种,一种是纯文本的XML,一种是将一个纯文本的XML文件和其他资源(如图标)进行zip压缩后形成的KMZ,本质是zip。使用Android解析KML服务需要根据情况首先判断是否需要解压缩,然后再解析XML文本。

Android Java中包含了zip压缩解压缩工具库,可以从“java.util.zip”包中进行调用。我们看一下一个KMZ如何被解压缩:

URL url = new URL(strUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();

InputStream isKxml = null;

ZipInputStream zipIs = new ZipInputStream(uc.getInputStream());
ZipEntry zipEntry = null;
while ((zipEntry = zipIs.getNextEntry()) != null)
{
String zipEntryName = zipEntry.getName();
if (zipEntryName.endsWith("kml"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();

isKxml = new ByteArrayInputStream(os.toByteArray());
}
else if (zipEntryName.endsWith("png"))
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[512];
int readedByteSize = 0;
while ((readedByteSize = zipIs.read(b)) > 0)
{
os.write(b, 0, readedByteSize);
}
os.flush();
os.close();

InputStream isBitmap = new ByteArrayInputStream(os
.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBitmap);
kml.addBitmap(zipEntryName, bitmap);
isBitmap.close();
}
}
zipIs.close();

Reader reader = new InputStreamReader(isKxml);
parseKxml(kml, reader);//解析KML文本的方法
isKxml.close();
reader.close();

好了,解压缩完成后,重点就在解析KML文本上了。鉴于移动终端的KML内容不应该很大,因此在这里使用了XmlDocument方法解析,下面看一下方法:

private static void parseKxml(Kml kml, Reader reader) throws Exception
{
KXmlParser kXmlParser = new KXmlParser();
kXmlParser.setInput(reader);
Document doc = new Document();
doc.parse(kXmlParser);

if (doc == null) return;

Element eRoot = doc.getRootElement();
……(处理XML Element)
}

2008年9月28日星期日

Android SDK 1.0 移除了原先0.9中包含的KXML2库

如果原先使用KXML2来解析KML文档的,需要手动添加这个库。

最新版KXML2可以从这里下:
http://sourceforge.net/project/showfiles.php?group_id=9157

2008年9月19日星期五

Android开发简明教程-4.Activity跳转与传值

一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转,而且能够互相传值是一个很基本的要求。

在前面创建的MyApp中,我们通过点击按钮可以更新当前界面上的文本内容。现在我们想换种方式,在点击按钮后,显示一个新的屏幕,在这个屏幕上输入一段话,然后再返回到原先的界面显示刚才输入的那句话。

首先我们新建这个新屏幕的布局文件input.xml,并添加一个文本输入框和一个按钮(注意,xml元素的命名不要和其他布局文件中的定义重名,因为所有的资源都在R中进行索引,比如id,如果重名了在使用R.id.*的时候就会有问题了)。这个布局文件对应的是一个Activity,因此我们再新建一个Input类(继承自Activity)用于显示这个布局并响应事件。

然后,还有一个重要的工作,那就是在清单文件AndroidManifest.xml中告诉程序,我定义了一个新的Activity,你可以去调用它。

我们希望在以前的那个主界面上点击按钮以后可以跳转到文本输入界面,所以我们需要对按钮的onClick事件进行定义:
在这段代码里出现了一些新东西。首先是Intent,它是Android一个很重要的类.Intent直译是“意图”,什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图。它不但可以连接多个Activity,还可以在它们之间传递数据。在这里,我们就是用Intent从MyApp对象跳转到了Input对象。
再看紧跟着的startActivityForResult()方法,顾名思义,它可以从一个定义好的Intent对象启动一个新的Activity,并且,这个Activity会返回执行的结果,这些内容下面马上就会提到。

好,这里我们已经可以调出新Activity了,我们看一下执行的结果:

你马上可以想到,现在需要对新的Activity(Input)进行处理了。我们在点击“确定”按钮的时候,需要获得上面EditText对象中的文本,然后返回到前一个Activity(MyApp)中去。看我们的按钮事件处理:

这里的关键是SharedPreferences对象,这是在多个Activity(同一包中)共享数据的方式,本质上它就是一个可以在包的范围内进行数据共享的文件。
我们通过一个标签“Text”获得了和文本相关的那个SharedPreferences对象(“Text”仅仅是自己定义的一个标签),然后给它赋予一个“text”对象值为当前文本框中输入的文本。设置完成以后,设置当前Activity的执行结果为RESULT_OK,再关闭当前的Activity,剩下的事情就可以回到MyApp这个主界面中去执行了。

其实剩下的事情也很简单,在MyApp这个Activity中,我们需要重写一个函数,onActivityResult()。因为我们启动Input这个Activity的时候使用的是startActivityForResult()方法,这个方法会使Input执行完以后返回给MyApp一个结果,MyApp接收到返回结果的时候会触发onActivityResult事件,对于结果的处理就在onActivityResult()中进行。同样,我们通过“Text”这个标签获得SharedPreferences对象,再把字符串从“text”对象中取出来并显示到当前屏幕上。

另外说明一下,requestCode是用来标识请求对象,我们刚才在启动Activity的时候使用的是“startActivityForResult(intent, 0)”,这里的0就是requestCode,当然,你可以设置成任何你喜欢的值。


我们看一下执行结果:

对于Activity我们先了解到这里,下面我们看一些其它的内容。

2008年9月18日星期四

Android开发简明教程-1.简介

【关于本教程】Android的API文档和APIDemo做的是很不错的,但是Tutorial写得比较简单。因此,这个教程旨在对如何上手Android开发试图做一些更加简单的说明和解释,同时也会用一些案例片段来进行一些功能演示。
【教程开发环境】Eclipse 3.3.2(for Java EE),Android 1.0 SDK (r1),Window XP SP3
【联系作者】wuyongfeng@tsinghua.org.cn

Android构建于Linux Kernel 2.6之上,面向开发人员的开发语言是Java,这个Java是Java SE的一个子集,但并不是Java ME,Google开发了一个虚拟机Dalvik用于解释Android Java——这是我生造的一个名词,用以指代Android平台上的Java。——因此,很遗憾,很多为桌面或者Java ME开发Java库可能并不能直接在Android项目中引用,对于开发者来说,他们还需要做一些源代码移植的工作。

Android的开发环境很友好(Eclipse+Android Plugin),Android的功能很齐全(GSM、蓝牙、EDGE、3G、WIFI、GPS、相机、指南针……),同时,在Android SDK中还包括了对SQLite、OpenGL ES的支持,开源面对对象数据库db4o也声称已经全面支持Android。——我们可以在这些软硬件支持的基础上想像一下Android平台的应用扩展性……

放上一张换过皮肤的Android模拟器截图,大家先混个脸熟:)

下面,我们首先配置一下开发环境,并熟悉一些重要的功能。

Android开发简明教程-3.初识Activity

让我们首先从MyApp的目录结构入手。可以看到,在根目录下有一个“AndroidManifest.xml”文件,这是Android程序的清单文件,任何项目的组成模块都需要在这个xml文件中首先进行声明。“src”目录包含了项目的Java源代码。“res”目录包含了项目的资源。资源包括drawable(图片)、layout(布局)、values(值),所有这些资源都有一个ID,它们都由“src”目录下的“R.java”自动维护,通常你不需要去手动修改“R.java”这个文件,在项目中,通过R这个类就可以获得对应资源的ID,从而访问所有这些资源。

让我们继续打开“src”下的MyApp.java文件,看一下默认生成的代码刚刚如何在屏幕上显示了“Hello World, MyApp”。
MyApp类继承自Activity,Activity是Android应用程序的重要组成部分之一,它通常表现为一个屏幕,可以显示用户界面,并响应事件,简单来说你可以把它理解成桌面程序的一个窗体。一个应用可以有多个窗体,在多个窗体间可以跳转,从这点来说Activity的功能类似。当然,这是一种粗糙的类似,在后面我们慢慢发现Activity的一些其它特点。
在重写的onCreate方法中,最后一行setContentView(R.layout.main)设置了当前Activity的视图(View)。View包含了用户界面的布局和内容属性(View中可以包含View或者是继承自View的widget——比如Button等等),Activity设置了View以后就可以呈现一个图形的用户界面。新建一个View有两种方法,一个是在代码中使用new View()方法——当然,完全在代码中创建一个用户界面并很好地组织它是一件很繁琐的事情,所以,还有一种更加直观的方法定义View,那就是xml布局文件,让我们打开“res/layout”目录下的main.xml文件看一下。
在右面的树状图我们可以看到,这个View由一个根元素LinearLayout组织所有的屏幕元素,。在这里加载了一个TextView,这个widget可以向用户显示一些文本信息。我们可以切换到xml的文本编辑模式进行查看和属性编辑:
其中TextView定义的属性中有这样一行:android:text="@string/hello",这是定义了TextView显示的文本内容。“@string/hello”表示引用了string资源的hello对象,打开“res/values”目录下的strings.xml文件,你可以找到hello的值。由于设置了TextView的text属性,所以,屏幕上会显示这样一行文本“Hello World, MyApp”:
让我们回到setContentView(R.layout.main)方法,这个方法原型是setContectView(int resourceID),我们通过R.layout.main可以得到main.xml这个布局文件的资源ID,因此,这个方法就设置了MyApp这个Activity的View,并且在屏幕上显示了出来。

让我们再尝试添加一些其它组件,比如Button:这个Button我给它一个id来标识叫buttonHit,这是通过Button的id属性定义的:android:id="@+id/buttonHit"。这个id同样可以在通过R这个类来引用(在这之前需要先编译main.xml这个文件),下面我们马上就要使用这个id,因为我们想给这个Button添加一个事件响应。

打开MyApp.java文件,我们在onCreate()方法中添加这个Button的Click事件响应。这里需要用findViewById(int id)方法从id获得View(包括所有继承自View的对象),再给Button添加onClickListener:
调试一下:在下一小节中,让我们看一下一个Android应用中的多个Activity之间的跳转和传值。

Android开发简明教程-2.熟悉开发环境

Android SDK安装指南在这里:http://code.google.com/android/intro/installing.html,我的叙述是“简明”版的,所以,如果你遇到什么问题,请参考这个网址。

以下是Android SDK安装的简明步骤,如果你已经有了一个Eclipse并对相关操作比较熟悉的话,按照下面的步骤可以基本配置好Android开发环境:
  1. 下载Android SDK:http://code.google.com/android/download.html,解压到一个目录。
  2. 将SDK子目录tools/的路径添加到环境变量的PATH。
  3. 安装Eclipse Plugin(ADT, Android Development Tools):Eclipse3.3和3.4下操作不同,简单来说就是从远程地址 https://dl-ssl.google.com/android/eclipse/ 安装ADT;同时,你也可以从这个地址下载ADT,然后手动安装:http://code.google.com/android/adt_download.html
好了,现在我们的Eclipse中已经出现了Android项目模板:
新建一个叫MyApp的项目:
我们来运行一下这个什么都没干的程序。首先打开Debug设置对话框,在“Android Application”下新建一个名叫MyApp的项,在这里根据你的喜好做一些设置,比如我比较喜欢看横着的屏幕,所以我会选择Screen Size为“HVGA-L”。设置完成后,点击Debug,Eclipse就会自动启动模拟器并连接,然后在模拟器中运行我们的MyApp。
在成功运行了这个Hello World程序以后,让我们暂时把目光转到在Eclipse的透视上来。除了熟悉的Java、Debug透视,Android项目中还有一个重要的透视DDMS,这个透视对应了SDK中的DDMS(Dalvik Debug Monitor Service)工具,在这里可以在调试时对模拟器进行监控和操作,比如:我想在模拟器的某个目录下放置一个文件,或者模拟一个GPS定位信号,或者想给当前的界面做一个截屏……等等,都可以使用DDMS来实现。
Android的Eclipse的开发环境大致如此,最后,我们花一点时间看一下Android的命令行环境。在模拟器运行的条件下,打开控制台,输入 adb shell 就可以进入模拟器(Linux)的shell。试着执行 ls 命令,是不是可以看到模拟器的文件目录?
在下面的小节中,我们将会首先了解一些Android程序的基本概念。

2008年9月16日星期二

Android的InflateException异常

迄今为止已经遇到过2个问题引发了InflateException异常,通常来说,出现这种情况一般都是因为解析器无法正确解析布局文件中的类声明。

第一次遇到这个异常是我使用了google的MapView组件,在我使用代码new MapView()的时候没有任何问题,但是在我使用xml首先进行布局时引用一个MapView实例就出错,总是在MapView这一行出错,eclipse提示的异常是Binary XML文件解析异常,实质就是找不到xml元素对应的类声明。

这是我的xml布局声明:


这个错误的解决是要在AndroidManifest.xml中引入包含MapView的组件包:

第二次遇到这样的错误是我试图使用自定义的组件而引发的,我从LinearLayout继承了一个新的自定义的布局类,在xml布局文件中引用时又引起了InflateException异常。

问题的发生是因为我将这个继承的类放在了当前Activity的同一个包之下,在xml布局文件解析的时候,是没办法找到当前包的自定义类的,解决方法就是把这个类移出去,重构到一个新的包中。比如我的当前项目的包是:wuyf.android.trafficnowmap,原来的类放在wuyf.android.trafficnowmap.MyLinearLayout会引发错误,因此我将其重构到wuyf.android.view.MyLinearLayout,然后一切正常。

总结一下,使用xml布局一定要让xml文件解析的时候可以找到布局文件中使用到的类包,引用第三方的组件需要引入user-library,使用自定义的类则需要注意不要放置在当前包之下。

2008年9月11日星期四

Android发送HTTP请求抛出Socket异常

【环境】Android 0.9 SDK Beta (r1)

比如如下的代码,作一个HTTP请求:

URL url = new URL(strUrl);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();

InputStream is = uc.getInputStream();
DoSomeThing(is);
is.close();


如果调试的时候发现始终在
openConnection之后跳不过去,抛出“android java.net.SocketException: unknown error”异常,那么你就需要检查一下是不是联网权限的问题。

打开项目的配置文件AndroidManifest.xml,添加这样的一行标记以授予权限:


如图:

2008年9月2日星期二

编写高效的移动设备应用

目前来说,再快的移动设备(智能手机、手持设备)的性能也比不上主流的PC。而且,你要考虑电池续航等因素,所以,很多在PC应用上无所谓的代码,需要在移动设备应用中加以优化。

基本原则
用户体验依赖与你的应用,要想让移动设备应用不像蜗牛一样地响应用户的请求,就要保证你的应用不进行不必要的运算,不分配不需要的内存——归根结底,不做不必要的事。

有效使用对象
对象都是需要分配内存的,谨慎地创建短命的临时对象。

使用有效的数据结构
多个一维数组的性能要优于一个多维数组,所以int数组性能也要优于Interger数组。

实类比接口的性能要好
比如要创建一个哈希表,那么尽量使用HashMap hashMap = new HashMap(); 而不是使用Map map = new HashMap();

避免使用浮点数
目前的移动设备的硬件基本上都不支持浮点运算,浮点运算是通过软件实现的,性能极差。甚至是整数的除法和取模等运算,也是通过软件支持的,因此,尽量避免使用。

将成员变量缓存到本地
避免使用:
for (int i = 0; i < this.mCount; i++)
{
do(this.mObjects[i]);
}
而是这样:
int count = this.mCount;
Object[] objs= this.mObjects;
for (int i = 0; i < count; i++)
{
do(objs[i]);
}

不需要访问对象成员时使用静态方法
静态方法的调用性能更佳

少用getter和setter
而是直接访问成员变量,虚方法调用会带来额外的开销。

避免使用枚举
枚举会使代码可读性增强,特别对于API来说,不过,为性能考虑,尽量避免使用枚举。

2008年8月28日星期四

.Net Compact Framework获得当前目录

一直以为在智能设备上是不支持的,事实上还是有其它办法。查阅了微软的网站,由于某些设备操作系统不支持当前目录操作,因此简单的使用Directory.GetCurrentDirectory()在Windows Mobile等平台上会抛出错误。

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

2008年8月23日星期六

ArcGIS Mobile 9.3 + ArcSDE for PostgreSQL 向服务器上传更新Feature的bug

当使用 ArcGIS Mobile 9.3 SDK 开发的程序向 ArcSDE for PostgreSQL 提交本地新建或更改的Feature时,目标服务会崩溃并报“gsrvr.exe error”错误。开发人员已证实这是一个bug,将在SP1中被修复。

2008年8月19日星期二

ArcGIS Mobile 9.3 开发的Missing ArcGIS registry key错误

以前没有注意到这个问题,今天换了一个模拟器调试原先的程序,抛出“Missing ArcGIS registry key”错误。

这与ArcGIS Mobile的开发环境配置不人性化有关。我们知道ArcEngine开发桌面程序需要目标机器安装Runtime,但是开发机器的环境已经包含了 Runtime。ArcGIS Mobile与此类似,部署的时候需要在目标设备上安装ArcGIS Mobile Runtime,但是开发调试时并不会自动部署,因此需要你首先手动安装。

安装包是“%ARCGIS_HOME%\DotNet\WindowsCE\Install\AGMRuntime.CAB”,对于定制的WinCE平台,可能需要安装AGMRTWinCE.CAB

2008年8月15日星期五

使用ArcGIS Mobile SDK 9.3 开发移动设备应用-高级篇

【概述】概述如何通过ArcGIS Server 9.3提供的Mobile SDK开发移动设备应用。

【环境】Windows XP SP3,ArcGIS Server 9.3,Visual Studio 2008,Windows Mobile 6 Professional SDK


预生成地图缓存

我们已经知道,ArcGIS Mobile支持离线和在线两种应用。我们可以选择让ArcGIS Mobile应用在首次请求的时候保存地图缓存,也可以在此之前(部署应用之前),预先生成缓存,跟应用一起发布。是不是有点像原来的单机设备应用?

好,让我们把ArcCatalog打开,启动ArcToolbox工具箱:


在工具箱中,找到“Mobile Tools”。ArcToolbox专门为Mobile应用提供了两个工具。其中“Generate Mobile Service Cache”就是用以生成Mobile地图服务的缓存。


点 击确认,经过处理,在指定目录生成了缓存。我们可以比较一下,这些缓存和在移动设备上通过MobileService对象生成的缓存是一样的。换句话说, 在部署的时候将这些缓存部署到缓存目录以后,MobileService可以直接打开它,无需与服务器进行任何交互。


Mobile Basemap

这 是Mobile的特殊数据,目的在于通过对地图数据进行高度压缩,使之在移动设备上的性能更加优化。Basemap与我们前面使用的Mobile地图服务 数据不同,Basemap是不提供用户进行操作的,它将在程序运行时首先被渲染,其他所有的Mobile地图都将在它之上绘制——简单地说,它应该被称为 底图。

创建Mobile Basemap很简单,我们从ArcToolbox中点击“Create Mobile Basemap”,根据提示操作即可。一个mxd文档对应一个navmap文件,每个图层也都有相应的对应文件。

在ArcGIS Mobile中,有个专门的命名空间“ESRI.ArcGIS.Mobile.SdcData”,这个命名空间包括了所有对Basemap进行操作的类。事实上,Mobile Basemap对应的数据叫做SDC base map data。

Basemap的使用非常简单:

try
{
ESRI.ArcGIS.Mobile.SdcData.SdcMapLayer sdcMapLayer = new ESRI.ArcGIS.Mobile.SdcData.SdcMapLayer(@"\Storage Card\bj_basemap\bj.navmap");
map.MapLayers.Add(sdcMapLayer);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

看一下效果。我们把整个北京地图生成了Basemap预先部署到移动设备上,而仅仅将建筑物图层发布成地图服务,如图,Basemap自动衬在底部,想一下,对于某些应用,你会不会有一种把所有不经常变化的内容全部生成Basemap的冲动?

哦,还需要说明一下,Basemap和其他Mobile 地图服务的空间参考需要是一致的。

开发移动桌面程序

说是移动桌面程序,跟不移动的桌面程序有区别么?所以,这一部分需要说的内容实在太少了,在移动设备上开发调试都可以过来了,桌面程序还有困难么?

当然,还是有一点点小地方需要注意。比如新建工程,一定不要采用默认设置.Net Framework为3.5版本。

常见问题

以下是Develop Help中提到的一些常见问题:

1. ArcGIS 9.3的Mobile SDK是否使用ArcGIS 9.2发布的Mobile Service
很遗憾,不能……

2. 我能用Visual Studio 2003开发ArcGIS Mobile应用吗?
不能,ArcGIS 9.3 Mobile SDK需要.Net Compact Framework 2.0支持。

3. 我生成了Mobile应用,但是为什么我看不到地图?
出现这个问题,如果你使用了地图缓存,检查你的缓存路径是否正确。如果是从服务器获取数据,那么检查你的Mobile 地图服务是否正常工作。同时,确认你的Map控件的Datasource属性中的MobileService对象设置正确。

4. 为什么ArcGIS Mobile toolbox没被添加到Visual Studio 2008工程中来?
ArcGIS 9.3 Mobile SDK不能和.Net (Compact) Framework 3.5兼容,这是Visual Studio 2008的默认设置,注意在新建工程的时候选择正确的.Net Framework。

5. 如何获得开发ArcGIS Mobile应用的最新信息?
http://edn.esri.com/index.cfm?fa=mobile.gateway

【结 语】好了,到这里,ArcGIS Mobile SDK 9.3的整体内容已经基本介绍完成。ArcGIS Mobile作为ArcGIS Server的一部分发布,其与ArcGIS Server也的确是紧密相连。当然,事实上在某些条件下,ArcGIS Mobile还是可以脱离ArcGIS Server跑起来的。希望本文能给你开发移动GIS应用带来一点帮助!