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我们先了解到这里,下面我们看一些其它的内容。

ArcSDE 9.3 for Oracle 10gR2 在 Linux(SLES 10)上的安装

首先,别忘了装compat-g77包

1. 新建一个ArcSDE用户,比如sde

2. 进入sde的shell,打开~/.profile文件,添加如下环境变量
export SDEHOME=/opt/sde/93/oracle10g/sdeexe93
export ORACLE_HOME=/opt/oracle/product/10.2/db_1
export ORACLE_SID=orcl
export TNS_ADMIN=$ORACLE_HOME/network/admin
export PATH=.:$PATH:$HOME/bin:$SDEHOME/bin:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$SDEHOME/lib:/usr/lib:/lib:$ORACLE_HOME/lib

3. 进入安装文件的 linux/oracle10g/ 目录,运行./install -load,选择安装目录为/opt/sde/93/oracle10g

4. 打开$SDEHOME/etc/services.sde, 去除“esri_sde 5151/tcp”的注释

5. 在sqlplus中执行SDE安装目录下/tools/oracle/createsdeoracle.sql脚本,注意,执行前先修改这个脚本中的为你想要设置的SDE数据文件路径,这个脚本会新建sde用户,默认密码为sde

6. 用sde用户运行sdesetup命令:
sdesetup -o install -d ORACLE10G -l ***.ecp -u sde -p sde

7. 用sde用户运行sdemon命令控制sde服务

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月4日星期四

ArcSDE 9.3 + SQL Server Express 2005 安装常见问题

  • 连不上数据库
检查SQL Server实例是否填写正确,Post Installation默认只有机器名,需要在后面加上SQL Server EXPRESS 实例名。

  • 创建数据库失败
数据库文件须放置在%Program Files%\Microsoft SQL Server\MSSQL.1\MSSQL\Data目录下,Post Installation的默认设置有问题,你可以把Database name删掉重新填,下面的Data file会自动更新到正确的目录。

  • 启动sde服务失败
打开 管理工具\服务,找到ArcSde Service服务,手动启动它。

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年9月1日星期一

使用GeoServer发布ArcSDE 9.3数据

【环境】GeoServer 1.7.0 RC2,ArcSDE 9.3
【先决条件】安装ArcSDE SDK (java)

对于GeoServer 1.7以前的版本,官方文档支持ArcSDE9.2 sp2及以前版本,但我尝试连接9.3的SDE失败。GeoServer 1.7采用的是GeoTools 2.5,与之前的版本不同,因此我又尝试了这个版本+最新的SDE SDK,发布服务成功。


1.安装GeoServer、GeoServer ArcSDE 扩展及其依赖项

下载GeoServer:http://geoserver.org/display/GEOS/GeoServer+1.7.0-RC2,该页面也包含了ArcSDE Extension的下载链接。

首先安装GeoServer,安装完成以后,将ArcSDE Extension压缩包中的所有文件解压缩到GeoServer的lib目录:%GeoServer 1.7.0-RC2%\webapps\geoserver\WEB-INF\lib。

由于ArcSDE扩展依赖ArcSDE SDK,因此还需要将%ArcGIS%\ArcSDE\lib下的所有jar包复制到GeoServer的lib目录。

通过开始菜单启动GeoServer。


2.配置GeoServer连接ArcSDE

通过http://localhost:8080/geoserver 访问GeoServer Administrator。

首先进入“配置-数据-名称空间 ”,新建自己的名称空间,完成后点击左侧的“保存”。


进入“配置-数据-数据库”,点击“新建”,在这里需要新建一个SDE数据库连接。


进入“配置-数据-FeatureTypes”,点击“新建”,在这里通过一个SDE图层来发布一个FeatureType。这里发布了一个图层,在GeoServer中命名为“bj_road”。完成后点击左侧的“保存”、“应用”。


打开http://localhost:8080/geoserver/mapPreview.do,查看当前发布的SDE图层,选择合适的方式预览。下图是上面发布的bj_road的SVG预览。



3.获得kml服务

GeoServer的kml服务地址如下:http://localhost:8080/geoserver/wms/kml_reflect?layers=<名称空间>:<图层别名>,比如上面发布的bj_road,它的kml地址就是http://localhost:8080/geoserver/wms/kml_reflect?layers=wuyf:bj_road,将这个地址添加到Google Earth或者其它支持kml的客户端就可以对SDE图层数据进行查看了。