Android 與網路攝影機(1)

大部份網路攝影機都會提供多種格式,例如 AVI、Motion JPEG 等等,這邊我選擇的是 Motion JPEG,主要原因是 Android 有直接支援這種格式 ,不會牽涉到「可能沒有解碼器」的問題。

首先是環境的準備,因為手頭沒有一般市售的網路攝影機,只好搭配手頭上有的 USB Cam ,克難的自己弄一個。 很幸運,正好有人用 python + OpenCV 寫了一個簡單的 Streaming Server,輸出格式正好就是 Motion JPEG ,網址是 https://gist.github.com/n3wtron/4624820

然後播放的部份,我是參考 StackOverflow 上的這篇 Android and MJPEG – Stack Overflow ,程式主要是繼承 SurfaceView 做出 MjpegView 來使用,MjpegView 裡則使用 thread 搭配 MjpegInputStream 去讀取指定位址的 Motion JPEG,進行播放。但這個程式有一個小問題,在 Android 3.0 以後,以 HttpClient (MjpegInputStream 裡使用了 HttpClient )去讀取網路資源時,會丟出 NetworkOnMainThreadException 。因此需要對程式進行改寫。

很幸運,StackOverflow 又有人提出解:Android ICS and MJPEG using AsyncTask – Stack Overflow 。這樣拼拼湊湊之下,要播放網路攝影機上的影像不是難事。

P.S. StackOverflow 上的範例程式有個問題,就是沒妥善處理 onPause/onResume,因此在按 Home 或切到別的程式再回來時,會沒辦法繼續播放。

[Android]用 am 輸入 MMI code

在 Android 裡,用 am 撥號,可以這樣用:am start -a android.intent.action.CALL -d tel:09xxxxxxxx

在撥號畫面裡,使用 MMI code 可以帶出一些特殊的畫面,每隻手機都不太一樣,但一般來說都會有 # 這些特殊字元,因此 -d tel:*#38# 這樣的參數就會失效。am 的原始碼在 frameworks/base/cmds/am 下,這邊可以看到 am 會用 Uri.parse 去解析 -d 後的參數,問題就出在這裡。因為是以 Uri 處理,因此也需要遵循 Uri 的規則,# 應該要使用 %23 才行。

所以使用 am start -a android.intent.action.CALL -d tel:*%2338%23 就可以成功。

小技巧是,你可以在編譯後,執行 out/host/linux-x86/bin/monkeyrunner ,在裡面依序輸入,就可以取得編碼後的 Uri 字串:

[python]
from android.net import Uri
print Uri.encode(‘your_string’)
[/python]