星期日, 一月 27, 2008

blog搬家了

终于...多个原因促使我将blog再次搬家了:

- Blogger虽然不错,无奈隔了一堵墙,这还是带来了不小的麻烦。
- 如果想给blog做一些自己想要的定制特性的话,基于空间自建的blog是更好的选择,加上对wordpress神往已久,终于决定加入wordpress的大家庭。

这次的搬迁算是相当顺利(因为有那个blog同步工具的帮忙),但也有一些损失,如下:
- 所有的留言都丢了,还好我的留言不多,但还是感觉有些遗憾。
- 帖子的分类信息也丢了,不过这个我可以一点点补回来,暂时还没来得及做。

回顾一下我的blog经历:
- 2003年5月,开始写blog(那时还叫做weblog),当时是放在我自己的PC上,用一些CMS程序来做blog,比如我用过mambo和PostNuke(在用这些CMS之前,我还自己用PHP写过一些,不过那时觉得太麻烦了,一个留言本都需要花很多时间搞)。
- 2003年7月,我发现了b2,这个在现在看来应该算是非常标准的blog程序了,在此后很长的时间内,我一直用b2作为我的blog程序,现在这个程序还可以从网上下载,但已经很久没有更新过版本了。
- 2003年8月,买了一个空间和域名,开始了比较正规的blog生涯。
- 2004年10月,这个空间的问题慢慢暴露出来了,服务比较差,带宽分配不合理以及强制广告等等,我的blog的积极性也慢慢降低了。
- 2005年,因为空间商和我自己的问题,我的blog几乎是停止了更新,这一直延续到2006年。
- 2006年,是比较彷徨的一年,我尝试了国内的一些blog服务商,比如blogbus,donews,都没能坚持下来,总是有这样那样的问题。我还考虑了很久是否搭建一个wiki来代替我的blog,并花了不少时间维护了一个个人wiki,最终我否定了这个想法。
- 2006年9月,我切换到了Blogger,这次切换看来是相当的明智,自此之后我blog的频率逐渐恢复了,并开始使用Gmail来发blog。
- 2007年一年是我的blog历史中最高产的一年,这应该得益于Gmail和Blogger的组合,非常感谢google。
- 现在,2008年1月,我再次切换到了wordpress,这个决定会对我的blog如何影响,需要在未来靠时间来检验了。

最后也是最重要的,亲爱的读者们(如果有的话),请更新你们的地址栏,到 http://www.liuzhongshu.com,这是我的blog的新家,使用rss的朋友们,也请更新地址到: http://www.liuzhongshu.com/feed,我原来的Blogger将会停止更新。

星期四, 一月 24, 2008

设置Sun J2ME模拟器

Sun的模拟器我感觉还是不错的,不过还可以给它们做很多设置,在

/usr/local/netbeans-6.0/mobility8/WTK2.5.2/wtklib/devices

下面可以看到每种设备有一个目录,在每个目录下都有一个xxx.properties (xxx取决于设备名)文件,编辑这个文件就可以设置某类模拟器的很多细节参数,比如

设置 touch_screen = true 就可以得到一个带触摸屏的模拟器(当然要运行的程序也支持触摸屏,才能看到效果),Cool。

星期三, 一月 23, 2008

flickr API

flickr API用起来还是很方便的,记录一下:

申请key
lickr的所有API都需要api_key,商业使用需要申请,个人使用也需要申请,但很简单,只是在Web上填个表单就可以了(需要flickr帐号),这样就可以得到一个很长的api_key。

格式
使用flickr API可以使用很多种格式,输入(Request)可以是REST/XML/SOAP格式,输出(Response)则更多,可以有REST/XML/SOAP/JSON/PHP等格式,最常见的输入格式就是REST格式,给个URL就可以了,并且可以通过工具curl在命令行下面测试。

curl
curl是一个命令行工具,用于各种URL交互,在Ubuntu下只需要sudo apt-get install curl就可以了,然后可以用curl来测试flickr的API,下面是用REST输入格式获取flickr的interesting图片的方法:
curl http://api.flickr.com/services/rest/?method=flickr.interestingness.getList\&api_key=xx\&per_page=5
这个API(flickr.interestingness.getList)会返回一组图片列表,这个API除了api_key参数外(这里api_key随便写了一个值),还带了另一个参数per_page表示每次返回几张图片。另外注意&前要用的反斜杠(因为在shell下&是个特殊字符)

图片
很多API(比如上面的那个)会返回一些图片的列表,包含访问具体图片的参数, 可以用这些参数(比如图片ID,图片所在的server ID等)就可以构造得到一个图片URL,来访问flickr上的图片(包括剪裁后的各种图片),很方便。

全部的API都在网站上列的很详细,简单易用。

星期一, 一月 21, 2008

Nokia 模拟器的调式

使用Nokia模拟器可以很方便的在PC上调试midlet,不过我用下来最深的感受是,慢。。。

也许是我的PC性能不佳,也有可能是这个Nokia Emulator优化不够,又或是Windows系统有关,反正在Netbeans里面,直接调用Nokia Emulator来调试的话,肯定是Emulator连不上而超时(因为模拟器还在那慢腾腾的启动呢),如果先用一般的run模式启动模拟器运行一下midlet,然后不关闭模拟器,再选调试就可以了。

Nokia的SDK包还支持真机调试,需要在手机上装一个Debug agent,我还没有试过,不过Nokia模拟器的模拟度似乎很高,估计大部分情况时是不需要这个牛刀的。。。

星期日, 一月 20, 2008

Nokia 模拟器

在Nokia网站上下载Java开发SDK,可以得到一个不错的模拟器,不仅可以支持J2ME开发,用来在PC上玩"手机"也不错的。可惜目前支持Windows系统

下载
Nokia的网站上选择合适的平台下载即可,我的手机是N73,自然选择S60,进去以后,页面后边可以看到有一个下拉框,列出了多个下载选项,比如 3rd Edition, FP2, Beta,这个就是S60v3的开发包了,FP2是指Feture pack2,相当于小版本号(反正我这么理解的)。选择这个就ok了,由于模拟器带了大量的手机程序,所以这个包很大。

安装
安装这个包很简单,安装完后,通常也要在J2ME开发环境中通知一下有了这个模拟器,在Netbeans,只需要在Java Platform对话框下把这个Nokia S60 Platform加进来就OK了(Netbeans会让选择一个目录)。

运行
运行之前,可以在Windows的Start菜单中,将这个模拟器切换为中文(不过中文汉化的不完全,有少量信息还是英文的),然后启动模拟器,就看到Nokia的一个"模拟手机"了,可是我运行了几遍都不能让这个手机"开机",无奈, 使用命令行运行开发包下的一个sdk.exe(文档中这么写的),就可以了,不过很慢,要等10秒左右才看到"手机"的开机画面,以后再通过Start菜单运行模拟器,也可以"开机"了,大部分Nokia手机程序都在里面,还可以切换主题,很酷的样子,找时间试试里面的手机"硬件",看看音乐播放/USB/红外/蓝牙是怎么模拟的,不过文档中如此说到,相机是模拟不了的,呵呵。

开发
如果是之前的Netbeans Project想使用这个新的模拟器,一定要为项目建立一个新的Configuration,并选择从Nokia S60 Platform中继承选项,而不能直接在原先的Sun模拟器上改(反正我这样做的结果是:运行时Nokia模拟器起不来)。不知什么原因,Netbeans6在Windows下的启动速度比Linux下慢很多(大约58秒vs30秒),怎么差这么多?

输入法
用这个版本的模拟器,可以看到它支持了中文拼音词组输入(这个应该可以比之前的输入法快不少),不错哈,不知什么时候能在我的N73真机上用。不过这个模拟器模拟的程度太高,在编辑框输入中文,居然不能用Windows的输入法(只能输进去英文),只能用下面的虚拟键一个个点,好慢啊。

星期三, 一月 16, 2008

MIDP 实例 I

下面是一个简单的midlet,它会在屏幕上显示字符串Commander,并显示一个Exit的软键,按下这个软键会退出程序。

源码

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Commander extends MIDlet {
  public void startApp() { 
    Displayable d = new TextBox("TextBox", "Commander", 20, TextField.ANY);
    Command c = new Command("Exit", Command.EXIT, 0);
    d.addCommand(c);
    d.setCommandListener(new CommandListener() {
      public void commandAction(Command c, Displayable s) {
         notifyDestroyed();
      }
    } );
                                          
    Display.getDisplay(this).setCurrent(d);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) { }
}

说明
这里涉及了MIDP程序的几个基本概念:
* MIDP程序被称为midlet,它的生命周期很简单,创建并构造后处于paused状态,然后通过StartApp进入Actived状态,退出时会调用DestroyApp函数,而actived状态可以通过调用pauseApp()回到paused状态,因此,一个midlet总是能看到这几个基本函数, 这几个函数通常是被应用程序管理器调用的,但程序自己也可以调用(下面讲解)。
* Display对应了整个midlet的显示部分,它有可能是不可见的(比如处于后台的midlet),而在Display上,自然可以设置Displayable对象,这个Displayable对象就象一般的GUI widget,有其家族谱系,不过在MIDP中,GUI widget比较简单,上面的例子用到的是TextBox。
* MIDP对用户输入做了高度抽象,Command就是抽象后的产物,它表示MIDP设备(比如手机)的一个输入,不同的设备上的Java实现会将Command对应到设备的某个输入上,比如使用软键,触摸屏等。多个Command可以加入到一个Displayable对象上,表示在显示这个对象时可执行的多个动作,而这些Command的安排也由Java实现去安排(比如组织为多个软键,或菜单)。
* Command可以注册一个CommandListener来执行command的响应,实际上就是一个回调函数了。上面的例子很简单,为了退出,调用了一个notifyDestroyed。

NotifyDestroyed和DestroyApp(boolean)
这个区别很重要:
* 当midlet被强制退出(比如用户通过程序管理器杀程序),DestroyApp会被调用,并带参数true,这种情况下notifyDestroyed不会被调,也不需要主动调。
* 而应用程序自己希望退出时,比如用户按了什么键,或工作已经做完了,那么应该调用NotifyDestroyed(),这时DestoyApp不会被触发,但通常主动退出前,也需要清理资源,所以一般的程序会在NotifyDestroyed前调用DestroyApp,会了和上面的退出区别,通常会带个false参数,但实际上这种情况下,不是一定要DestroyApp(比如没有资源需要释放),也不是一定要带false参数(比如没有什么需要和强杀区别,所以也可以带true参数)。

编译和发布
在Netbeans里面,无论选择何种configuration,这小程序都是能编译,仿真运行的,但要是想发布到手机上,必须选择合适的Device Configuration和Device Profile(Device倒是无所谓,似乎只影响仿真),比如对于N73,缺省的MIDP-2.1会导致最终程序无法在手机上安装,降为MIDP-2.0就可以了。

星期二, 一月 15, 2008

Linux下开发Nokia,难

想在Linux开发Nokia手机程序,怕是要失望了, Nokia的java SDK只支持在Windows下使用, 这很让人难以理解,从集成开发环境(Netbeans或Eclipse),到Sun的J2ME SDK参考实现,以及Sun的虚拟机都支持了Linux平台,为什么Nokia不支持呢? Nokia的网站上看到一些解释是虚拟机在Linux下实现工作量大,不过我觉得这只是一个借口,还是没有重视Linux,哎,短视啊。

不过索爱,摩托也不支持Linux,摩托更可气,它的手机上已经在跑Linux,却需要在Windows下开发Java应用程序,看看 这里