๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค2024 ์•ˆ๋“œ๋กœ์ด๋“œ/โ˜€๏ธ ํ•˜๊ณ„ ์ธํ„ด ๊ฐœ๋ฐœ ํ”„๋กœ์ ํŠธ ๊ธฐ๋ก

๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ธก์ •ํ•ด๋ณด๊ธฐ

by hyeonha 2024. 8. 14.

๋ชฉ์ฐจ

    ๐Ÿ™Œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ 

    ์ด์ œ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ ์œ„์น˜ , ๋น„์ฝ˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ธก์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์ž.

    ๊ตฌํ˜„์— ์•ž์„œ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ •๋ฆฌํ•˜๊ณ  ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ์— ํ•„์š”ํ•œ ๊ธฐ์ˆ ์„ ๊ฒฐ์ •ํ•ด๋ณด์ž

     ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ

    1. ์•ฑ์ด ํ™”๋ฉด์— ๋ณด์ด์ง€ ์•Š์•„๋„ ๋ฐ์ดํ„ฐ ์ธก์ •์ด ๋˜์–ด์•ผํ•œ๋‹ค.

    2. ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ์ฃผ๊ธฐ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์ธก์ •ํ•ด์•ผํ•œ๋‹ค.

    3. ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ์ฃผ๊ธฐ(5์ดˆ ~ 1๋ถ„)๋งˆ๋‹ค ์ธก์ •๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•ด์•ผํ•œ๋‹ค.

    4.. ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ์‹œ๊ฐ„๋™์•ˆ(ex 09:00 ~ 18:00) ๋™์•ˆ ์ง€์†์ ์œผ๋กœ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ ธ์•ผํ•œ๋‹ค.

    ๊ธฐ์ˆ  ์„ ํƒ ๊ณผ์ •

     - WorkManager๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ์ด์œ  

    ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰์„ ํ–ˆ์„ ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ๋“ฑ์žฅํ•œ ๊ธฐ์ˆ ์€ WorkManager์˜€๋‹ค. Workmanager๋Š” Jetpack์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ฒ˜๋ฆฌ๋ฅผ ๋„์™€์ฃผ๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ์š”์†Œ๋กœ ๊ฐ€์žฅ ์ตœ์‹ ์— ๋‚˜์˜จ ๊ธฐ์ˆ ์ด์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„๋ž˜์˜ ์ด์œ ๋“ค๋กœ WorkManager ๋ฐฉ์‹์€ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€๋‹ค. 

     

    1. ์ œ๊ณตํ•˜๋Š” ์ตœ์†Œ ๊ฐ„๊ฒฉ์ด 15๋ถ„์œผ๋กœ ์ดˆ ๋‹จ์œ„์˜ ๊ฐ„๊ฒฉ์„ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ์šฐ๋ฆฌ์˜  ์š”๊ตฌ ์‚ฌํ•ญ์— ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค.

    2. ์ธก์ •ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธํ•ด์•ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— WorkManager๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค.

     

    ์œ„ ์ด์œ ๋กœ WorkManager ๋ฐฉ์‹์€ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค.

    ๋”ฐ๋ผ์„œ ForegroundService ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

     


    ๊ตฌํ˜„ ํ๋ฆ„

    ForegroundService ์‚ฌ์šฉํ•˜๊ธฐ

    // ํฌ๊ทธ๋ผ์šด๋“œ ์ƒ์„ฑ ์ฝ”๋“œ
    
    class LocationForegroundService : Service() {
    
        override fun onBind(intent: Intent?): IBinder? {
            return null
        }
    
        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            createNotificationChannel()
            startForeground(1,getNotification("๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘"))
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            getLocation()
        return START_STICKY
        }

     

    1. ์•Œ๋ฆผ ์š”์ฒญ

    ํฌ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•Œ๋ฆผ์„ ๊ตฌํ˜„ํ•ด์ค˜์•ผํ•œ๋‹ค.

      // ์•Œ๋ฆผ ์ฑ„๋„ ์ƒ์„ฑ
      private fun createNotificationChannel() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                val serviceChannel = NotificationChannel(
                    CHANNEL_ID, "location service channel", NotificationManager.IMPORTANCE_DEFAULT)
                val manager = getSystemService(NotificationManager::class.java)
                manager.createNotificationChannel(serviceChannel)
            }
        }
    
    // ์•Œ๋ฆผ๋‚ด์šฉ ์—…๋ฐ์ดํŠธ 
        private fun updateNotification(latitude : Double, longitude: Double,time:Long){
            val notification = getNotification("์œ„๋„ : $latitude, ๊ฒฝ๋„: $longitude, ์‹œ๊ฐ„ : $time")
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(1,notification)
        }
    
    
    // ์œ„์น˜ ์•Œ๋ฆผ ๊ตฌ์„ฑ
        private fun getNotification(contentText : String) : Notification {
            val notificationIntent = Intent(this,LocationActivity::class.java)
            val pendingIntent = PendingIntent.getActivity(
                this,0,notificationIntent,PendingIntent.FLAG_IMMUTABLE
            )
    
            val builder = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("location service")
                .setContentText(contentText)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .setCategory(NotificationCompat.CATEGORY_LOCATION_SHARING)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setVibrate(longArrayOf(0))
    
            builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
            return builder.build()
        }

     

    2. ์œ„์น˜ ์š”์ฒญ

    // ์œ„์น˜ ๋ฐ์ดํ„ฐ ์ธก์ • 
    private fun getLocation() {
        val mLocationRequestHighAccuracy = LocationRequest.create().apply {
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
            interval = 5 * 1000 // 1-minute interval
            fastestInterval = 5 * 1000
        }
    
    // ๊ถŒํ•œ ๊ฒ€์‚ฌ 
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            mFusedLocationClient.requestLocationUpdates(
                mLocationRequestHighAccuracy,
                object : LocationCallback() {
                    override fun onLocationResult(locationResult: LocationResult) {
                        for (location in locationResult.locations) {
                            location?.let {
                            // ์•Œ๋ฆผ์—…๋ฐ์ดํŠธ
                                updateNotification(it.latitude, it.longitude, it.time)
                            }
    					'''

     

    3. ํฌ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค ์‹คํ–‰

    
      override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
      
      // 1. ์•Œ๋ฆผ
            createNotificationChannel()
            startForeground(1,getNotification("๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘"))
            
     // 2. ์œ„์น˜ ์š”์ฒญ
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            getLocation()
        return START_STICKY
        }

     

    ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ฒฐ๊ณผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์œ„์น˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ธก์ •ํ•˜๋Š”๋ฐ ์„ฑ๊ณตํ–ˆ๋‹ค!

    ์‹ค์‹œ๊ฐ„ ์œ„์น˜ ๊ฐ’์„ ๋ฐ›์•„์˜จ ๊ฒฐ๊ณผ

    ๐Ÿ’ก๋ฐฐ์šด ์ 

    • ๊ถŒํ•œ ์š”์ฒญ ๋ฐ ์‚ฌ์šฉ์ž์˜ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ์— ๋”ฐ๋ฅธ ๋™์ž‘
    • ๋ฐฑ๊ทธ๋ผ์šด๋“œ(ํฌ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค)๋ฅผ ํ†ตํ•ด ์œ„์น˜ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๋ฐฉ๋ฒ•
    • ๋ฐฑ๊ทธ๋ผ์šด๋“œ(ํฌ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค) ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ์•Œ๋ฆผ(notification)์„ ๋„์šฐ๋Š” ๋ฐฉ๋ฒ•
    • ์•Œ๋ฆผ์„ ๋„์šฐ๊ธฐ ์œ„ํ•ด์„œ manifest ๋ฟ ์•„๋‹ˆ๋ผ ๋Ÿฐํƒ€์ž„ ๊ถŒํ•œ์„ ์š”์ฒญํ•ด์•ผํ•œ๋‹ค.

     

    - ๊ถŒํ•œ์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ๊ณผ์ •์€ ์•„๋ž˜ ๊ธ€์— ์ •๋ฆฌํ•ด๋‘์—ˆ๋‹ค.

    https://hyeonhahaha.tistory.com/entry/Android-%EA%B6%8C%ED%95%9C-%EC%9A%94%EC%B2%AD-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-%EB%9F%B0%ED%83%80%EC%9E%84-%EA%B6%8C%ED%95%9C

     

    Android ๊ถŒํ•œ ์š”์ฒญ ์ฒ˜๋ฆฌํ•˜๊ธฐ (๋Ÿฐํƒ€์ž„ ๊ถŒํ•œ??)

    ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ์‚ฌ์šฉ์ž์˜ ์œ„์น˜๋ฅผ ์ธก์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์—์„œ๋Š” ์œ„์น˜ ๊ถŒํ•œ ์š”์ฒญ์ด๋ผ๋Š” ๊ถŒํ•œ์ด ํ•„์š”ํ–ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ๊ถŒํ•œ ์š”์ฒญ์— ๋Œ€ํ•ด ๋Œ€์ˆ˜๋กญ์ง€ ์•Š๊ฒŒ ์—ฌ๊ฒผ๋Š”๋ฐ, ๊ถŒํ•œ์„ ์ œ๋Œ€๋กœ ์„ค์ •ํ•ด

    hyeonhahaha.tistory.com

    728x90