Parcelable & Intent extra

Android 如果想將自己寫的 data type 的 object 傳到其他 ActivityFragment 之類的地方的話,就要用 Parcelable 來做 serialization/deserialization。Parcelable 有點像 Java 本身的 Serializable,不過 Parcelable 是 Android SDK 內專為 Android 而特設的,所以會快過 Serializable

最近寫 Android app 時無意中發現 IntentgetParcelableExtra return 出來的 object 是會重用的。如果我有個 object 用 Parcelable intent extra 在 Activity A 傳去 Activity B,而在 Activity B 用 getParcelableExtra 取回這個 object 然後再改一下 object 的 field,之後返回 Activity A 再傳相同的 object 去 Activity B,用 getParcelableExtra 取回這個 object 是會取得先前在 Activity B 改動過的 object,而不是 Activity A 那個原本的 object。

所以如果打算會改動 getParcelableExtra 傳回的 object 的話,最好都是複製一個來改,不要直接改傳回的 object。如果是 Kotlin data object 的話,可以用 copy 這個 method。

另外,Kotlin 1.1.4 的 Android Extensions plugin 新增了 @Parcelize annotation 來自動生成 Parcelable 相關的 code。但它是實驗功能,還未有正式說明文檔。如果不想用實驗功能的話,可以用 PaperParcel 之類的 library。

SemVer

剛剛為了方便做 force update app 功能的版本號碼比對就寫了一個 Semantic Versioning (SemVer) 的 Kotlin data class。這個 class 有 implement Comparable,是參照 SemVer 規範要比對 major、minor、patch 和 pre-release version,但 equals 就會再比對 build metadata(即是 Kotlin data class 的預設做法)。

Read More

Kotlin for Android

在四月開始轉用 Kotlin 來寫自己的 Android app。其實上年八月左右已經留意到 Kotlin 這個 JVM 語言能在 Android app 開發時使用,不過那時因為沒有太多時間所以只是看了少許官方教學和一些外國網誌就作罷,沒有真正拿來寫 Android app。到了最近看到愈來愈多人開始轉用 Kotlin 所以才真正開始轉用。到了現在 Kotlin 更成為 Android first-class support language。

初初轉用時都有些地方不明白,需要經常查閱文檔和 Google 例子。但其實 Kotlin 都不算太難學,syntax 上和 Java 有不同但差異不算太大,再加上一些當代語言常見的特性。所以如果本身有學過其他語言的話會很快上手。Kotlin 誕生的原因是 JetBrains 用 Java 開發 IDE 時發現到 Java 的不足而令他們決心做一個新的語言,所以骨子裏有着 Java 的影子,而 Kotlin 本身都是 JVM language(即是 Kotlin 原碼會變成 JVM bytecode 然後用 JVM 來執行)。現在 Kotlin 除了 compile 成 JVM bytecode 之外,還可以轉換成 JavaScript 和 native(即是直接在作業系統上執行,不需要 JVM/Node)。

Read More

Timber live template for Java/Kotlin

最近轉了用 Kotlin 來寫自己的 Android app,但發現 Android Studio 在 Kotlin 檔案內無法使用 Logcat logdlogm 之類的 Live templateAnkoAnkoLogger 因為用了 Log.isLoggable) 來包住 Log.d 之類的 method 所以在開發時看 log 不夠方便。於是就轉了用 Timber 來做 logging。但是轉了 logging library 都是沒有方便的方法來產生 log message。所以最後我參考了 Android Studio 的 log live template 來做了適用於 Java 和 Kotlin 的 Timber live template。

Live template 示範

Live template 我已經放到 Gist,是兩個 XML 檔來的。一個是 Java 版一個是 Kotlin 版。大致上和原裝的 live template 相似,只是將 log 改成 tim。例如 timd 會生成 Timber.d。安裝方法可以參考 Sharing Live Templates 一文。

Android 隱藏 signing config

其實官方網站有介紹過做法,不過就令到 build 那時一定要有 keystore.properties,否則就不能 build。部分 CI 可能會針對 Android 會提供專門的方式來設定 release keystore 和密碼。而在 VCS checkout source code 後在 file system 補上 keystore.properties 和 keystore 未必可以在 CI 環境上做到。所以我將那個教學稍作改動,令到當 keystore.properties 不存在時就不提供 signing config,使它能 build 未加簽的 apk,然後才讓 CI 加簽 apk。

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
apply plugin: 'com.android.application'
// Release signing properties
def keystorePropertiesFile = rootProject.file("keystore.properties");
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.example.helloworld"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
signingConfigs {
debug {
storeFile file("../app/debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
if (keystorePropertiesFile.exists()) {
release {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
}
buildTypes {
debug {
debuggable true
minifyEnabled false
signingConfig signingConfigs.debug
}
release {
minifyEnabled true
shrinkResources true
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
}
dependencies {
// ...
}
keystore.properties
1
2
3
4
storeFile = ../app/release.keystore
storePassword = mypassword
keyAlias = myalias
keyPassword = mypassword

Spek

之前一直都有留意 Kotlin 這個程式語言在 Android app 開發的應用。最近試用 Spek 來做 Android project 的 local test。Spek 是一個用 Kotlin 寫的 testing framework,用法和 Ruby 的 RSpec 差不多。對比 Android project 預設用的 JUnit 4,Spek 的寫法會比較清楚。因為 JUnit 4 只靠 class 和method 來為 test 分類,不能 nested(JUnit 5 才支援)。Spek 就用 nested 的方式來把 test 分類,還有就是用 string 來定義 test 名,比起 JUnit 4 用 method 名較易閱讀。

Spek 有提供 IntelliJ IDEA/Android Studio plugin,而且還有 JUnit platform engine。所以在 Android project 上面使用都沒有太大問題。

Read More

小米藍牙手柄

之前提及過只需要在 Windows 安裝 mapper 就能將小米藍牙手柄模擬成 Xbox 360 手掣,試過之後確實可以用到。在 The Crew 可以用手掣操作,在刹掣時手掣還會震動,比起在 Android 用功能還多。

除了 desktop game 之外,原來 HTML5 有 Gamepad API。我特別在 HTML5 Gamepad Tester 試了一次(未有用 Xbox mapper)。

  • Vendor ID: 2717
  • Product ID: 3144

其他按鍵的 keycode 可以看下面的影片:

小米盒子國際版開箱

小米盒子相信大家都聽過,亦都可能用過。不過這次小米香港推出的是「國際版」,用的是包含 Google Services 的 Android TV 而不是客製化的 Android。這個就是國際版和中國版的最大分別,這亦都是應否購買小米盒子國際版的主要考慮因素。

小米盒子國際版

Read More

nodetree 和 jazzy

這次想介紹兩個 documentation 相關的工具﹔nodetreejazzy

nodetree 是用來生成 ASCII 樹狀目錄結構圖。先前一篇有關 iOS 的文章就是用 nodetree 生成相關的樹狀目錄結構圖。它的用法非常簡單,只需要輸入 nodetree 指令就能印出目前目錄的結構。

而 jazzy 就是一個 Swift 和 Objective-C 的文檔生成器。它和 Java 的 JavaDoc 功能相近,都是按照源碼檔案中以特定格式輸入的註解來生成 HTML 網頁。如果是 Objective-C 的話,註解形式和 JavaDoc 相近。而生成出來的 HTML 網頁外觀和 Apple 官方的 API documentation 非常相似。如果不喜歡的話還可以自訂範本。