2011年12月31日 星期六

Year of Apple


不知道是習慣還是大圍氣氛的影響, 在一年的最後一天來個總結已變得理所當然。無論如何,自我反省確能認清當前所處的位置,修正向目標邁進的方向。

2011 年犯太歲之年再次讓我有突破性的發展。今年由打工一族轉為創業一族,由為別人打工到為自己打工。亦能讓太太全身投入照顧女兒。

公司成立了 9 個月,開發了 18 個 Apps,收支仍未平衡,與目標仍有差距。當中有為了爭取知名客戶而殺價,亦有自家 Apps 生產量不足,收入低乎預期之緣故。客戶數目方面,除了原本關係內的客戶之外,只增加了 4 位客戶,當中 3 位是由我引入。成績不好,但總算是有個交代。 始終我的時間是放在技術開發而不是市場開發。 明年繼努力。

管理方面,每周一次例會的習慣已經確立。每月一次評分的制度亦得以實行。是以 Lakoo 的打分制為藍本的在地化改良機制。分數不影響當月收入,只作為花紅分配的基準,另加入對同事當月的評語。目前運作順利。同事們亦漸趨成熟,能勝任較大的工作。因此公司安排了一筆花紅分派給同事,以表達一點心意。還有加薪。

在技術方面,HTML5, WebSocket, 圖案辨識,藍芽連線,PNG 解密,Windows Server 安裝,ASP.Net 編程,GPS 推送通知等都是今年學到的東西。 是收獲不差的一年。

機體開發方面,只在 Mac 機上成功以藍芽連線,機乎沒有進度。今年白過。

總括來說,在「Year of Apple」之年投放了大部份時間給蘋果,學到很多新鮮事,識到很多新鮮人,是之前打工生涯沒有涉及的範疇。

2011年12月30日 星期五

iDemo + ScreenSplitr

幾天前網遊時發現了一段踢爆「iWiFiHack 騙局」的 YouTube 影片,當中能在 Lion 上顯示一個類似 iPhone 4 模擬器的東西,而畫面竟然是真機的畫面。在好奇之下向影片上傳者查詢,原來他是在 Mac 機上使用 iDemo 及在 iPhone 上使用 ScreenSplitr,利用 USB 線把手機畫面傳到 Mac 機上。我立即安裝軟件試試,結果成功了。可是畫面的幀數比較低,是美中不足之處。不過這個方法能有助把 BeyondZ 作品拍成影片,上傳到 YouTube 內。

2011年12月29日 星期四

iExplorer

最近發現了一個好用的程式。它的名字是「iExplorer」。透過 USB 來瀏覽 iOS 裝置上的檔案。無論是 JB 與否一樣能用,只是 JB 機能查看所有檔案內容。對於開發人員來說,也是一個很好的除錯工具。除此之外,用來黑 Apps 也是十分好用。

2011年12月28日 星期三

在舊式 Mac mini 啟動 AirDrop

Enable AirDrop on Old Mac mini

我一直都很奇怪,為何家中的 Mac mini 找不到 AirDrop。今晚終於明白,原來不是所有的 AirPort 卡都支援 AirDrop 功能。不過,網友們提供了一個打開 AirDrop 的方法。啟動 Terminal 後輸入:

defaults write com.apple.NetworkBrowser BrowseAllInterfaces 1
killall Finder

2011年12月27日 星期二

iWiFiHack 騙局

今天網遊時發現一個叫「iWiFiHack」的 iPhone App,聲稱能在 iPhone 上破解 WEP 密碼。好奇的我當然找來一試。在 iPhone 4 運行這個 App 時覺得奇怪,當時用 iPod touch 4G 跑 WiFi Analyzer 能搜出來的 WiFi 熱點,竟然在 iWiFiHack 找不到。倒找到了幾個不在列的熱點。晚然找到了熱點,那不妨嘗試一下。誰不知五個熱點中有四個都沒有反應,只有一個能選。點選後,程式表示要收集 75000 份數據才能破解密碼。原本打算把它閣在一旁時,卻在數到 100 時畫面便轉為分析中,不一會還顯示出密碼來。

在驚訝效能奇高的同時,我感覺到有點不對勁,於是立即嘗試連接。結果失敗了。其後我把 iPhone 的 WiFi 關掉再試,竟然能搜出相同的熱點,亦同樣能收集數據,更能破解密碼!豈不神奇乎?當刻便知道 iWiFiHack 是一個騙局。用戶在下載前要完成一份資料,作者就是憑這些資料來賺錢...。

2011年12月25日 星期日

MacBook Air - BlueTooth - ATmega128

整理 Servo 資源期間,發現之前購買了 14 隻 ES08A,另加雜牌細 Servo 4 隻,共 18 隻細 Servo。這些 Servo 都是用來製作 Amigo Mini 二足步行機械人,打算在 2012 年繼續。

至於 MCU 板的話,手頭上有 ATmega-128 x2, Renesas x2, NEC V850 x4, Fujitsu FR60 x2。當中運算能力最強的是 FR60。不過體積較大,留待大機體才使用。迷你級別的機體會使用最細小的 ATmega-128。

硬體確認好了,輪到軟件。五年前製作機體時,用的是 Windows XP 平台的 Fujitsu 手提電腦;現在是 MacBook Air。兩個完全不同的平台。我最希望能在 MacBook Air 上完成編程及操控。首先測試了操控方面。原本用 USB to Serial 接線,可是沒有 Lion 的驅動程式。嘗試過其他牌子的 Lion 驅動卻不成功,於是嘗試另一個方式。接駁的方法是利用 MacBook Air 內置的藍芽跟一塊藍芽模塊無線連接。藍芽模塊的 UART 有線接到 ATmega-128 的 UART 接口。由於 2010 年時已編寫好 Servo 操控程式並儲存在 ATmega-128 之內,所以能直接測試及觀看數據。另外,在 Lion 內安裝 ZTerm 來觀看 MCU 的輸出,設定為 38400/8/N/1。打開電源,看到 2010 年 5 月所寫的程式輸出;再試試輸入 a 鍵能列出數值,一切正常!確認能使用 MacBook Air 操控。

2011年12月23日 星期五

機體資源整理

近來有點興致,想花點時間製作一部六足。整理過手頭上的資源,發現有 22 隻 Futaba Servo 及 10 隻 TowerPro MG995。我打算用 18 隻 Futaba Servo 製作。上次做了一點便放棄了,希望今次能完成一台!

2011年12月20日 星期二

Dissection of iFighter 1945

得到 Lakoo 高總的通知,上周六第一次踏進《創業公社》參與「Dissection of iFighter 1945」研討會。iFighter 是 EpicForce 公司在 iOS 上一個出色的射擊遊戲。而這個會就是製作人分享從公司的管理、遊戲開發的工具、營銷的策略上的分享。

最吸引我的是「公司管理」方面的心得。EpicForce 以發展目標是「貴精不貴多」,他們確實做到了。在過去二年時間開發出四款遊戲,全部都曾被 Apple 推薦過,而且銷量也很好。他們的 CEO Stanly 指出公司的同事都是有經驗、有能力、有態度的人。當然這樣的人才也要得到相對的回報才能留得住。加上有競爭力的公司文化,確實是一間很有熱誠的公司。籍著 2011 年的尾聲,也讓我重新思考一下 BeyondZ 在 2012 年應該往哪個方向走。

有興趣的朋友不妨回重溫一下當日的分享:
http://www.youtube.com/watch?v=xQVrzK97ol8

2011年12月16日 星期五

UIActionSheet 新貌

UIActionSheet New Look
今日無意之中看到一個新的介面。好奇之下追尋一下介面的名稱。這個介面是在 Album > Photo Stream > Picture > Export 中得來的。那個位置原本是 UIActionSheet 介面,相信是因為選項太多而自動變成這個樣子。我做了一個小實驗,加入 8 個選項,結果證明了這個是 UIActionSheet 來的。

2011年12月13日 星期二

ASP.NET 的 Connection String

之前替客戶開發了一個基於 ASP + ASP.NET 環境下的「推送通知」服務器;但她們的電腦部為了方便日後的發展,要 BeyondZ 把結構改為只使用 ASP.NET。對於不喜歡 Microsoft 的我,實在是一個折磨。在改版的過程中,一直卡在 MSSQL 的連接上面。Google 了很多很多,無論是連接的方法,以至 Connection String 的內容都有不同版本,變化萬千而且不完整。無法拿來即用。我把原本 ASP 使用的設定套到 ASP.NET 卻無法成功。最後原來在 Web.config 內的 SqlConnectionString 設定以下數值便可:

Server:WINDOWS_SERVER\SQLEXPRESS; Database=beyondz_db; Uid:user_sa; Pwd=12345678;

ASP.NET 的代碼為:
//  Get device token from MSSQL
String strSQLConn = System.Web.Configuration.WebConfigurationManager.AppSettings["SqlConnectionString"];
SqlConnection sqlConnection = new SqlConnection(strSQLConn);
sqlConnection.Open();

SqlCommand cmd = new SqlCommand("SELECT * FROM deviceTokenTable", sqlConnection);
SqlDataReader reader = cmd.ExecuteReader();

String deviceTokenList = "";
while (reader.Read()) {
deviceTokenList += reader["deviceToken"] + ", ";
}

2011年12月8日 星期四

《中國神馬天氣》上架

China Whats Weather
兩個星期前開始進入《聖誕提交高峰期》,平日七天內的審批、三天內的重審,變成八九天的審批、八九天的重審。最近有幾個 App 提交了,都需要很長時間才能通過審批。期間被拒絕了的更花上超過 20天時間才能通過。

今天最新上架的《中國神馬天氣》就是經過長時間審批的一個作品。這個 App 是免費下載的,有興趣的朋友不妨試試。如有任何意見,歡迎給我們留言指教指教。

http://itunes.apple.com/hk/app//id479136416?mt=8

2011年12月7日 星期三

Device Token

BeyondZ 旗下使用 Push Notifications 的 App 開始多起來,是時候整頓統一一下。在整理的過程中,突然想到一個疑問:在同一部 iPhone 上如果有兩個 App 都使用 Push Notifications 的話,那它們傳回的 Device Token 是一樣的嗎?雖然我做了數個含有推送通知的 APP,連推送服務器都有 PHP 及 ASP 版本。可是由於數據都是儲存在不同客戶的服務器,而且代碼中的設定不同,暫時無法印證。

根據我的認知,Device Token 是跟 App 的,亦即是說不同 App 在同一台機上是會生成不同的 Device Token。在網上搜了一下,分別有兩個說法:一是跟機,另一是跟 App;甚至是兩者皆有。使用開發證書的是跟機,使用正式推送證書的是跟 App。就此我向有經驗的朋友 Tommy 查詢。他是現時負責《帝國》正體版、簡體版、英文版的項目經理。他指出《帝國》這三個版本都含有推送通知,而這三個版本當然是使用不同的 App ID。結果是 Device Token 也不一樣。有了這樣的實證,我想不用做實驗也能放心地相信吧。

2011年12月6日 星期二

打開光碟機門

Open DVD Tray with Non-Mac Keyoboard

如果你的 Mac 機使用非 Mac 鍵盤,而又要打開光碟機門的話,可以利用 Finder 到 System/Library/CoreServices/Menu Extras 找一個名為 Eject.menu 的檔案,雙擊它便可。

2011年12月3日 星期六

Base 64 to NSData

今日嘗試了破解 Snoopy 遊戲,發現它的數據是以 NSUserDefaults 來儲存,而且用 Base64 來編碼。為此寫了以下代碼:

+ (NSData *)dataWithBase64String:(NSString *)string {
NSString *alphabet = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";

NSString *encodedString = [string stringByPaddingToLength:(ceil([string length]/4)*4) withString:@"A" startingAtIndex:0];
NSUInteger base64Length = [encodedString length];
int rawLength = (base64Length*3)/4;

char *dataByte = (char *)malloc(rawLength);
memset(dataByte, 255, rawLength);

int offset = 0;
for (int i=0; i<base64Length; i+=4) {
char a = [alphabet rangeOfString:[encodedString substringWithRange:NSMakeRange(i+0, 1)]].location;
char b = [alphabet rangeOfString:[encodedString substringWithRange:NSMakeRange(i+1, 1)]].location;
char c = [alphabet rangeOfString:[encodedString substringWithRange:NSMakeRange(i+2, 1)]].location;
char d = [alphabet rangeOfString:[encodedString substringWithRange:NSMakeRange(i+3, 1)]].location;

UInt32 value = ((UInt32)a<<18)+((UInt32)b<<12)+((UInt32)c<<6)+((UInt32)d<<0);

dataByte[offset++] = (value>>0)&0xff;
dataByte[offset++] = (value>>8)&0xff;
dataByte[offset++] = (value>>16)&0xff;
}

NSData *decodedData = [NSData dataWithBytes:dataByte length:rawLength];
free(dataByte);

return decodedData;
}

2011年12月2日 星期五

樹狀選單的處理方法

Develop Tree Menu by Using isKindOfClass

今日要製作一個介面,當中有一個 UIButton。點選按鈕後會出現一組清單。清單是以 UIActionSheet 的形式出現。點選 UIActionSheet 後會再出現相應的 UIActionSheet 或完結整個選擇過程。這種分枝再分枝的結構,我稱之為樹狀選單。

為了方便改動,我把所有數據以 Plist 方式儲存。這樣就容易作出修改及加減層次。

在程式開始時載入 Plist 備用。當 UIActionSheet 傳回 clickedButtonAtIndex 後,只需要讀取所選中的層次,如果是 NSDictionary 的話,代表還有下一層;如果是 NSNumber 便是完結。
 NSString *key = [brandKeyArray objectAtIndex:buttonIndex];
id brandValue = [brandDictionary objectForKey:key];

// If value is NSNumber then it is end of levels
if ([brandValue isKindOfClass:[NSNumber class]]) {
...
return;
}

// Otherwise, keep dig into next level
if ([brandValue isKindOfClass:[NSDictionary class]]) {
NSDictionary *dictionary = (NSDictionary *)brandValue;

NSString *string = [key substringFromIndex:2];
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:string delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];

NSArray *array = [dictionary allKeys];
NSArray *sortedArray = [array sortedArrayUsingFunction:keySort context:NULL];

for (NSString *brandNameWithSortingKey in sortedArray) {
NSString *brandName = [brandNameWithSortingKey substringFromIndex:2];
[actionSheet addButtonWithTitle:brandName];
}
self.brandDictionary = dictionary;
self.brandKeyArray = sortedArray;

[actionSheet showInView:self.view];
[actionSheet release];
}

2011年12月1日 星期四

訊號生成

Pulse Generation

自有 iPhone 以來都很想製作利用 iPhone 進行操控的機體,可是實在有太多東西需要學習,一直都沒有實行。單單要利用 iPhone 的 UART 接口跟 MCU 進行溝通,便要使用 Open Toolchain;也要找到合適的硬件接口。我曾到過黃金商場、鴨寮街及售賣 iPhone 配件的店舖,找到的 USB 接口都只有 4-5 條針的接線,而 TX 及 RX 針是沒有。所以無法使用坊間的 USB 接頭來改裝。外國網上有出售這樣的接頭,但連運費的整體成本卻十分之高。就算這個問題得到解決,Open Toolchain、Jailbreak、編程都各有障礙。

除了 UART 接口外,其實還可以用耳機接口來達成。這個相對地來得簡單,所以便著手嘗試。這個方式是利用程式生成所需要的訊號,利用 MCU 的 A2D 接口把訊號數值化,再進行控制。為了能快速實作,會先以車型機體作測試。

我選了《訊號生成》作為第一項工作。在網上找到一個音頻生成的程式,稍為改裝便能使用。可是阻礙出現了。我需要生成像方波般的訊號,可是數值正確,但波形則不是想要的模樣...。