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
80
炎炎夏日學 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
[GDG Build with AI] 善用現代 AI 科技:打造專屬行銷工具箱 @ GDG Changhua 彰化
j796160836
0
15
Kubernetes 地端自建 v.s. GKE,哪個更適合你? @Devfest Taipei 2024
j796160836
0
45
地端自建 Kubernetes (K8s) 小宇宙 (On-premises Kubernetes) @ CNTUG 2024/11 Meetup #63
j796160836
0
32
[AI LLM] Gemma 初體驗 @ GDG Cloud Taipei Meetup #70
j796160836
0
27
ArgoCD 的雷 碰過的人就知道 @TSMC IT Community Meetup #4
j796160836
0
88
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
j796160836
0
74
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @ Devfest Taipei 2023
j796160836
0
210
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具
j796160836
0
38
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
j796160836
0
63
Other Decks in Programming
See All in Programming
GPUを計算資源として使おう!
primenumber
1
190
Advanced Micro Frontends: Multi Version/ Framework Scenarios @WAD 2025, Berlin
manfredsteyer
PRO
0
340
Git Sync を超える!OSS で実現する CDK Pull 型デプロイ / Deploying CDK with PipeCD in Pull-style
tkikuc
3
160
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
270
코딩 에이전트 체크리스트: Claude Code ver.
nacyot
0
850
TypeScriptでDXを上げろ! Hono編
yusukebe
3
480
「テストは愚直&&網羅的に書くほどよい」という誤解 / Test Smarter, Not Harder
munetoshi
0
190
チームのテスト力を総合的に鍛えて品質、スピード、レジリエンスを共立させる/Testing approach that improves quality, speed, and resilience
goyoki
5
1k
The Modern View Layer Rails Deserves: A Vision For 2025 And Beyond @ RailsConf 2025, Philadelphia, PA
marcoroth
2
640
Rubyでやりたい駆動開発 / Ruby driven development
chobishiba
1
750
Porting a visionOS App to Android XR
akkeylab
0
640
ご注文の差分はこちらですか? 〜 AWS CDK のいろいろな差分検出と安全なデプロイ
konokenj
3
380
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
524
40k
Side Projects
sachag
455
42k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
Designing Experiences People Love
moore
142
24k
Balancing Empowerment & Direction
lara
1
440
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
How STYLIGHT went responsive
nonsquared
100
5.6k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Writing Fast Ruby
sferik
628
62k
Embracing the Ebb and Flow
colly
86
4.7k
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