安能饭否新版发布

2011年01月16日 12:41

今天安能饭否发布了0.6版。这个版本带来的全新的界面和很多新的功能,称之为一个里程碑式的版本我觉得并不为过。

最早我做安能饭否,只是希望自己在手机上能用客户端访问饭否,节省流量并获得后台提醒的功能。于是就找了一个开源的软件twitta,在它的代码基础上修改并稍稍增强了一下。当时我并没有什么宏图大志,纯粹是想弄个东东自己用而已。所以我也遵循twitta的协议开源了。

正是因为代码开源,所以三日坊主同学在我的代码基础上又做了新的界面。在这个基础上,才有了今天的安能饭否。新的界面激发了我的热情,也使得这个项目真正焕发了活力。到了今天,我已经不满足于仅仅做一个能用的饭否客户端了。我希望能做一个受大家喜爱的饭否android客户端。

三日坊主是一个优秀的开发者,今天这个版本里大量的工作都是由他完成。感谢他。我也同样希望有更多的高手来帮助我们一同将这个项目做得更好。当然,如果有人能从我们的代码中获益,我也会感到开心。

新的版本在这里下载。如果访问Google Code网站有困难,那么这里还有一个墙内镜像地址。感谢.rex同学提供的镜像资源。

安能饭否的项目主页:http://code.google.com/p/fanfoudroid/

安能饭否测试版

2010年12月18日 19:13

饭否重开之后,我们的感觉一瞬间回到了一年前。除了那些被时间冻结的发言,还有一年前的各种技术。

然而一年之间发生了太多的事。一年前我还在用着200块的黑莓手机,用Opera Mini孜孜不倦的追饭,而一年后的今天,我已经成了一个android资深玩家,早已习惯了各种android客户端提供的后台提醒功能。

可惜目前饭否还用不上。

于是,我打算自己动手。

受到猛禽的饭坚勤的启发,我去网上找了几个twitter的客户端,打算从twitter客户端改一个过来。几经比较之后,我选择了 twitta 。选择的原因是因为它看起来比较好看,而且思路简单,改动容易。

但是twitta提供的功能太少,所以把基本功能改完之后,还远远达不到我的需要。所以我又自己增加了一部分功能。现在,这个客户端已经基本满足我自己的需要了,于是打算发布出来。

安能饭否目前的功能包括:

  • 查看自己和好友消息
  • 查看提到我的消息
  • 查看特定用户的消息
  • 回复
  • 热饭
  • 私信
  • 发言
  • 拍照/从图库选择照片 并上传

未来打算完成的功能:

  • 收藏管理
  • 回复消息线索查看

我的业余时间不算太多,因此也许不会弄得很快,不过我会慢慢改进,至少要满足我自己个人的需要。

随后我会将代码开放

项目源代码在http://code.google.com/p/fanfoudroid/,欢迎协作开发。

下载地址 (Google Code)

[tips]vim替换技巧一则(数字递增)

2010年11月08日 17:51

(本文收录于[go4pro.org]

为了充实自己,把《Dive Into Python 3》用calibre做成了epub版。

可能是自己不太会用吧,一开始做出来的书目录顺序和翻页顺序都不对(似乎它把所有的目录项都按字母排序了,很囧),折腾几次之后未果,后来发现有一个“调整epub”的菜单项,可以把epub分离出来手工编辑,然后再合并回去。于是就不再折腾如何自动生成正确的版本,而是手工调整了一下,效果还不错。

但是当调整toc.ncx时,遇到了一项艰巨的任务:目录项是有一个playOrder属性的,说实在话我不太清楚playOrder的具体作用,因为似乎顺序已经由文本本身给出了,不过我试过这个属性如果留空的话,Aldiko打开会出错。于是,在调整完目录的顺序之后,必须重新生成playOrder。

一个自然的想法是,我把playOrder="xxx"全部清空,比如清空成 playOrder="",然后再通过某个命令重新编号。

前一步很容易: 

:s/playOrder="[0-9]\{-}"/playOrder=""/

即可完成。

但是后一步怎么做呢?当然我可以写一个Python脚本什么的也很容易,不过既然我已经用VIM打开,如果能在VIM里完成岂不更好。所幸的是确实有解决之道:

:let i=1|g/playOrder=""/exe "s//playOrder=\"".i."\"/"|let i=i+1

这条命令由三部分组成:let i=1 和 let i=i+1 构成了一个变量递增的循环。我现在无意解释具体的工作原理,总之这样就是一个循环就对了。

关键是中间一句:g命令用于全局查找一个字符串,并对此字符串施加一个命令。比如:

g/\(12\)3/s//\14/  #查找123,并将3替换成4

而在上面的例子里,执行的命令是exe,exe用于执行一个命令,这个命令用一个字符串作为参数传递过来。在这里,这个字符串是:s//playOrder=\"<变量>\",其中变量的部分用字符串拼接的方法将i的值传入。

于是这件事就完成了。

vim很强大,是吧。

Android开发小感

2010年11月04日 09:18

前几天,因为更前几天的一次BT聚会上的一个偶然的想法,我开始算是半正儿八经的写了一个Android小程序。主要功能是在BT聚会时更方便的BS猪手。

程序非常小,小到没有什么可说的。我这几天做的事情无非就是查资料,抄代码,再查资料,再抄代码。如此循环。

不过小小的感想还是有一些,记录下来。没有太多技术含量,就不发到狗屎皮了。

  1. 就像我刚接触电脑那会儿一样,我写很多程序只是因为喜欢和为了解决自己的问题,而不是为了赚钱。我需要一个方便的低成本的供我使用的开发环境,以及方便的不那么正式的发布使用渠道。Android提供了这一切。感谢它。
  2. 我第一次接触Android开发是在更早的时候,当时只是浅尝辄止,并没有太过深入的去了解,当时感觉开发模式里的好多东西都很古怪很不习惯。但是这次做下来,发现其实很多当时认为的古怪模式其实是合理的,我用起来也比我自己认为的“合理方式”要更合理。所以,不要轻易批评自己不熟悉的东西。
  3. 没有可视化UI编辑器方面,我这次的界面比较简单,所以感觉用Layout配合手写还是挺合胃口挺舒服的,不知道以后碰上要精确控制的时候会不会觉得难受,以后有机会再试吧。另外现在有很多应用使用的是webkit做UI和原生组件进行交互,有机会也要试试。
  4. Android对内置资源的使用非常方便,这一点比起Windows开发真的是天差地别。在Android里你很轻松就可以做出很有Android味道的应用,而在Windows下要做出很有Windows味道的应用其实还是需要你花上很多时间的,随便做做的东西跟Windows内置风格可能会相差很大。
  5. Android 1.5/1.6和Android 2.1/2.2真是两个世界的东西。太多的差别了。版本差异我认为会是Android发展的最大短板。希望google在未来会有解决之道。这次考虑到实际情况,我只支持到了2.1/2.2,没有仔细研究1.5/1.6。
  6. Google到的中文世界的资料就是一个字:抄。搜到几百篇都是一样的,都不知道是谁在抄谁。而且根本就是古董级的东西,新版都已经不适用了,最近写的blog里居然还在抄。
  7. stackoverflow确实是好地方。

gphoto2是个好东东

2010年09月04日 21:21

继续尝试简明扼要的风格。

今天拿出久违的单反拍了一堆照片,等到晚上准备导电脑时发现杯具了。

我那只恐龙化石级的CF卡读卡器被两个儿子玩得不成器形了都,两排针脚完全扭曲成了麻花。尝试拨乱反正未果。

于是尝试把USB插到相机上。但是很显然相机没有被挂载为U盘。用lsusb发现设备被正确识别成了佳能350D,心中略安。

网上一顿狂找,发现一个gphoto2的工具可以直接支持相机操作,遂安装之。

结果发现……很杯具。不能用。

正在决定放弃之时又看到一篇资料说gphoto2仅支持相机的PTP模式。虾米鬼PTP模式?不过想想应该在设置里,去相机菜单里找了一下,果然有一个数据传输设置,可以设置成“打印/PTP”,设置之后,重新尝试……。OK了。

简单记录一下操作步骤:

设置相机的数据传输设置模式为PTP

用USB连接到电脑

打开相机

在电脑(Linux操作系统)上执行 gphoto2 --auto-detect,如果连接正确会看到相机被列出。

然后执行 gphoto2 -L 查找相机中的照片。注意一下照片前面有序号,下面会用到。

最后执行 gphoto2 -p <序号范围> 导出需要的照片。比如我要导出相机中全部的照片,在上一步中发现最后一张是 #176,则执行命令 gphoto2 -p 1-176,这个命令会把指定的照片导入到电脑的当前目录。

然后……该怎么办就怎么办吧。

不过我觉得我还是要去买只新的读卡器,这种导法麻烦不说,速度也慢了很多。

杯具的产生及解决

2010年09月01日 14:20

觉得以前遇到问题,总会洋洋洒洒写上一堆。我写得累你也看得累。所以这次我尽量简明扼要。

背景:

我的系统是用wubi安装的Ubuntu 10.04,Windows和Ubuntu双系统。

问题的产生:

看到一个grub美化的帖子,一时手痒,安装了,使用了,并且没有注意到它的错误提示。安装完之后启动,发现不是平时看到的Windows NTLDR,而是grub引导界面,并且是出错直接进入了rescue模式。

杯具了……

问题的分析:

因为使用wubi安装,Linux分区实际上被安装在/host/ubuntu/disks/root.disk,它所在的分区会在启动时由wubi引导程序挂载成/host,grub引导程序实际是安装在这个host(/host/ubuntu/disks/boot)上,而非mbr。因此在wubi引导之前,ubuntu的分区实际并不存在,如果将grub直接装到mbr,就无法引导ubuntu了。

另外一方面,可能是因为虚拟硬盘的存在,自动安装的mbr并没有正确识别出windows的引导程序,于是装好的grub也不能正确引导启动windows。

两者都不行,于是整个就杯具了。

问题的解决:

其实我们的目标就是要修复mbr,恢复成windows的那个版本。

而目前我的手头没有windows启动盘或修复盘。只有一张Ubuntu 10.04的安装盘。

杯具中的杯具。

还好Ubuntu 10.04可以当作LiveCD来用。

进入liveCD(试用)模式,然后配好网络。然后,上网找资料。

(此处省略过程1万字……)

经过几次失败尝试之后,找到了一个很容易的解决方法:

sudo apt-get install lilo (安装lilo,好古老的东东)

忽略一切错误提示

sudo lilo -M /dev/sda mbr

重启。

搞定。

-----------------------------

我真是一个善于修电脑的……好人呀。

各种求……我要变坏人……

使用Ubuntu工作

2010年07月21日 16:21

最近工作性质有所变化,离开了数据库开发部门,转回了老本行,做C++开发。考虑到开发的C++代码大部分都是在Linux下运行,所以我的心思又活络了,很久以前考虑过的使用Ubuntu做日常工作的想法又蹦回了脑海。经过几天的构思和实践,我发现使用Ubuntu工作基本是可行的。

当然,用Ubuntu工作跟个人使用不一样,因为工作性质的关系,需要做一些迁就,并且要考虑到各种问题,不能像个人使用那般激进。

安装

首先当然是Ubuntu的安装。工作机并不是新机器,上面已经有大量日常工作数据和资料,包括文档、代码和其它各种资料,另外还有大量的个人数据。如果要空出一个分区来安装,需要做大量的迁移工作。为了减少工作量以及由此带来的各种风险,我选择了使用wubi安装。

wubi在选择的分区上创建一个虚拟的分区(有点类似虚拟机的做法),最大容量可以到30G,然后将ubuntu系统安装在这个虚拟的分区上。并且修改Windows的Bootloader,增加一个Ubuntu的选项。进入Ubuntu之后,所有的Windows分区,除了安装所在分区之外,都会存在于位置列表中,当你点击打开时进行自动的挂载。而Ubuntu虚拟分区所在的实际分区,则会预先挂载到/host目录。

按这种方式安装好的系统,Windows下的一切都不需要改动,只是在安装所在的分区减少了30G的容量而已。如果觉得不需要则可以安全的卸载。可以使系统迁移的风险降到最低。

基本办公

邮件/日程安排使用Evolution,稍加设置即可,没有什么麻烦,值得一提的是日程可以设置跟Google日历同步,结合我的android手机,很方便。Office文档可以用OpenOffice阅读和编辑。

MSN/GTalk交流可以用Empathy。另外Ubuntu 10.04有一个提醒指示工具,直接集成了邮件/IM的提醒,很好用。

C++开发

这是我最重要的工作,找一些合适的工具当然是很必要的。这里要稍微介绍一下我们的代码规范。我们的代码以组件的形式分布在上百个目录中,用配置文件的形式指名组件间的依赖。有一个自制的工具负责产生项目代码,在Windows下,这个工具可以产生VC用的makefile和Visual Studio用的dsw/dsp文件,在Linux下,这个工具可以产生makefile。

makefile做构建没有问题,但是并不利于代码管理。而在几百个目录之间做代码管理,用VIM显然不太合适。必须要有一个IDE。在网上稍微找了一点资料之后,我选择了Code::Block作为C++开发的IDE。那么如何将产生的makefile导入成Code::Blcok的项目呢?一开始我想了很多办法,都没有得到满意的效果。后来找到一份资料,说Code::Block支持项目使用外部的makefile做构建,这让我茅塞顿开:我不需要创建一个跟makefile功能完全相同的项目,而只需要一个包含全部文件的项目,并指定用外部makefile就好了!后者简单得多。我稍微修改了我们的工具,增加了生成cbp(CodeBlock Project)文件和workspace文件的功能,并在project里指定使用外部makefile进行构建,这样既可以使用Code::Block做文件管理,又不用担心构建跟原来有所不同。一举两得。

数据库

我们的项目经常要跟oracle打交道,因此一个oracle的客户端还是必不可少的。还好oracle提供了一些免费的工具,可以让我们完成这个任务。可以去Oracle网站下载oracle-xe.deb做客户端基础(注意oracle-xe从定义上来说是server,按理oracle-xe-client才是我们要的,但实际中我发现client缺少很多必要的功能,比如tnsname.ora,所以我还是选择装server)。然后使用SQLDeveloper这个免费工具做GUI。说实话SQLDeveloper没有PLSQL developer好用,但还算是一件不错的工具。

版本控制

我们公司相当BT的使用Visual SourceSafe做版本控制。想要公司在短时间内改用subversion/CVS/mercurial/git是不现实的,于是我只能自己想办法迁就了。

首先为了使用VSS,wine是不可或缺的。安装完wine之后,可以去找一份现成的VSS 6.0直接拷贝到本地就可以了。然后输入命令:wine SSEXP.exe就可以启动VSS的图形化界面了。有可能第一次运行会失败,报找不到MFC42.DLL,这个也比较容易,去Windows目录下找一个DLL丢到VSS程序目录就可以了。

在Linux下运行VSS是无法直接访问远程目录的。不过好在Linux有mount这个强有力的工具。我们使用cifs文件类型将远程目录mount到本地目录,然后在VSS里选择本地目录就可以了。在mount的时候要注意权限。

根据wine网站的说明,check in/check out/getversion等常用功能都没有问题,different会出错,但我实际实验是正常的。另外还说加文件不行,这个还没条件试,改天试试。

-----------------------------------

基本上这么一来,我的日常工作在Ubuntu下就没有问题了。以后如果再碰到问题,再解决。

备份BAT脚本

2010年07月05日 11:50

有个需求:Windows服务器上有一堆的LOG文件,需要定期清理掉一些之前的文件,将他们归档到指定目录(归档时保持原先的目录结构)。

用Shell其实挺简单的,不过Windows服务器上不能用,而且服务器原则上也不能安装第三方的软件。所以只能通过BAT实现了。

本来认为这是一个不可能的任务,但是后来一查资料,原来Windows还提供了一个不错的工具:forfiles,可以查找指定日期之前之后的文件,并针对这些文件执行一个命令。这个命令可以满足我的需求。

这个命令是Windows 2003以上的服务器版本自带的,XP没有。如果需要的话,可以去下载一份2003的版本,直接可用。

但是forfiles执行命令的时候有个问题,就是他会将当前目录设定为扫描到的文件所在的目录,这一点在实现我的需求的时候,造成了一些麻烦。不过最后我还是写出了这个批处理,现在贴出来希望给需要的人一些帮助。

archive.bat

@echo off
rem 注意,以下所有涉及路径的变量,均必须为绝对路径,不能为相对路径。
rem 在这个批处理的同目录下必须存在do.bat,用于实际的文件处理

rem ====================================
rem 配置设定
rem ====================================
rem 扫描的源文件夹。此程序对目标文件夹是递归扫描的。
set SRC_PATH=f:\temp\test\src

rem 目标文件夹。需要归档的文件将存放在这个文件夹里。
rem 注意该文件夹必须为绝对路径
set DEST_PATH=f:\temp\test\dest

rem -- 归档几天前的文件
set DAYS=5

rem ==============================================
rem 实际程序开始
rem ==============================================

rem 实际处理文件的批处理程序
set DO_BATCH=%~p0\do.bat

forfiles /P %SRC_PATH% /S /D -%DAYS% /C "cmd /c %DO_BATCH% @isdir @relpath @path %DEST_PATH%"

do.bat

@echo off
rem 参数:%1=isdir %2=relpath %3=fullpath %4=dest_path
rem 注意:%2是相对路径

set ISDIR=%1
set RELPATH=%~2
set FULLPATH=%~3
set DEST_ROOT=%~4
set DEST_PATH="%DEST_ROOT%%~p2"
set DEST_FILE="%DEST_ROOT%%RELPATH%"

rem 创建必需的目标目录
if %ISDIR%==TRUE mkdir "%DEST_FILE%"
if not EXIST "%DEST_PATH%" mkdir "%DEST_PATH%"

rem 复制文件到目标目录
if %ISDIR%==FALSE copy "%FULLPATH%" "%DEST_FILE%"

rem 删除源文件(如果源文件是目录则不删除)
if %ISDIR%==FALSE del "%FULLPATH%"

其中 %~2中~的意思是消除对应字符串的分号("),比如原先%2的值是"c:\program files",%~2的值就是 c:\program files

%~p2的~p的意思是获取文件所在的目录。

其他似乎没什么好解释的了。

Design downloaded from free website templates.