我們用到的 API endpoint 只有一個,就是用來取得港鐵機場快綫、東涌綫、屯馬綫及將軍澳綫最多四班即將到站列車的抵達時間。車站清單我們會直接寫死在 app 裏面。API 的使用方法可以在資料一線通網站(香港政府 open data 的網站)內找到。這個 API 是不需要額外申請 API key,只是一個普通的 HTTP GET request,然後 response body 是一個 JSON object。
打開「數據字典」PDF 檔,可以找到各車站及行車綫的代碼和 response body JSON object 的說明。當中我們主要用到的 property 大致上是:
plat
月台編號time
時間(留意它的格式並非按照 ISO 8601)dest
目的地車站代碼seq
次序(我們要按照這個順序顯示班次)再看「港鐵實時列車服務資訊 API 規範文件」PDF 檔,它提供了幾個 HTTP response status code 的意義和一些 response body 例子。例如當事故發生時那個 API 會提供一段文字讓我們顯示。
一般而言,我們都不會直接用 Android SDK 入面的 org.json 套件(即是 JSONObject
那些 class)來將 API response 的 JSON 轉成 Java/Kotlin object。因為要為每個 property 逐個寫 code,費時失事,所以我們都會用其他 deserialization library 去做 JSON 和 Java/Kotlin object 轉換。
在使用那些 library 之前,我們要準備 API response JSON 對應的 Kotlin data class。那個 data class 基本上就是要跟 JSON object 的結構相同,即是 response 的那個 property 是 string 就要在 data class 開對應的 string property。另外,我們只對整個 response 入面的某幾個 property 感興趣,所以在準備 data class 只針對那幾個 property 而造,其餘的東西我們就略過。
下面就是完成後的 data class,最尾的 companion object 放了幾個 constant 方便之後處理。
data class EtaResponse(
/**
* system status code.
*/
val status: Int = STATUS_ERROR_OR_ALERT,
/**
* Alert message.
*/
val message: String = "",
/**
* URL for Special Train Services Arrangement case.
*/
val url: String = "",
/**
* Indicate if the train is delayed.
*/
val isDelay: String = IS_DELAY_FALSE,
val data: Map<String, Data> = emptyMap()
) {
data class Data(
/**
* Indicate the destinations of the train in the specific line (up trip).
*/
val up: List<Eta> = emptyList(),
/**
* Indicate the destinations of the train in the specific line (down trip).
*/
val down: List<Eta> = emptyList()
)
data class Eta(
/**
* Platform numbers for the departure / arrival train.
*/
val plat: String = "1",
/**
* Estimated arrival time (or departure time) of the train.
*/
val time: String = EMPTY_TIMESTAMP,
/**
* MTR Station Code in capital letters.
*/
val dest: String = "",
/**
* The sequence of the 4 upcoming trains.
*/
val seq: String = "0"
)
companion object {
const val EMPTY_TIMESTAMP = "-"
const val STATUS_NORMAL = 1
const val STATUS_ERROR_OR_ALERT = 0
const val IS_DELAY_TRUE = "Y"
const val IS_DELAY_FALSE = "N"
}
}
我們已經準備好 response 的 data class。下一篇我們會介紹不同的 JSON deserialization library 並且將 EtaResponse
加上 deserialization library 的 annotation。