๐ SeSAC์ 'JetPack๊ณผ Kotlin์ ํ์ฉํ Android App ๊ฐ๋ฐ' ๊ฐ์ข๋ฅผ ์ ๋ฆฌํ ๊ธ ์ ๋๋ค.
์๋๋ก์ด๋ ๋ฒ์ ์ด ์ฌ๋ผ๊ฐ๋ฉด์ ์๋ ๋์ํ๋ ๊ฒ๋ค์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฝ
์ด๋ผ๋ ์ด์ ๋ก ๋ถ๊ฐ๋ฅํด์ง ๋ถ๋ถ์ด ์๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฝ์ด ์ด๋์ ๊ฐํด์ง ๊ฒ์ด๊ณ , ์ด๋ฅผ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ด ์๋์ง ์์๋ณด์.
์๋๋ก์ด๋ ์ฑ์ ์กํฐ๋นํฐ, ์๋น์ค, ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ, ์ปจํ ์ธ ํ๋ฌ๋ฐ์ด๋ ๋ก ๊ตฌ์ฑ
์กํฐ๋นํฐ๋ฅผ ์ ์ธํ๊ณ ํ๋ฉด๊ณผ ์๊ด์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ ์ ๋ชฉ์
์๋๋ก์ด๋๋ 4๊ฐ์ ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์๋น์ค
์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ
๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ด๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ, ์ด ๋ ๋ถ๋ถ์ ์ ์ฝ์ด ๊ฐํด์ก๋ค.
์์ ์๋ ์๋น์ค์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ๋ง๋ค์ด์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์ฅ์๊ฐ(ํ๋ฃจ์ข
์ผ) ๋๋ฆด ์ ์์๋ค. ๋ํ ๋ถํ
์ด ์๋ฃ๋๋ฉด ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ํตํด ์๋น์ค๋ฅผ ๋๋ฆด ์๋ ์์๋ค. ํ์ง๋ง ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฝ
์ ์ํด ์ด๊ฒ๋ค์ด ๋ถ๊ฐ๋ฅ ํด์ก๋ค.
์๋น์ค, ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ์ด์ฉํ์ฌ ์ฑ์ ํ๋ฉด์ด ์ถ๋ ฅ๋์ง ์์ ์ํฉ์์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅ
์๋๋ก์ด๋ 8 ๋ฒ์ (API Level 26) ๋ถํฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฝ
ํ๋ฉด์ ์ถ๋ ฅ๋์ง ์๋ ์์
(๋ฐฑ๊ทธ๋ผ์ด๋ ์์
)์ API 26
๋ถํฐ ์ ์ฝ์ด ๊ฑธ๋ ธ๋ค.
์ด์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ ๊ฒ๋ค์ด ๋ถ๊ฐ๋ฅํด์ง๊ธฐ ์์
์์คํ ์ด ๋ถํ ์ด ์๋ฃ๋์ ๋ง์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ์คํ ๊ฐ๋ฅ
์ด ์ํฉ์์ ์๋น์ค๋ฅผ ์คํ์์ผ ์ด๋ค ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์๋๋ก์ด๋ 8 ๋ฒ์ ๋ถํฐ ๋ถ๊ฐ๋ฅ
๋ํ์ ์ผ๋ก ๋ถํ
์๋ฃ ์ ์๋น์ค ๊ตฌ๋
์ ์ ์ฝ์ด ๊ฑธ๋ ธ๋ค. ์ฌ์ ํ ๋ถํ
์๋ฃ ์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ
๋ ์คํ์ํฌ ์ ์๋๋ฐ, ์ด ๋ฆฌ์๋ฒ๊ฐ ์๋น์ค
๋ฅผ ๊ตฌ๋์ํฌ ์ ์๊ฒ ๋์๋ค. ๋ฌผ๋ก ์กํฐ๋นํฐ
๋ ์ ์คํ๋๋ค.
์ด๋ฌํ ์ ์ฝ์ด ์๋น์ค
์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ
์ ๊ฐํด์ก๋ค.
๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ์คํ์ํค๊ธฐ ์ํด์๋ ์ธํ
ํธ๋ฅผ sendBroadcast()
ํจ์๋ก ๋ฐ์์ํจ๋ค.
๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ์์์ ์ธํ
ํธ
์ ์ํด ์คํ ์ํค๋ ๊ฒ ๊ธ์ง
๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ
์ ์ ์ฝ์ด ๊ฐํด์ง๊ธด ํ๋๋ฐ, ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ๋ฐ ์ฝ๋์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง๋ ์๋๋ค. ์ผ๋ง๋ ์ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ์คํ์ด ๊ฐ๋ฅํ๋ค๊ณ ํ๋ค.
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true>
<intent-filter>
<action android:name="ACTION_RECEIVER"/>
</intent-filter>
</receiver>
val intent = Intent("ACTION_RECEIVER")
sendBroadcast(intent)
Manifest ํ์ผ์ ๋ฆฌ์๋ฒ
+ ์ธํ
ํธ ํํฐ
๋ฅผ ๋ฑ๋กํ์ฌ ์์์ ์ธํ
ํธ๋ฅผ ๋ฐ๋ ์ํฉ์ด๋ค. ํด๋น ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ์คํ์ํค๊ณ ์ถ์ ๊ณณ์์ ์ธํ
ํธ ํํฐ์ ์ก์
๋ฌธ์์ด๋ก ์ธํ
ํธ๋ฅผ ๋ ๋ฆฌ๋ฉด ์คํ๋๋ค.
๊ทธ๋ฐ๋ฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ฝ
์ผ๋ก ์ธํด ์์์ ์ผ๋ก ์คํ์ด ๋ถ๊ฐ๋ฅํ๋ค. ์ด๋์์? ๋ด๋ถ์์.
A์ฑ๊ณผ B์ฑ์ด ์๋ค. B์ฑ์์ ์ธํ ํธ๋ฅผ ๋ ๋ ค A์ฑ์ ๋ฆฌ์๋ฒ๋ฅผ ์์์ ์ผ๋ก ์คํ์ํค๋ ๊ฑด ์ ๋๋ค. ํ์ง๋ง A์ฑ์์ ์์ ๋ด๋ถ์ ๋ฆฌ์๋ฒ๋ฅผ ์์์ ์ผ๋ก ์คํ์ํค๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๋ค.
์ฆ, ๋ณธ์ธ์ ๋ฆฌ์๋ฒ๋ ํด๋์ค ๋ช
์ ์์ฑํด์ ๋ช
์์ ์ธํ
ํธ๋ก ์คํ์ํค๋ผ๋ ์ ์ฝ์ด๋ค.
๋ด๋ถ ๋ฆฌ์๋ฒ์ ์์์ ์ธํ
ํธ๋ฅผ ๋ ๋ฆฌ๋ฉฐ ๋ก๊ทธ์ฐฝ์ ์๋์ ๊ฐ์ด ์๋ฌ๊ฐ ๋ฌ๋ค.
Background execution not allowed: receiving Intent { act=ACTION_RECEIVER flg=0x10 } to
com.example.test
AndroidManifest.xml ํ์ผ์ ๋ฑ๋ก๋ ๋ฆฌ์๋ฒ๋ฅผ ์์์ ์ธํ ํธ๋ก ์คํ์ํค๋ ๊ฒฝ์ฐ ๊ธ์ง
๋ช ์์ ์ผ๋ก ์คํ์ํค๋ ๊ฒ์ ๊ฐ๋ฅ
์ฝ๋์์ registerReceiver() ๋ก ๋ฑ๋ก์ํจ ๊ฒฝ์ฐ์๋ ์์์ ์ธํ ํธ์ ์คํ ๊ฐ๋ฅ
// ์ฝ๋๋ก ๋์ ๋ฑ๋ก
receiver = object : BroadcastReceiver() {
override fun onReceiver(context: Context?, intent: Intent?) {
Log.d("kotdev", "outer app dynamic receiver......")
}
}
// ์ธํ
ํธ ํํฐ
registerReceiver(receiver, IntentFilter("ACTION_OUTER_DYNAMIC_RECEIVER"))
๊ทธ๋ฐ๋ฐ ์ฝ๋์์ ๋์ ๋ฑ๋กํ๋ ์ํฉ์ด๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น? ๋์ ๋ฑ๋ก ์์๋ ํด๋์ค๋ช ์ด ์๋ ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํ๊ธฐ ๋๋ฌธ์ ์คํ ์กฐ๊ฑด์ผ๋ก ์ธํ ํธ ํํฐ๋ฅผ ์ค ์ ๋ฐ์ ์๋ค.
๊ทผ๋ฐ ์๋ฌด๋ฐ ๊ฑฑ์ ํ ํ์ ์๋ค. registerReceiver()
ํจ์๋ก ๋์ ๋ฑ๋ก๋ ๋ฆฌ์๋ฒ๋ ์์์ ์ธํ
ํธ๋ก ์คํ์ด ๋๋ค.
์ฆ, ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ ๊ด๋ จํด์ ๊ฐํด์ง ์ ์ฝ์ Manifest ์ ์ ์ ๋ฑ๋ก๋ ๊ฒฝ์ฐ
๋ง ํด๋น๋๋ค.
๊ทธ๋์ ๊ทธ๋ฅ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ์ ์์ ๋ ์๋น์ค๋ฅผ ์คํ์ํค๊ธฐ ์ํด์ ์ธํ ํธ๋ฅผ ๋ฐ์์ํค๋ฉด ์๋ฌ ๋ฐ์
์ฑ์ด ํฌ๊ทธ๋ผ์ด๋ ์ํฉ์ด๋ผ๋ฉด ์ ์ ์คํ
Not allowed to start service Intent { act=ACTION_OUTER_SERVICE pkg=com.example.test }: app is in background uid null
์ฑ์ ํ๋ฉด์ด ์ถ๋ ฅ๋์ง ์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ์ผ ๋ ์๋น์ค ๊ตฌ๋ ์ ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋จ์ด์ง๋ค.
์๋๋ค. ํฌ๊ทธ๋ผ์ด๋๋ผ๊ณ ๋ณด๋ ์ํฉ์ด ๋ช ๊ฐ์ง ์๋ค. ๋๋ฌธ์ ํ๋ฉด์ด ์ ๋์จ๋ค๊ณ ๋ฌด์กฐ๊ฑด ๋ฐฑ๊ทธ๋ผ์ด๋๊ฐ ์๋๋ค.
1. Activity ๊ฐ ์์๋๊ฑฐ๋ ์ผ์ ์ค์ง๋๊ฑฐ๋ ์๊ด์์ด ๋ณด์ด๋ Activity ๊ฐ ์๋ ๊ฒฝ์ฐ
2. ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค๊ฐ ์๋ ๊ฒฝ์ฐ
3. ์ฑ์ ์๋น์ค ์ค ํ๋์ ๋ฐ์ธ๋ํ๊ฑฐ๋ ์ฑ์ ์ฝํ
์ธ ํ๋ฌ๋ฐ์ด๋ ์ค
ํ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ์ ๋ ๋ค๋ฅธ ํฌ๊ทธ๋ผ์ด๋ ์ฑ์ด ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ
1. ์ฐ์ ์์๊ฐ ๋์ Firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง(FCM) ๋ฉ์์ง ์ฒ๋ฆฌ
2. SMS/MMS ๋ฉ์์ง์ ๊ฐ์ ๋ธ๋ก๋์บ์คํธ ์์
3. ์๋ฆผ์์ PendingIntent ์คํ
4. VPN ์ฑ์ด ํฌ๊ทธ๋ผ์ด๋๋ก ์น๊ฒฉ๋๊ธฐ ์ ์ VpnService ์์
์ฆ, ์ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์ฌ๋ ์์ ์ ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅธ ๊ณณ์ ๋ฟ๋ ค์ง๋ ์ํฉ์ด๋ผ๋ฉด ํฌ๊ทธ๋ผ์ด๋ ์ทจ๊ธํด ์ค๋ค.
๋ฐฑ๊ทธ๋ผ์ด๋ ์ํฉ์์ ์๋น์ค๊ฐ ์ ์ ์คํ๋๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ
startForegroundService()
ํจ์์ ์ํด ์ธํ
ํธ๋ฅผ ๋ฐ์ ์ํค๋ฉด ์ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํฉ์ด๋ผ๊ณ ํ๋๋ผ๋ ์ ์์ ์ผ๋ก ์๋น์ค๊ฐ ์คํ
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
๋ถํ ์ด ์๋ฃ๋ ์๊ฐ์ ์ฑ์ด ๋ช ๋ฐฑํ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ์ธ ์๊ฐ์ด๋ค. ๋ถํ ์๋ฃ ์ ๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๋ ์๋ง ์คํ๋๋ค. ํ์ง๋ง ์ด ๋ฆฌ์๋ฒ๊ฐ ์ฑ์ ์๋น์ค๋ฅผ ๊ตฌ๋ํ๋ ์๊ฐ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
โ ํ์ง๋ง startForegroundService()
ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์๋น์ค๋ฅผ ์คํ์ํฌ ์๊ฐ ์๋ค. (์กฐ๊ฑด์ด ์์ง๋ง)
Context.startForegroundService() did not then call Service.startForeground()
startForegroundService()
๋ก ๊ตฌ๋๋ ์๋น์ค๋ ์์ฃผ ๋น ๋ฅธ ์๊ฐ ๋ด์ ๋ฌด์ธ๊ฐ๋ฅผ ๋์ ์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋ฌ์ง ์์ผ๋ฉด ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
๋ธ๋ก๋์บ์คํธ ๋ฆฌ์๋ฒ๊ฐ ์ธํ
ํธ๋ก ์๋น์ค๋ฅผ ์ ์ ๊ตฌ๋์ํฌ ์๋ ์๋ค. ๊ทธ๋ฐ๋ฐ ์๋น์ค๊ฐ ๊ตฌ๋๋์ ๋ง์ startForeground()
ํจ์๋ฅผ ์ฝ ํด์ฃผ์ด ํ๋ค.
๊ทธ๋ฐ๋ฐ ์ด ํจ์์ ๋งค๊ฐ๋ณ์๊ฐ Notification
์ด๋ค. ๊ฒฐ๊ตญ ์๋น์ค๋ฅผ ๊ตฌ๋์์ผ ์ค ํ
๋ ๋นจ๋ฆฌ Notification
์ ๋์ฐ๋ผ๋ ์๋ฆฌ๋ค. ๊ทธ๋ผ ํฌ๊ทธ๋ผ์ด๋ ์ทจ๊ธ ํด์ฃผ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.๊ทผ๋ฐ ์ด๊ฑธ ์ํด ์๋ฏธ ์๋ ์๋ฆผ์ ๋์ฐ๋ฉด ์ ์ ๊ฐ ๊ณผ์ฐ ์ข์ํ ๊น?
startForegroundService() ์ ์ํด ์คํ๋ ์๋น์ค ๋ด์์ ๋น ๋ฅธ ์๊ฐ ๋ด์ startForeground() ํจ์๋ฅผ ํธ์ถํด ์ค์ผ ํ๋ค.
startForeground() ํจ์์ ๋งค๊ฐ๋ณ์๋ ์๋ฆผ ๊ฐ์ฒด
val notification = builder.build()
startForeground(1, notification)
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
์๋น์ค๊ฐ ๊ตฌ๋๋ ์๊ฐ ๋น ๋ฅด๊ฒ startForeground
๋งค๊ฐ๋ณ์๋ก Notification
์ ์ค์ ์ฝ ํด์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํผ๋ฏธ์
์ด ์๊ตฌ๋๋ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ Manifest ์ ๋ฑ๋ก ํด์ฃผ์.
์ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์ด๋ผ๋ ์กฐ๊ฑด์ ์๋ง๊ฒ JobScheduler
๋ฅผ ์ฌ์ฉํ๋ฉด ์
๋ฌด ๋ก์ง์ ๋๋ฆด ์ ์๋ค.
JobScheduler
๋ ์๋น์ค์ด๋ค. ๋๋ฌธ์ Manifest ์ ๋ฑ๋กํด ์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ผ๋ฐ์ ์ธ ์๋น์ค์๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ ๊ตฌ๋๋๋ค. ์๋น์ค๋ ์ธํ
ํธ์ ์ํด ๊ตฌ๋๋์ง๋ง, JobScheduler
๋ ์์คํ
์ ๋ฑ๋ก๋๋ฉด ํน์ ์กฐ๊ฑด์ด ๋ง์กฑํ๋ ์๊ฐ์ ์์์ ์คํ์ด ๋๋ค.
JobScheduler ์ ์ด์ฉํ๋ฉด ์ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํฉ์์๋ ์ ๋ฌด์ฒ๋ฆฌ ๊ฐ๋ฅ
์กฐ๊ฑด์ ๋ช ์ํ๊ณ ๊ทธ ์กฐ๊ฑด์ ๋ง๋ ๊ฒฝ์ฐ์๋ง ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฌด ์ฒ๋ฆฌ ๊ฐ๋ฅ
1. ๋คํธ์ํฌ ํ์
2. ๋ฐฐํฐ๋ฆฌ ์ถฉ์ ์ํ
3. ํน์ ์ฑ์ ์ฝํ
์ธ ํ๋ฌ๋ฐ์ด๋์ ๊ฐฑ์
4. ์คํ ์ฃผ๊ธฐ (1์๊ฐ์ ํ ๋ฒ ๋ฑ)
5. ์ต์ ์ง์ฐ ์๊ฐ
๊ฐ๋ฐ์ ์๋น์ค
android.permission.BIND_JOB_SERVICE ํผ๋ฏธ์ ์ด ๋ฑ๋ก๋์ด์ผ ํจ
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class MyService : JobService() { ์ผ๋ฐ ์๋น์ค๊ฐ ์๋ JobService ๋ฅผ ์์
override fun onCreate() {
super.onCreate()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onStartJob(params: JobParameters?): Boolean {
// ์
๋ฌด๋ก์ง
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
// ์
๋ฌด๋ก์ง
return false
}
}
์์คํ
์ ์ํด์ JobService
๊ฐ ๊ตฌ๋๋ ๋ onStartJob()
์ onStopJob()
ํจ์๊ฐ ์๋ ์ฝ ๋๋ค.
์
๋ฌด๋ก์ง์ onStartJob()
์ ๋ด์์ฃผ๋ฉด ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด ํจ์๋ค์ ๋ฆฌํด๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
onStartJob() ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ ์ ๋ฌด๋ฅผ ๊ฐ์ง๋ ํจ์
๋ฆฌํด๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์
- false : job ์ด ์๋ฒฝํ๊ฒ ์ข
๋ฃ๋์๋ค๋ ์๋ฏธ (๋ ์ด์ ์ฒ๋ฆฌํ ์์
์ด ์์์ ์์คํ
์๊ฒ ์๋ฆผ)
-> onStopJob() ํจ์๊ฐ ํธ์ถ๋์ง ์์
- true : job ์ด ์์ง ๋๋์ง ์์์์ ์๋ฏธ (์์ ์ ๋๋ฌ์ง๋ง ์์ง ์์
์ด ๋จ์๋ค๋ ๊ฒ์ ์์คํ
์๊ฒ ์๋ฆผ)
-> onStopJob() ํจ์๊ฐ ํธ์ถ๋จ
- false : JobScheduler ๋ฑ๋ก์ด ์ทจ์ -> ๋ค์ ์คํ์กฐ๊ฑด์ด ๋๋ ์คํ x
- true : ๋ค์ JobScheduler ๋ฑ๋ก -> ๋ค์ ์คํ์กฐ๊ฑด์ด ๋๋ฉด ์คํ
JobService
๋ก ์๋น์ค๋ฅผ ์์คํ
์ ๋ฑ๋กํ๊ณ , JobInfo
๋ก ์กฐ๊ฑด์ ๋ด์ ๋ฑ๋กํ๋ค.
๊ทธ๋์ ๋น๋ ๊ฐ์ฒด
๋ก ๋ง๋ค์ด ์ค๋ค.
JobInfo.Builder(1, ComponentName(this, MyService::class.java)).run {
setRequireNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
jobScheduler?.schedule(build())
}
๋น๋๋ก JobService ๋ช
์ ์ฃผ๊ณ setter ํจ์
๋ก ์กฐ๊ฑด์ ์ค ํ์ schedule()
ํจ์๋ก ์์คํ
์ ๋ฑ๋กํ๋ค.
์กฐ๊ฑด | ๋ด์ฉ |
---|---|
setPersisted(true) | ๋จ๋ง์ ์ฌ๋ถํ ํด๋ Job ๋ฑ๋ก ์ ์งํด์ผ ํ๋์ง ์ค์ |
setPeriodic(long intervalMillis) | Job ์ ์คํ ์ฃผ๊ธฐ ์ค์ |
setMinimumLatency(long minLatencyMillis) | Job ์คํ์ ์ง์ฐ ์๊ฐ ์ค์ |
setOverrideDeadline(long maxExecutionDelayMillis) | ๋ค๋ฅธ ์กฐ๊ฑด์ด ๋ง์กฑํ์ง ์๋๋ค๊ณ ํ๋๋ผ๋ ์ด ์๊ฐ ์์ Job ์ด ์คํ๋์ด์ผ ํจ์ ์ค์ |
setRequiredNetworkType(int networkType) | ๋คํธ์ ํ์ ์ค์ |
setRequiresBatteryNotLow(boolean batteryNotLow) | ๋ฐฐํฐ๋ฆฌ๊ฐ ๋ฎ์ ์ํ๊ฐ ์๋์ ์ค์ |
setRequiresCharging(boolean requiresCharging) | ๋ฐฐํฐ๋ฆฌ๊ฐ ์ถฉ์ ์ํ์ธ์ง๋ฅผ ์ค์ |
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="add job"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.kotdev99.android.c79
class MyService : JobService() {
override fun onCreate() {
super.onCreate()
Log.d("JobService", "MyService...onCreate...") // ์๋น์ค ๊ตฌ๋ ํ์ธ
}
override fun onStartJob(p0: JobParameters?): Boolean {
Log.d("JobService", "MyService...onStartJob...")
return false
}
override fun onStopJob(p0: JobParameters?): Boolean {
Log.d("JobService", "MyService...onStopJob...")
return false
}
override fun onDestroy() {
super.onDestroy()
Log.d("JobService", "MyService...onDestroy...") // ์๋น์ค ์ข
๋ฃ ํ์ธ
}
}
package com.kotdev99.android.c79
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btn = findViewById<Button>(R.id.button)
btn.setOnClickListener {
// ์์คํ
์๋น์ค ํ๋
var scheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
// JobInfo ๋ฑ๋ก
JobInfo.Builder(1, ComponentName(this, MyService::class.java)).run {
setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // ์์ดํ์ด์ ๋ถ๋ ์๊ฐ ์คํ
scheduler.schedule(build())
}
}
}
}
์์ดํ์ด๋ฅผ ๋ ์ํ์์ ์ฑ ์คํ ํ ๋ฒํผ ํด๋ฆญ -> ์ฑ ์์ ํ ์ข ๋ฃ ํ ์์ดํ์ด ์ฐ๊ฒฐ -> Logcat ํ์ธ