Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
炎炎夏日學 Android 課程 - Part3: Android app 實作
Search
Johnny Sung
June 30, 2019
Programming
0
82
炎炎夏日學 Android 課程 - Part3: Android app 實作
炎炎夏日學 Android 課程 - Part3: Android app 實作
(Kotlin EveryWhere 活動)
Johnny Sung
June 30, 2019
Tweet
Share
More Decks by Johnny Sung
See All by Johnny Sung
用 Gemma 3 開放模型來解決企業難解的問題 @ COSCUP 2025
j796160836
0
11
[GDG Build with AI] 善用現代 AI 科技:打造專屬行銷工具箱 @ GDG Changhua 彰化
j796160836
0
18
Kubernetes 地端自建 v.s. GKE,哪個更適合你? @Devfest Taipei 2024
j796160836
0
55
地端自建 Kubernetes (K8s) 小宇宙 (On-premises Kubernetes) @ CNTUG 2024/11 Meetup #63
j796160836
0
41
[AI LLM] Gemma 初體驗 @ GDG Cloud Taipei Meetup #70
j796160836
0
38
ArgoCD 的雷 碰過的人就知道 @TSMC IT Community Meetup #4
j796160836
0
120
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
j796160836
0
83
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @ Devfest Taipei 2023
j796160836
0
250
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具
j796160836
0
47
Other Decks in Programming
See All in Programming
組織もソフトウェアも難しく考えない、もっとシンプルな考え方で設計する #phpconfuk
o0h
PRO
3
860
エンジニアに事業やプロダクトを理解してもらうためにやってること
murabayashi
0
130
GC25 Recap: The Code You Reviewed is Not the Code You Built / #newt_gophercon_tour
mazrean
0
140
Introducing RemoteCompose: break your UI out of the app sandbox.
camaelon
2
460
業務でAIを使いたい話
hnw
0
230
Register is more than clipboard
satorunooshie
1
390
Reactive Thinking with Signals and the Resource API
manfredsteyer
PRO
0
120
Bakuraku E2E Scenario Test System Architecture #bakuraku_qa_study
teyamagu
PRO
0
270
HTTPじゃ遅すぎる! SwitchBotを自作ハブで動かして学ぶBLE通信
occhi
0
190
CSC305 Lecture 12
javiergs
PRO
0
250
SwiftDataを使って10万件のデータを読み書きする
akidon0000
0
250
Inside of Swift Export
giginet
PRO
1
360
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
55
9.1k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
Mobile First: as difficult as doing things right
swwweet
225
10k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
The Invisible Side of Design
smashingmag
302
51k
Designing for Performance
lara
610
69k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Thoughts on Productivity
jonyablonski
72
4.9k
Statistics for Hackers
jakevdp
799
220k
Code Review Best Practice
trishagee
72
19k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.7k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
Transcript
炎炎夏⽇日學 Android Johnny Sung Part3: Android app 實作
Mobile device developer Johnny Sung https://fb.com/j796160836 https://blog.jks.coffee/ https://www.slideshare.net/j796160836 https://github.com/j796160836
⼩小試⾝身⼿手
震動 。
震動 <uses-permission android:name="android.permission.VIBRATE" /> val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(10) AndroidManifest.xml
震動 vibrator.vibrate(longArrayOf(80, 150, 80, 150, 80, 150), -1) vibrator.cancel()
None
休息⼀一下 ☕
軟體設計 • 企劃 • UI/UX 介⾯面設計(美術) • 程式 • 測試
所需材料 • 畫⾯面線框稿 (Wireframe) • API 接⼝口⽂文件 • 美術圖片
成功畫⾯面 載入中畫⾯面 錯誤畫⾯面
成功畫⾯面 載入中畫⾯面 錯誤畫⾯面 夕陽⼩小幫⼿手
成功畫⾯面 載入中畫⾯面 錯誤畫⾯面 夕陽⼩小幫⼿手
所需⼯工具 • Method Draw 線上編輯圖片⼯工具 https://editor.method.ac/ • App Icon Generator
線上 App icon 產⽣生⼯工具 https://appicon.co/ • JSON Editor Online 線上 JSON 編輯⼯工具 https://jsoneditoronline.org/
None
None
https://sunrise-sunset.org/api
22.604098, 120.3001811 K Square 經度 (Latitude) 緯度 (Longitude) 地址:806⾼高雄市前鎮區復興四路路 20
號 座標
None
None
None
https://api.sunrise-sunset.org/json?lat=22.604098&lng=120.3001811&date=today&formatted=0 今⽇日 K Square 夕陽時間
None
None
夕陽⼩小幫⼿手 使⽤用套件 • Gson 解析 JSON 資料 • OkHttp 網路路函式庫
• jDeferred 架構函式庫
dependencies { // ... implementation 'org.immutables:gson:2.7.1' implementation 'com.squareup.okhttp3:okhttp:3.12.0' implementation "org.jdeferred.v2:jdeferred-core:2.0.0-beta1"
implementation "org.jdeferred.v2:jdeferred-android:2.0.0-beta1" // ... } 加入套件參參考
None
None
None
None
class SunsetResponse { var results: SunsetResult? = null var status:
String? = null } class SunsetResult { var sunset: String? = null }
單元測試原則 • Arrange – 準備,準備輸入資料與期待值 • Act – 執⾏行行,執⾏行行測試對象 •
Assert – 驗證,驗證結果 3A 原則
class ExampleUnitTest { @Test fun addition_isCorrect() { // Arrange val
expected = 4 // Act val actual = 2 + 2 // Assert assertEquals(expected, actual) } } Arrange 準備 Act 執⾏行行 Aessrt 驗證
object SunsetDateUtil { val dateFormater = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.US) .apply {
timeZone = TimeZone.getTimeZone("UTC") } }
Arrange 準備 Act 執⾏行行 Aessrt 驗證 @Test fun testJSON() {
// Arrange val json = "{\"results\":{\"sunrise\":\"2019-06-28T21:17:03+00:00\",\"sunset\":\"2019-06-29T10:47:28+00:00\",\"solar_noon\": \"2019-06-29T04:02:16+00:00\",\"day_length\":48625,\"civil_twilight_begin\":\"2019-06-28T20:52:00+00:00\",\"civil_twilight_end\": \"2019-06-29T11:12:31+00:00\",\"nautical_twilight_begin\":\"2019-06-28T20:22:00+00:00\",\"nautical_twilight_end\": \"2019-06-29T11:42:31+00:00\",\"astronomical_twilight_begin\":\"2019-06-28T19:50:46+00:00\",\"astronomical_twilight_end\": \"2019-06-29T12:13:46+00:00\"},\"status\":\"OK\"}" val excepted = "2019-06-29T10:47:28+00:00" // Act val gson = Gson() val obj = gson.fromJson(json, SunsetResponse::class.java) // Assert Assert.assertEquals(excepted, obj.results?.sunset) } }
Arrange 準備 Act 執⾏行行 Aessrt 驗證 輸入的資料 期待成功的資料 class SunsetUnitTest
{ @Test fun testFormatter() { val sunsetTime = "2019-06-24T10:46:49+00:00" val expected = Date(1561373209000) val result = SunsetDateUtil.dateFormater.parse(sunsetTime) assertEquals(expected.time, result.time) } }
class NetworkManager { companion object { val instance: NetworkManager by
lazy { NetworkManager() } } val mainHandler = Handler(Looper.getMainLooper()) inline fun <reified T> requestAsync(request: Request, typeToken: Type): Promise<T, Exception, Double> { val okHttpClient = OkHttpClient() val gson = GsonBuilder().create() val deferred = DeferredObject<T, Exception, Double>() okHttpClient.newCall(request).promise().then { okhttpResponse -> val strResult = okhttpResponse.body()?.string() try { val result = gson.fromJson<T>(strResult, typeToken) if (okhttpResponse.isSuccessful) { mainHandler.post { deferred.resolve(result) } } else { mainHandler.post { deferred.reject(Exception(strResult)) } } } catch (e: Exception) { mainHandler.post { deferred.reject(e) } } }.fail { deferred.reject(it) } return deferred.promise() } } fun Call.promise(): Promise<Response, Exception, Double> { val deferred = DeferredObject<Response, Exception, Double>() this.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { deferred.resolve(response) } override fun onFailure(call: Call, e: IOException) { deferred.reject(e) } }) return deferred.promise() } 補檔案 NetworkManager.kt
https://github.com/jdeferred/jdeferred
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
object NetworkAPI { fun getSunsetDataAsync(): Promise<SunsetResponse, Exception, Double> { val
okhttpRequest = Request.Builder() .url("https://api.sunrise-sunset.org/json?lat=22.604098&lng=120.3001811&date=today&formatted=0") .method("GET", null) .build() val type = object : TypeToken<SunsetResponse>() {}.type return NetworkManager.instance.requestAsync(okhttpRequest, type) } }
https://square.github.io/okhttp/
None
完成了了!
Q & A
趕快去追夕陽吧
None