Json.Net serialization/deserialization

Json.Net 的 serialization/deserialization 其實不難,因為都內建了,我被卡到的原因,是因為我沒仔細看文件。我的類別裡有日期時間的屬性,但我一直以為不需要特別處理,但我錯了。


在用 JsonConvert.SerializeObject 時,得傳入 new IsoDateTimeConverter () 才行,要不然會導致之後 JsonConvert.DeserializeObject 時無法轉換日期時間。

var items = new List<Item>();
// other stuffs
File.WriteAllText (m_filename, JsonConvert.SerializeObject (items, Formatting.Indented, new IsoDateTimeConverter () ));
List<Item> objs = JsonConvert.DeserializeObject<List<Item>>(File.ReadAllText (m_filename));

另外一件重要的事情就是你的類別必須有 default constructor,如果沒有的話,JsonConvert.DeserializeObject 也會丟例外出來給你。

initrd+busybox

kernel source 的 Documentation/initrd.txt 裡,把 initrd 、開機順序跟必要的程序講的很清楚,依法施為,大致就沒問題了。

雖然如此,我還是花了快一天的時間。這邊紀錄一下我的作法,我是用文件裡提到的 loop device 方法,也就是先用 dd if=/dev/zero of=initrd bs=4M count=1 製作出 initrd,再用 mke2fs 格式化,接著用 mount -o loop 把這檔案掛為檔案系統。

然後我 build BusyBox,參考 BusyBox 原始碼的 examples/bootfloppy/mkdevs.sh 裡的 code,把我要的 device 都建起來,然後把 BusyBox 的相關檔案放進去,再把 examples/boot/floopy/etc 放進去。接著修改 etc/init.d/rcS, etc/fstab, etc/inittab,調整成我要的樣子以後,就差不多了。

因為這份 initrd 在開機後,我就拋棄了,所以 etc/init.d/rcS 最後得掛上真正的 device,並且切換過去:

# mount your device to /newroot.
mkdir /newroot
mount -t ext3 /dev/your_device /newroot
cd /newroot
mkdir /initrd
/sbin/pivot_root . initrd
exec /usr/sbin/chroot . /init </dev/console >/dev/console 2>&1

最後,umount,再用 gzip -9 壓縮得到 initrd.gz 之後,大致上就是這樣子。

VirtualBox的VM啟動不了兒

好久沒啟動公司的VirtualBox OSE,就想說啟動起來,打算開個新VM,裝個Debian來玩玩兒,結果不知道是不是太久沒啟動,他鬧了脾氣,出現這樣的錯誤訊息:

VirtualBox can’t operate in VMX root mode. Please disable the KVM kernel extension, recompile your kernel and reboot.

這真是一個糟,所以我立馬就把所有視窗都關掉(天知道我關了多少),然後重新開機,再試試,居然還是不行。拜請Google大神,果然早有人回報到 https://bugs.launchpad.netBug #292588 in virtualbox-ose (Ubuntu): “VirtualBox can’t operate in VMX root mode.”
照看起來,只要用這指令 workaround 一下就行了:sudo modprobe -r kvm-intel
我想應該是昨天裝了 qemu 的關係,因為印象中有裝 qemu-kvm,應該跟他有關係。Bug #292588後面的 comment 也有人提到這點,不過看起來,這 bug 真的很久了啊~

添加自訂的類別

就我目前所知道的有兩種方法:

  1. 放在mydroid/frameworks/base下:在mydroid/frameworks/base下建立目錄,然後裏面放java的source(請記得建必要的目錄),如果有需要的話,也可以在這裡放jni,對,不需要放Android.mk,只有jni目錄下需要。然後修改mydroid/frameworks/base/Android.mk,在packages_to_document後,加上你的目錄名稱,就這樣。最後你的類別會被加到 android.jar 裡。
  2. 放在mydroid/vendors/your_vendor目錄下:建立frameworks目錄,然後裏面再放目錄、Android.mk,接著就跟上面很類似了。最後再修改mydroid/vendors/your_vendor/Android.mk去include frameworks目錄下的Android.mk即可。這部份可以參考mydroid/vendor/sample/。最後還要記得修改 init.rc 裡的 BOOTCLASSPATH,加上你編譯出來的 .jar。

不過以上的方法,在 make sdk 的時候,都不會被包到 SDK 裏面去,這邊我還沒找到方法。

ChangeLog and svn2cl

目前大部分的開放原始碼專案都是遵從 GNU 的Changelog 格式,基本上寫起來不難,只是有點煩。
所以有的開發工具,例如 monodevelop (Version Control Screencast),甚至把你 commit 的格式也固定下來,讓你省掉許多功夫。
好吧,其實只是我今天突然想到以前有用過 cvs2log 這個 perl script,還不錯用,可以直接把 cvs 裡的 log 轉出來成 Changelog,所以,就想到 svn 應該有類似的工具,之前好像有用過,但我忘了。於是我就用 svn2log 去找,嘿,當然有這工具,可是這工具的網站已經連不上了。我只好退而求其次,用 apt-cache 找找,但也沒找到,只是有 subversion-tools 這個 package。裝起來試試看吧,裏面有不少東西,有一個小程式叫作 svn2cl,試了一下,果然這就是我要的東西。
要使用 svn2cl 來產生 Changelog 的話,在你 commit 時,log 就不需要加什麼格式了,就儘可能地在一行之內把 log 寫完,然後不要一次修改很多檔案,這樣產生出來的 Changelog 就會很不錯了。svn2cl 有相當多選項,甚至可以產生 html、只產生某段期間的 log…等,有時間再來研究看看。

Sensors in Android

拜請Google大神以後,找到這篇:阅读android有关sensor的源码总结,這篇寫的超級詳細,從上層到底層巨細靡遺的都描述出來了,但他並沒有描述當你有新的 sensor device 時,該怎麼做?
基本上,除了 Kernel driver 以外,還需要寫 library(sensor module),去實作 hardware/libhardware/include/hardware/sensors.h 所提出的介面,也就是上面文章最後面提到的 JNI 函數。這部份可以再參考這篇:Android Sensors Development對 HTC G1 Sensor的剖析。
對照著看,大致上就能了解了。Kernel sensor driver 被實作為一個 input system driver,當有事件時,會把 input event 發出去;sensor module 是被上層的 Sensor service 呼叫,主要是透過 _data_poll 函數詢問 input device 是否有事件並且取得數據。

NDK r4

跟 r3 比起來,這一版更方便了。
我的環境是 Ubuntu 10.04,所以我下載 for linux 的 zip 檔以後,解開放到 /opt 下,這樣就完成安裝了。
印象中,r3 Build 的方法,需要把程式放在 apps 下面,然後打 make APP=your_project 才能編譯,這一版可以允許你不放在指定目錄,你可以隨意放,像我放在 ~/NdkProjects/my_project 下,就可以直接打 /opt/android-ndk-r4/ndk-build 來進行編譯了。甚至我還意外發現,我不一定要在 ~/NdkProjects/my_project 下,只要在 ~/NdkProjects/my_project 的任意目錄下,都可以用 /opt/android-ndk-r4/ndk-build 來編譯。
此外,也可以用 /opt/android-ndk-r4/ndk-build -C ~/NdkProjects/my_project 來直接指定目錄,表示要編譯該目錄下的檔案,這樣就更容易整合到 Makefile 或 script 裡了。
gdb 現在也內建了,我還沒試過,要找時間試試看。然後也有限度的可以讀圖,不必再利用 Skia 硬幹了。
詳細的變動可以參考 /opt/android-ndk-r4/docs/CHANGES.TXT

電影流水帳(2010/6/11~2010/7/7)

到今天近一個月了,只看了三片,還有,另外回顧了之前的補完的EVA 25跟26,死與新生。
突然覺得今年要達成百片會有點難度了,我還沒去算,不過應該機率不高。
Toy Story 3 上映了,希望 DVD 趕緊出,這樣我就可以去百視達借來看了。

  • Percy Jackson & the Olympians: The Lightning Thief(IMDB, Wikipedia),中譯:波西傑克森-神火之賊。故事本身相當有趣,基本上就是把希臘神話的軼事搬到現代來,不過電影就拍的不怎麼樣,很趕,所以感覺上蠻多枝節都被砍了,書應該會比較好看,不過我想應該就跟哈利波特很相似吧,我想我是不會去借來看。波西是海神跟人類生下來的小孩,上高中的某天被誣賴偷了宙斯的神火,於是展開冒險與探索的歷程,最後發現小偷居然是曾經幫助自己的Luke。飾演雅典娜女兒的女主角Alexandra Daddario相當漂亮,有一種靈氣。
  • Nine(IMDB, Wikipedia),中譯:華麗年代。這是由舞台劇改編的電影,我沒看過,但裏面的歌倒是挺好聽的,特別是Kate Hudson唱的那首Cinema Italiano,很輕快,有機會要把原聲帶找來聽。故事是描述一個失去創意的導演要籌拍新片的心路歷程,在這個歷程裡經歷了數個女人,之後他心灰意冷,決定放棄拍攝,但是最後他還是重回導演椅,拍出他自己的這段歷程。這部片,我最喜歡的3個女人是飾演情婦的Penélope Cruz,飾演元配的Marion CotillardKate Hudson,Penélope跟Marion戲份很重,表演也很出色,深深覺得Marion之前拿到獎決非偶然。Kate戲份不重,但是她主唱的那首歌為她加了很多分。相當不錯看的片。
  • 新世紀福音戰士新劇場版:序(IMDB, Wikipedia)。劇情省略頗多,基本上第1部幾乎都是真嗣在唱獨角戲,而凌波零只是一個觸媒,讓真嗣願意上EVA的觸媒。

pywin32應用:刪Outlook過期郵件

寫了個小程式,來幫我把 outlook 寄件備份跟已刪除郵件的資料夾裡超過30天的郵件刪除掉。
主要使用python跟pywin32,雖然程式很短,但花了不少時間摸索。

首先是對 Office Outlook 的物件模型不了解,我參考了不少網路上的範例(例如:MG: Python for Windows)以及微軟提供的參考才摸索出來。
另外就是對時間的處理,OLE的日期時間跟python的日期時間不一樣,我參考了Converting OLE datetime values into Python datetime objects來作。
最後就是意外發現了 pywin32 有提供 makepy.py 這個工具,可以預先根據 COM Type Library 產生 code 出來,這就很類似 .Net framework 提供的 tlbimp。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import win32com.client
from datetime import datetime
from datetime import timedelta
import pywintypes
# Microsoft Outlook Constants
# http://msdn.microsoft.com/en-us/library/aa219371(office.11).aspx
olFolderDeletedItems=3
olFolderSentMail=5
# or you can use the following command to generate
# c:\python26\python.exe c:\Python26\lib\site-packages\win32com\client\makepy.py -d
# After generated, you can use win32com.client.constants.olFolderSentMail
# http://code.activestate.com/recipes/496683-converting-ole-datetime-values-into-python-datetim/
OLE_TIME_ZERO = datetime(1899, 12, 30, 0, 0, 0)
def ole2datetime(oledt):
return OLE_TIME_ZERO + timedelta(days=float(oledt))
if __name__ == '__main__':
app = win32com.client.Dispatch( "Outlook.Application" )
ns = app.GetNamespace( "MAPI" )
folders = [
ns.GetDefaultFolder(olFolderSentMail),
ns.GetDefaultFolder(olFolderDeletedItems)
]
for folder in folders:
print( "Processing %s" % folder.Name )
past30days=datetime.now()-timedelta(days=30)
mark2delete=[]
#If you use makepy.py, you have to use the following codes instead of "for item in folder.Items"
#for i in range(1,folder.Items.Count+1):
#    item = folder.Items[i]
for item in folder.Items:
if ole2datetime(item.LastModificationTime)<past30days:
mark2delete.append( item )
if len(mark2delete)>0:
for item in mark2delete:
print( "Removing %s" % item.Subject )
item.Delete()
else:
print("No matched mails.")