理由是去年初之前都是專心寫iOS
但最近還需要同時寫Web跟Android
導致我同時弄的東西太多
光看文件就沒空了
絕對不是因為之前沈迷D3
也絕對不是因為之前狂看冰與火之歌
也絕對不是因為下班後活動太多..... (踢飛..)
這篇是第一次拿Android來寫,就拿我最近遇到的小問題來做分享吧
情境是有些功能我們在開發版跟正式版會有不同的行為
這時候會是開發版用一套code
正式版需要另一套code
那需要怎麼做才可以用程式判斷出執行環境的差異呢?
首先因為Android是java-based的
並沒有像Objective-C有define來作選擇性編譯
而在Android的架構中也沒有明顯的development/release兩個版本的設計
我google了一下,比較類似的討論有
這篇stackoverflow的討論
當中我比較傾向是用Signature來去達到這個目標
因為只有這個是runtime可以分辨出差異,而且是程式中可以取得的
再來是我們發佈到google play (或是其他market)
應該都會用的是release key做簽署
所以只要能夠在runtime跟release key的signature做比較
就可以判斷執行環境是development或是production
有了這個方向,
先查到Android中取得Signature的方法如下
PackageInfo pkgInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES); for(Signature signature : pkgInfo.signatures) { System.out.println("cert: " + sigature.toCharsString()); }你只要把你的production的signature印出來,並且hardcode進你的code
之後你做個字串比對就可以判斷是不是production environment了。
但是你會發現印出來的字串很長,大概3-400個bye吧 (隨便估@@)
總覺得不是很精簡。
這時候假掰的個性又出現了
那就來個SHA-1 hash之後再base64吧~ \(^O^o)
其實這是Facebook Android SDK的key hash給的靈感 XD
方法是找到你用來簽署所用的keystore,對他下以下的指令 (以下為Mac環境為例)
keytool -exportcert -alias youralias -keystore yourkeystore.keystore | openssl sha1 -binary | openssl base64這時候你應該會印出一個類似下面這種字串
+YyPzaeOKYkleq9Rwtk7+Rett/o=
把這個hash放在code中,
並且加上以下代碼
private static final String SIG_HASH_PRODUCTION = "+YyPzaeOKYkleq9Rwtk7+Rett/o="; public boolean isProduction() { try { PackageInfo pkgInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES); for(Signature signature : pkgInfo.signatures) { String sigHash =getSignatureHash(signature); if(SIG_HASH_PRODUCTION.equals(sigHash)) { return true; } } }catch(Exception e){} return false; } public String getSignatureHash(Signature signature) { try { MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] hash = md.digest(signature.toByteArray()); String hashb64 = Base64.encodeToString(hash, Base64.NO_WRAP); return hashb64; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; }
如此一來,只要用給google play上架簽署的apk,
執行時期的
isProduction()
都會回傳的是true
如此你可以在任何程式去用這個Utility function判斷是否為production mode。
2013/2/4 Updated
上面的方法有一個缺點就是,預設是development。
比較好的方法還是預設市production mode,
因為避免"意外"發生而變成development mode。
而developement的key是在~/.android/debug.keystore
command如下
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64而程式中改成用debug has key做負面表列來判斷是否為production mode。
或是直接改成isDebugMode()