真的, 這真的很簡單, 只要兩個步驟

首先, 你要有兩個工具:

  • dex2jar
  • JD-GUI 或其他Java decompliler (這邊我用JD-GUI當範例)

步驟1: 拿dex2jar把apk或是dex轉成jar (裡面包含從dex轉譯過來的class file)

command > ./dex2jar.sh ~/SKeyTest.apk 

version:0.0.7.8-SNAPSHOT

5 [main] INFO pxb.android.dex2jar.v3.Main - dex2jar /Users/julianshen/SKeyTest.apk -> /Users/julianshen/SKeyTest.apk.dex2jar.jar

Done.

步驟2: 拿JD-GUI開啟/Users/julianshen/SKeyTest.apk.dex2jar.jar (轉出的檔名即是原始檔SKeyTest.apk加上dex2jar.jar)

結果就像這樣:

 

Android上有個很煩人的就是(尤其是某公司的手機), 如果畫面上有可以輸入的框, 預設會focus在那上面, 某些手機(或說某些公司的手機), 預設變成只要那邊取得focus, 就會跳出軟體鍵盤, 這對很多User來說, 會有點煩(要看場合啦)…..

要在code裡面把SIP預先藏起來的話, 要用這段code:

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

今天晚上的GTUG請來了Tony Chan講GB的新features, 不過, 這些內容其實大部分都已經在Android網站上看過很多次了, 提起不了啥興趣, 雖然是對StorageManager有點興趣, 但卻不在這次講的內容, 可見這東西真的並不是個完成品, 不足以拿出來推

唯一讓我有點感興趣的是Google Analytics for Android, 所以回來的時候在車上稍微研究了一下

目前這東西, 說起來有點陽春, 把user行為的tracking定義成兩個分類 - pageview和event

pageview這觀念感覺就是從Web上來的, 但mobile application其實也沒啥page, 硬要分的話, 可以拿Activity來當做一個page吧, 不過有很多user interaction是在同一個Activity發生, 所以這分類應該是拿來應用在追蹤使用者使用某大功能的頻率

既然pageview不能夠表示in-activity的互動行為, 其實還可以拿"event"來用, 可以把button click, gesture之類的當做event來記錄分析

不過, 對於pageview和event其實沒有很明確的分野, developer可以在任何時候任何地方使用這兩者記錄, 並沒有特別強制性(比如說只能在activity用pageview或是pageview只能每個activity記錄一次之類的), 所以要胡搞也可以啦 (不過那就失去意義了)

比較恐怖的功能是可以允許developer自定變數, 如果把使用者個人資訊一起送上去, 就不妙囉

這整個功能上還稍嫌陽春, 如果要tracking使用者的使用流程, 這樣的東西並沒辦法做到

這部份有被問了幾個問題, 回來後我稍微查了一下:

1. 使用權限問題: 要不要使用者先同意收集才可以使用? 很不幸的, 這一點似乎是developer自由心證了, 並沒有任何強制步驟是使用者同意後才可以使用, 雖然使用這lib必須在manifest加上兩個uses-permission:

<uses-permission android:name=“android.permission.INTERNET” />

<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE” />

但這兩個, 一個是存取Internet, 一個是存取網路狀態的, 完全跟Privacy無關

2. Tony提到, 在沒有網路的時候會先keep在local的database等有網路時在上傳資料, 我當時提的問題是, 是否會有background service來做這件事, 還是AP launch之後才會真正去檢查網路並重送, 是只會有一個background service來做這件事? 還是每個AP獨立, 我會想到這問題有兩點, 第一點是資料庫問題, 如果每個AP負責自己的, 那每個AP會有各自獨立的資料庫, 而不會統一管理, 第二個是background processes數量問題

在會中時沒得到啥答案, 所以我只好自己簡單的追了一下, 基本上, 這設計沒我想的複雜, 簡單很多, 沒任何background service, 只有一個AnalysticsReceiver但看起來是來處理com.android.vending.INSTALL_REFERRER而非Connectivity change

所以這問題的答案就是, 它其實只是一個AP內的thread來處理而已(應該是NetworkDispatcher的dispatcherThread)

而且tacking code是存於各個AP的data目錄下一個叫google_analytics.db資料庫內, 所以只要取得這資料庫就可以取得了

整個設計上應該可以再加強, 尤其是保護User privacy這部份, 不然有可能被告吧? 我認為比較好一點的設計應該是在Market那隻AP裡面放個service來負責上傳analytics的資料, 只要提供API給AP去呼叫這隻service就好, 這樣第一步可以透過Android permission的機制先卡第一關, 而且可以比較容易統一設計一個end user agreement的dialog, 當AP第一次使用的時候跳出來取得user同意, 此外, 亦可以自動在網路狀態從無到有時自動把未送出的資料送出, 而非一定要AP正在使用的時候

在Android Gingerbread引入了StorageManager這東西, 似乎是為了OBB(Opaque Binary Blobs)這功能而來的, 不過, 似乎是也還沒把tool含到SDK內, 也沒很詳細的說明文件, 所以看起來現在好像也沒啥人去用這個, 實際上試了一下, 最後還是有問題, 搞不好還有bug, 懶得繼續追下去了, 不過大致上理解怎來利用這東西

OBB是一個含有加過密的檔案系統的檔案, 唸起來頗繞口, 不過如果對Linux有點熟悉的話, 它是一個磁碟映像檔(image file), 最後會以loopback device的方式掛載入Android內(Android底層是Linux, 採用這種方式也不足為奇)

由於是加密過的, 所以, 應用程式可以把需要保密的內容放到這個檔內, 比如說私密的通訊資料庫啦, 或是見不得人的照片…(呃, 我講到哪去了)

要建立一個OBB的檔案需要幾個tool:

mkobb.sh

pdkdf2gen

obbtool

由於目前SDK好像還沒這幾個東西, 所以必須從aosp裡面去找, 前兩者是一組的, 要一起配合, 而且mkobb.sh只能在Linux底下跑, 如果你嘗試在Mac上跑(像我一樣), 是會失敗的 (不過想想, 目前沒支援Mac也很合理)

Linux下, 有幾個kernel module是一定必要被載入的

sudo modprobe cryptoloop

sudo modprobe twofish

sudo modprobe vfat

這樣你才可以建立一個被加密過的loopback file system image

執行的指令如下:

mkobb.sh -d obbdir -k password -o obbfile 

-d 後面那個obbdir可以改成任何一個存在的目錄, 建立好的obb檔會幫你含入所有這目錄裡面的檔案, -k 後面輸入加密的密碼, -o 後面加入輸出的檔名

執行後內容會如下:

最後一行裡的"5f88a3619e6544ef"這個salt很重要, 要抄下來, 之後會用到

接下來就要用obbtool加簽章了, obbtool用法如下:

加簽章: obbtool a -n com.yourcompany.app -v 1 obbtest.obb -s 5f88a3619e6544ef

移除: obbtool r ~/Dropbox/obbtest.obb

-n 後面是package name, 必須要跟你的應用程式的package name相同, -v 後面則是自定的版本, -s 後面接的就是剛剛做mkobb.sh後產生的salt了

這樣這個obb檔就完成了, 可以把它放到手機sdcard或其他地方讓你的程式存取

在程式內掛載obb的話就要用到StorageManager了:

不過目前, 我碰到的狀況就是, 明明state已經變成MOUNTED, 但我就是取不到mounted path, 怪怪的

其實這是一個沒啥用的技巧(至少我還想不出應用), 就是加上一個像是浮水印的東西在畫面上, 不管在哪都會出現的, 像是這樣:

因為這個image要讓他一直不會消失, 所以他並不會是一個Activity, 因為Activity會有他的生命週期, 離開後就沒了, 所以要透過WindowManager去加上這個ImageView, 而且加上View的動作必須要給Background service去處理(這樣也就可以去做一些變化, 或動畫之類的)

首先, 要建立一個Service, 要達成這目的也很簡單, 在onCreate加上:

WindowManager wm = (WindowManager) this

.getSystemService(Service.WINDOW_SERVICE);

ImageView logo = new ImageView(this);

logo.setImageResource(R.drawable.onepieceoverlay);

WindowManager.LayoutParams lparam = new WindowManager.LayoutParams(

WindowManager.LayoutParams.WRAP_CONTENT,

WindowManager.LayoutParams.WRAP_CONTENT,

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 0, PixelFormat.TRANSLUCENT);

lparam.gravity = Gravity.RIGHT | Gravity.TOP;

wm.addView(logo, lparam);

這樣就好了, 其實很簡單, 就是透過WindowManager在system overlay上加個view

但這樣還不會work, 因為少了一個permission, 所以必須在AndroidManifest裡面加上

<uses-permission android:name=“android.permission.SYSTEM_ALERT_WINDOW”></uses-permission>

這樣就好了

不過system overlay沒辦法接touch event, 所以這邊放的view真的只是拿來放好看的