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
用 Gemma 3 開放模型來解決企業難解的問題 @ COSCUP 2025
j796160836
0
0
[GDG Build with AI] 善用現代 AI 科技:打造專屬行銷工具箱 @ GDG Changhua 彰化
j796160836
0
16
Kubernetes 地端自建 v.s. GKE,哪個更適合你? @Devfest Taipei 2024
j796160836
0
49
地端自建 Kubernetes (K8s) 小宇宙 (On-premises Kubernetes) @ CNTUG 2024/11 Meetup #63
j796160836
0
36
[AI LLM] Gemma 初體驗 @ GDG Cloud Taipei Meetup #70
j796160836
0
34
ArgoCD 的雷 碰過的人就知道 @TSMC IT Community Meetup #4
j796160836
0
97
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
j796160836
0
77
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @ Devfest Taipei 2023
j796160836
0
220
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具
j796160836
0
41
Other Decks in Programming
See All in Programming
実践!App Intents対応
yuukiw00w
1
230
実践 Dev Containers × Claude Code
touyu
1
170
ワープロって実は計算機で
pepepper
2
1.2k
MCP連携で加速するAI駆動開発/mcp integration accelerates ai-driven-development
bpstudy
0
290
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
tnishinaga
2
1.9k
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
17
3.8k
Webinar: AI-Powered Development: Transformiere deinen Workflow mit Coding Tools und MCP Servern
danielsogl
0
110
What's new in Adaptive Android development
fornewid
0
140
大規模FlutterプロジェクトのCI実行時間を約8割削減した話
teamlab
PRO
0
460
あなたとJIT, 今すぐアセンブ ル
sisshiki1969
1
590
Google I/O Extended Incheon 2025 ~ What's new in Android development tools
pluu
1
250
QA x AIエコシステム段階構築作戦
osu
0
260
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
183
54k
Into the Great Unknown - MozCon
thekraken
40
2k
Git: the NoSQL Database
bkeepers
PRO
431
65k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
Being A Developer After 40
akosma
90
590k
Gamification - CAS2011
davidbonilla
81
5.4k
It's Worth the Effort
3n
185
28k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Agile that works and the tools we love
rasmusluckow
329
21k
Building a Modern Day E-commerce SEO Strategy
aleyda
43
7.4k
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