Bitcode 與 Bytecode

大家都知道 Android 裡面有 Java virtual machine (JVM), 而 JVM 上面執行的就是 Java 的 byte code. Byte code 具有跨平台的性質, 所以 Java 可以 compile once, execute everywhere. 但 Android 裡面還有一個 bit code 就太為人所知.

Bit code 的功能和 byte code 一樣, 但是它不僅限於 Java 語言. 根據伊利諾大學的 LLVM (Low Level Virtual Machine) 計畫, front end 的 compiler 可以是 GCC, 而支援的語言包括 Ada, C, C++, D, Fortran, 和 Objective-C 等等. 這些高階語言被編成 LLVM IF (intermediate form), 然後被放在 virtual machine 上執行. 當然, 從 IF 也可以直接再編成可執行檔.

LLVM 的官網似乎都是用 LLVM IR (intermediate representation) 來代替 IF (WIKI 用語) 一詞, 而這個 LLVM Bitcode File Format 在他們的官網就可以找得到. 

Bit code 除了跨平台之外, 還有什麼好處呢?Google 在推的 RenderScript Compute 就是其中一個應用.  使用者可以先寫好 script, 然後交給 LLVM compiler 去翻譯成對平台最有利的 binary. 比方說這個平台的 GPU (Graphic processor unit) 很弱, 那麼某些 code 在 just in time compile 的時候就會讓 CPU 多分擔一點工作. 從 Android 3.0 的 Honeycomb 開始就支援 LLVM compiler 的 API, 放在 /system/lib/libbcc.so.

Android 即將進入 K 版

Android 一向以英文字母順序來命名產品, 大家可能都注意到它是甜點名稱, 而忽略掉它在 10/29  (傳言有誤, 待更新)就要進入第 K (11th) 版了. Android 進版如此迅速, 當然反映出它跟進競爭對手的決心. 否則它大可以讓使用者覺得 4.0, 4.1, 4.2 都是第四版, 而毋須給予各自的暱稱. 不過對於軟體開發的工程師而言, 實在是追得太辛苦了. 網路有個很好的比較表, 可以知道每一版的 Android 有何差異.

[打岔 1] 據說第 K 版的名稱是酸橙派 (Key lime Pie), 那麼第 P 版來個珍珠奶茶 (Perl milk tea) 也不算是意外.

我這邊另外做一張表, 把三個作業系統 (假如 Android + Linux 也算一個 OS) 的三個重要指標 – 能否跨平台, 人機互動, 消滅異己的版號列出來. 至於雲端, Market, 社群, 開機速度, 拍照, 強化語音辨識, 改善 UI 速度或美化等等不具戰略價值或大家都有的功能, 我就自動忽略了.

  Google Apple Microsoft
消滅異己 JB, 去 FLASH

IOS6, 去 Google 化
向來不支援 FLASH

不知
人機互動 JB (2012/6/27), Google Now IOS5, SIRI Win8, 據說有  chatter
跨平台

ICS (2011/10/19)

IOS5 (2011/10/12) Win8 (2012/10/23)

[紅色為更正]

不用說, Microsoft 真是敗在 Windows 太過臃腫. 以致於在跨平台上輸了競爭對手好大一截, 不過它也並非全無優勢. Skype 和 XBOX 算是它的獨門武器. 預計另外兩大陣營短期之內, 都不可能跟上進度. Apple 看似占盡上風, 不過封閉系統的問題也慢慢浮現 – 一個遊戲 App 就要 60MB,你手中的蘋果裝置塞爆了嗎?.

在人機互動方面, 只要耕耘得夠深, 客戶很容易養成習慣. 如果我是它們的操盤手, 我一定要讓這些裝置的 AI 軟體變成主角, 而不是綁定硬體. 它們需要被取名字, 而且能夠跨平台轉生. 如此一來, 客戶未來在換機時, 不得不考慮到讓那個 "虛擬的朋友 – 人工智慧" 還能繼續投胎轉世. 如果客戶再也不買我家的硬體產品, 沒關係, 只要付一點投胎費, 虛擬朋友在別的平台也可以活過來, 只是難免會有一點相容性的問題而已.

[打岔 2] 如果 AI 太強, 會不會主動拗客戶幫它 "換屋" 啊? "主人, 我想搬到最新的 iphone8…, 聽我朋友說隔壁老王的新手機很好住…"

最後, 有篇 Win8 十大升級理由 供大家參考. 其中 style app – 預設style App整合Facebook、Flicker、Google、Twitter、LinkedIn服務。個人覺得這類功能挺重要的. 畢竟我們沒有那麼多時間去關注那麼網站, 還是讓他們自己協調一下匯報上來就好! 有 AI 當然就更好. 但 Windows 能做到什麼程度, 我沒有報什麼期望.

好用的 Outlook 整理工具

因為屢次 sync 通訊錄的關係, 我在 Outlook 裡面的行事曆或是通訊錄變成有好多重複的備份. 這種東西雖然害處不是很大, 但是既浪費硬碟空間, 看了也礙眼.

如果按照 Microsoft 官網上推薦的方法, 是可以一筆一筆地刪掉. 不過正常人應該都不會這麼做.

幸好, 還是有聰明的免費工具可以選擇. 我找到一個 VAitA 出品的 Outlook Duplicate Item Remover.  安裝它之後, 它在 Outlook 裡面會產生一個 ODIR 的按鍵. 點選此鍵, 會跳出一個應用程式, 我們就用它刪除各種重複的項目, 包括行事曆, 信件, 聯絡人, 工作, 筆記等等.

比較遺憾的是它只有 Windows 版本, 所以得在 Microsoft Windows 的環境下把東西清乾淨, 再靠 exchange server 更新到 Mac 的 Outlook 上. 另外一個限制是 64 bits 的 Office 不適用此軟體.

新增 Linux User 小檔案

由於 Android 4.1 的編譯環境不再支持 32 bits 的 Linux, 一定要用 64 bits. 所以富士通的同事跑來要求加個 server 的帳號. 我想說只是加個帳號, 就順便替他處理一下. 想不到害他前後跑了三趟, 第一次是加帳號, 第二次是要開 Samba, 第三次是要加 sudoer; 既然三大革命應該一次完成, 我還是寫個 SOP 吧!

1. 加帳號

useradd USERNAME

增加一個和帳號同名 (USERNAME) 的目錄在 home 下面,

mkdir /home/USERNAME

把目錄指設定為帳號的 home 目錄.

useradd -d /home/USERNAME USERNAME

chgrp GROUP_NAME USERNAME

chown USERNAME USERNAME

passwd USERNAME, 接著依提示輸入密碼兩次.

2. 開 samba

smbpasswd -a USERNAME, 增加 samba user.

smbpasswd USERNAME, 接著依提示輸入密碼兩次.

3. 加 sudo

sudo 放在 /etc/sudoer, 它不能用普通的 vi 去編輯.

必須使用特殊指令 sudo visudo -f /etc/sudoers

在裡面增加一行

USERNAME ALL=(ALL) ALL NOPASSWD: ALL

紅色部分可以省略, 好處就是打 sudo 時不用輸入 password 了.

按 ^X 離開, 按 Y 確定, 跑出一個選項後, 再按 enter 確認.

修改既有 APK 的流程

如果從網路上抓到一個 APK, 又想要對它修改的話, 大約需要幾個步驟.

第一步是抓 APK TOOL 或是 APK Manger 回來. 雖然他們都有 Windows 版本, 但是用起來和 MS-DOS 差不多, 並沒有方便的視窗可以操作. 原本聽說 APK Manager 很厲害, 但是選單也相對較複雜, 就沒有再研究了.

APK Tool 這一系列需要抓  apktool-1.0.0.tar.bz2 和 apktool-install-windows-2.1_r01-1.zip. 解開後得到一個apktool.jar 和 apktool. 雖然網路上說 apktool.jar 要 copy 到 c:windows, 但是實際上發現它只有放在 apktool 同一個目錄才找得到 (除非那個目錄就是 c:windows).

接著使用 apktool d ThisIsYourAPK.apk ThisIsYourDirectory

就可以把 APK 的內容解到 ThisIsYourDirectory. 下面可以看到 lib, res, smali 三個基本的目錄, 以及 AndroidManifest.xml.

若是直接把 .apk 重新命名成 .zip 後解壓縮 (unzip) , 同樣也會看到 lib, res, 與 AndroidManifest.xml. 但可能會多出 METAINF  目錄, 與 resources.arsc, 與 classes.dex 兩個檔案. 其中 classes.dex 可以再依序反組譯為 class → jar → java.  對應到 apktool 生出的 smali.

上面兩種方式獲得的結果不同, 特別可以從 AndroidManifest.xml 看出來. 由於 APK 是給 DVM 看的格式, 所以這個檔案已經變得不可讀了. 當然, 它可以再用工具將它還原 Android: 反編譯 Android APK 文件. 一路用工具把 APK 裡面的各個 binary 還原回 source code 也是一個方法.

若是使用 apktool, 反組譯後得到的 source 都是可讀, 包括. 比方說想把免費軟體裡面的廣告拿掉, 畫面從直的改橫的, 可以直接到 res/layout/main.xml 裡面去撈相關的定義來修改 – 一個 APK 反編譯利器 Apktool.

此外, 若是以 apktool 反組譯, 修改完了之後, 還可以用 apktool b ThisIsAAPK.apk  打包回 APK. 最後再加個簽名, 就變成正式的 APK. 如果是用 unzip 提出來的修改的, 要再打包成 APK 似乎比較麻煩.

如果得到的是一個已經打包好的 APK, 那麼重編 Android 系統時可以將它放在 device 的某層目錄下一起編譯. 在這個 APK 同層的目錄裡, 寫一個 Android.mk – android 編譯系統 makefile (Android.mk) 寫法. 就可以把 APK 編進系統裡面了.

雖然上面的那個連結的內容很多, 但是 Adroid.mk 裡面只要有下面幾個基本要素就夠了. 制式定義好的部分根本不用動. 

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ThisIsYourAPK
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX :=$(COMMON_ANDROID_PACKAGE_SUFFIX
include $(BUILD_PREBUILT)

如果像這樣寫了很多 APK, 上層目錄再加一個 Android.mk,  寫上這兩行即可.

include $(CLEAR_VARS)
include $(call all-makefiles-under, $(LOCAL_PATH))

寫完本篇之後, 忽然找到兩個厲害的網站, 順便記在這裡.

[1] [android反编译小结]apktool/ AXMLPrinter2.jar/ dex2jar.bat/ jd-gui/ Jodeclipse/ JadClipse

[2] 把玩"魔術師" — 認識、把玩 APK 檔