SlideShare una empresa de Scribd logo
1 de 68
Tim
About Me
● NCTU AM96
● Android GDE
● Software Engineer in Amazon
● Android 十全大補
● Kotlin 全面啟動
● https://github.com/Jintin
● https://medium.com/@jintin
● https://www.facebook.com/jintinlin
Android
Android
● Start from 2008
● Android 13 this year
● App normally written in Java / Kotlin
● Mostly in Phone, but also TV, car & watch
● App can also run in Windows 11, Chromebook
Android Versions
Historical Versions
Recent Versions
Kotlin
Kotlin
● Build by JetBrain
● Modern programing language
● Multi-platform
○ JVM, JS, Native ...
● Statically typed OOP with lot’s FP feature
● Rank 23 in TIOBE DEC 2022
Kotlin
● 100% compatible with Java
● No NPE (Null Pointer Exception)
● Less code to write, high productivity
Kotlin vs Java
Kotlin & Android
● Kotlin first in Google I/O 2019
● Lot’s of KTX extension lib
● Highly integrate Kotlin feature like Coroutine, Flow
Basic syntax
var a: String = "test"
Type Omit
var a = "test"
Immutable
var a = "a"
val b = "b"
a = "new a"
b = "new b" //Error
Optional
var a: String?
var b: String
a = null
b = null //Error
Optional Chaining
var a: String? = null
val b: Int? = a?.substring(7)?.length
val c: Int = a?.substring(7)?.length ?: 0
val d: Int = a?.substring(7)?.length!!
Function
fun sum(a: Int, b: Int): Int {
a + b
}
Function
fun sum(a: Int, b: Int): Int =
a + b
Function
fun sum(a: Int, b: Int) = a + b
Lambda
val sum: (Int, Int) -> Int = {
a, b ->
a + b
}
Lambda
val sum = { a: Int, b: Int ->
a + b
}
interface Animal {
fun walk()
}
class Cat(val age: Int) : Animal {
override fun walk() {
println("cat walk")
}
}
Class
data class Cat(
val age: Int,
val color: String,
)
Data Class
Extension Function
fun Cat.fly() {
println("Now I can fly")
}
Collection
val list = listOf("a", "b", "c")
val set = mutableSetOf(1, 3, 4)
val map = mapOf<String, Any>(
"a" to 1,
"b" to "test",
"c" to false
)
Functional Operation
listOf(1, 2, 3, 4, 5)
.filter { it % 2 == 1 }
.map { it * 2 }
.forEach {
println(it)// 2, 6, 10
}
Playground
https://play.kotlinlang.org
How to write Android Apps
● Java / Kotlin
● Android Studio
Android Studio
● Android IDE base on IntelliJ IDEA
○ IntelliJ IDEA is built by JetBrain, who built Kotlin
● Include full functionality we need
○ Build / Debug / Profile / Logging
○ Android SDK / Emulator management
○ Layout Preview / Inspect
● https://developer.android.com/studio
New Project Template
New Project Template
Project Structure
Project Structure
Demo
Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
textView.text = "some text"
}
}
Layout XML
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Activity
● Minimal Unit to display View/Page
● Need register in AndroidManifest.xml
● Launched by Intent
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jintin.myapplication">
<application
android:label="@string/app_name"
android:theme="@style/Theme.MyApplication">
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Intent
Android System
App 1
Activity A Activity B
App 2
Activity A’ Activity B’
Intent
Launch Intent
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<TextView>(R.id.textView)
button.setOnClickListener {
startActivity(Intent(this, MainActivity::class.java))
}
}
}
Back Stack
Stack
Activity A
Stack
Activity A
Activity B
Stack Stack
Activity A
Activity A
Activity A
Demo
Lifecycle
onCreate
onStart
onResume
onDestroy
onStop
onPause
Running
Visible
RecyclerView
● List / Grid View that display huge data set
● Reuse when View is out of screen
RecyclerView.Adapter
● Adapt Data to View in RecyclerView
● Place to create ViewHolder
Add Dependency
dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1"
}
Structure
RecyclerView
Adapter
ViewHolder 1
View
ViewHolder 2
View
ViewHolder 3
View
Adapter
class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): MyViewHolder
override fun getItemCount(): Int
override fun onBindViewHolder(
holder: MyViewHolder,
position: Int)
}
ViewHolder
class MyViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun bind(data: Int) {
//TODO
}
}
LayoutManager
● Handle how to layout each View inside RecyclerView
● Can be Linear, Grid, or Custom
LayoutManager
recyclerView.layoutManager =
LinearLayoutManager(
this,
LinearLayoutManager.VERTICAL,
false
)
Demo
Retrofit
● Handle Api request
● Use dynamic proxy to generate implementation in runtime
● https://github.com/square/retrofit
Add Dependency
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}
Model
data class Repo(
val id: Int,
val name: String,
val owner: User
)
data class User(
val id: Int,
@SerializedName("avatar_url")
val avatarUrl: String
)
Api Class
interface GitHubService {
@GET("users/{user}/repos")
fun listRepos(
@Path("user") user: String,
@Query("type") type: String? = null,
@Query("sort") sort: String? = null
): Call<List<Repo>>
}
Generate Instance
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(GitHubService::class.java)
Usage
service.listRepos("Jintin")
.enqueue(object : Callback<List<Repo>> {
override fun onFailure(call: Call<List<Repo>>, t:
Throwable) {
// network fail
}
override fun onResponse(call: Call<List<Repo>>,
response: Response<List<Repo>>) {
if (response.isSuccessful) {
// success
} else {
// application level fail
}
}
})
Demo
Things not cover yet
● UI: ViewBinding, DataBinding, Compose
● Storage: File, DataBase, Room
● Architecture: MVVM, ViewMoel, LiveData
● RxJava, Coroutine, Flow
● DI: Dagger, Hilt, Koin
● Test: Mockito, MockK, Espresso
● Automation: CI, CD, Jenkins
Resources - Official Site
● Android Developer
● https://developer.android.com/
● Kotlin
● https://kotlinlang.org/
● Basic Android in Kotlin
● https://developer.android.com/courses/android-basics-
kotlin/course
Resources - FB Group
● Android Taipei 開發者社群
● https://www.facebook.com/groups/382275241893545
● Android Developer開發讀書會
● https://www.facebook.com/groups/523386591081376
● Taiwan Kotlin User Group 討論區
● https://www.facebook.com/groups/725458374837125
● Kotlin Taipei
● https://www.facebook.com/groups/117755722221972
Resources - Blog
● Android Weekly
● https://androidweekly.net/
● Kotlin Weekly
● http://www.kotlinweekly.net/
● Android Developer Medium
● https://medium.com/androiddevelopers
● ProAndroidDev
● https://proandroiddev.com/
Resources - Conference
● DroidCon
● https://www.droidcon.com/
● Coscup
● https://coscup.org/
● Mopcon
● https://mopcon.org/
● JCConf
● https://jcconf.tw/
Q&A

Más contenido relacionado

Similar a 從零開始學 Android

Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
Yekmer Simsek
 
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon Berlin
 
Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
Lei Kang
 
ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013
Mathias Seguy
 
OWF12/PAUG Conf Days Pro guard optimizer and obfuscator for android, eric l...
OWF12/PAUG Conf Days Pro guard   optimizer and obfuscator for android, eric l...OWF12/PAUG Conf Days Pro guard   optimizer and obfuscator for android, eric l...
OWF12/PAUG Conf Days Pro guard optimizer and obfuscator for android, eric l...
Paris Open Source Summit
 

Similar a 從零開始學 Android (20)

Practical tips for building apps with kotlin
Practical tips for building apps with kotlinPractical tips for building apps with kotlin
Practical tips for building apps with kotlin
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android development
 
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
 
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
 
Why kotlininandroid
Why kotlininandroidWhy kotlininandroid
Why kotlininandroid
 
Design Summit - UI Roadmap - Dan Clarizio, Martin Povolny
Design Summit - UI Roadmap - Dan Clarizio, Martin PovolnyDesign Summit - UI Roadmap - Dan Clarizio, Martin Povolny
Design Summit - UI Roadmap - Dan Clarizio, Martin Povolny
 
Javascript as a target language - GWT KickOff - Part 2/2
Javascript as a target language - GWT KickOff - Part 2/2Javascript as a target language - GWT KickOff - Part 2/2
Javascript as a target language - GWT KickOff - Part 2/2
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Testing of javacript
Testing of javacriptTesting of javacript
Testing of javacript
 
Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
 
Developer Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for BeginnersDeveloper Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for Beginners
 
JSAnkara Swift v React Native
JSAnkara Swift v React NativeJSAnkara Swift v React Native
JSAnkara Swift v React Native
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15
 
Introduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google CloudIntroduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google Cloud
 
Griffon Presentation
Griffon PresentationGriffon Presentation
Griffon Presentation
 
ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013ProTips DroidCon Paris 2013
ProTips DroidCon Paris 2013
 
OWF12/PAUG Conf Days Pro guard optimizer and obfuscator for android, eric l...
OWF12/PAUG Conf Days Pro guard   optimizer and obfuscator for android, eric l...OWF12/PAUG Conf Days Pro guard   optimizer and obfuscator for android, eric l...
OWF12/PAUG Conf Days Pro guard optimizer and obfuscator for android, eric l...
 
Unity3D Plugins Development Guide
Unity3D Plugins Development GuideUnity3D Plugins Development Guide
Unity3D Plugins Development Guide
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 

Más de National Yang Ming Chiao Tung University

AI/ML O-RAN Cloud-Native Automation
AI/ML O-RAN Cloud-Native AutomationAI/ML O-RAN Cloud-Native Automation
AI/ML O-RAN Cloud-Native Automation
National Yang Ming Chiao Tung University
 
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
National Yang Ming Chiao Tung University
 

Más de National Yang Ming Chiao Tung University (20)

GDSC CTU First Meeting Party
GDSC CTU First Meeting PartyGDSC CTU First Meeting Party
GDSC CTU First Meeting Party
 
The Cloud-Native Solution of Integrate Satellite Ground Station System and Te...
The Cloud-Native Solution of Integrate Satellite Ground Station System and Te...The Cloud-Native Solution of Integrate Satellite Ground Station System and Te...
The Cloud-Native Solution of Integrate Satellite Ground Station System and Te...
 
AI/ML O-RAN Cloud-Native Automation
AI/ML O-RAN Cloud-Native AutomationAI/ML O-RAN Cloud-Native Automation
AI/ML O-RAN Cloud-Native Automation
 
從 Taker 成為 Giver!偏鄉學生也能成為開源貢獻者!
從 Taker 成為 Giver!偏鄉學生也能成為開源貢獻者!從 Taker 成為 Giver!偏鄉學生也能成為開源貢獻者!
從 Taker 成為 Giver!偏鄉學生也能成為開源貢獻者!
 
什麼是Nephio?
什麼是Nephio?什麼是Nephio?
什麼是Nephio?
 
Google IO Extended 2023 Hsinchu開場
Google IO Extended 2023 Hsinchu開場Google IO Extended 2023 Hsinchu開場
Google IO Extended 2023 Hsinchu開場
 
Case Studied on Federated learning Deployment in O-RAN
Case Studied on Federated learning Deployment in O-RANCase Studied on Federated learning Deployment in O-RAN
Case Studied on Federated learning Deployment in O-RAN
 
跟著 AI 學 Angular:活用 AI 讓你輕鬆快速掌握任何知識
跟著 AI 學 Angular:活用 AI 讓你輕鬆快速掌握任何知識跟著 AI 學 Angular:活用 AI 讓你輕鬆快速掌握任何知識
跟著 AI 學 Angular:活用 AI 讓你輕鬆快速掌握任何知識
 
Flutter實作概述 | GDSC NYCU
Flutter實作概述 | GDSC NYCUFlutter實作概述 | GDSC NYCU
Flutter實作概述 | GDSC NYCU
 
陽明交大 百川學程 服務學習二 專業服務企畫案-期末論壇 簡報
陽明交大 百川學程 服務學習二 專業服務企畫案-期末論壇 簡報陽明交大 百川學程 服務學習二 專業服務企畫案-期末論壇 簡報
陽明交大 百川學程 服務學習二 專業服務企畫案-期末論壇 簡報
 
找到你的為什麼,革自己的命 | 偏鄉教育 | 蔡秀吉
找到你的為什麼,革自己的命 | 偏鄉教育 | 蔡秀吉找到你的為什麼,革自己的命 | 偏鄉教育 | 蔡秀吉
找到你的為什麼,革自己的命 | 偏鄉教育 | 蔡秀吉
 
Flutter實作概述 | GDSC NYCU
Flutter實作概述 | GDSC NYCUFlutter實作概述 | GDSC NYCU
Flutter實作概述 | GDSC NYCU
 
Firebase 基礎上手 |2小時由入門到精通 | GDSC NYCU
 Firebase 基礎上手 |2小時由入門到精通 | GDSC NYCU Firebase 基礎上手 |2小時由入門到精通 | GDSC NYCU
Firebase 基礎上手 |2小時由入門到精通 | GDSC NYCU
 
GDSC NYCU下學期社員大會
GDSC NYCU下學期社員大會GDSC NYCU下學期社員大會
GDSC NYCU下學期社員大會
 
The Development and Prospect of Deploying Cloud-Native O-RAN.pdf
The Development and Prospect of Deploying Cloud-Native O-RAN.pdfThe Development and Prospect of Deploying Cloud-Native O-RAN.pdf
The Development and Prospect of Deploying Cloud-Native O-RAN.pdf
 
部屬雲原生O-RAN架構的發展與展望
部屬雲原生O-RAN架構的發展與展望部屬雲原生O-RAN架構的發展與展望
部屬雲原生O-RAN架構的發展與展望
 
Young飛全球行動計畫 ppt 年度成果簡報
Young飛全球行動計畫 ppt 年度成果簡報Young飛全球行動計畫 ppt 年度成果簡報
Young飛全球行動計畫 ppt 年度成果簡報
 
World Engineering Day Hackathon 2023
World Engineering Day Hackathon 2023World Engineering Day Hackathon 2023
World Engineering Day Hackathon 2023
 
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
陽明學生會 陽明校區無線通訊品質問題-初步進度報告書
 
博雅書苑 社教中心 Active Learning 自主學習計畫說明會 -蔡秀吉經驗分享簡報
博雅書苑 社教中心 Active Learning 自主學習計畫說明會 -蔡秀吉經驗分享簡報博雅書苑 社教中心 Active Learning 自主學習計畫說明會 -蔡秀吉經驗分享簡報
博雅書苑 社教中心 Active Learning 自主學習計畫說明會 -蔡秀吉經驗分享簡報
 

Último

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Último (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

從零開始學 Android