Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

안드로이드에서 10초마다 인텐트 서비스(IntentService)를 시작하는 방법

인텐트 서비스(IntentService)란 무엇인가?

본격적인 예제에 들어가기 전에, 안드로이드의 인텐트 서비스(IntentService)가 어떤 역할을 하는지 먼저 이해할 필요가 있습니다. 인텐트 서비스는 백그라운드 작업을 비동기적으로 처리하는 서비스 컴포넌트입니다. 액티비티에서 startService()를 호출하더라도 요청마다 새로운 인스턴스를 생성하지 않으며, 서비스 클래스의 작업이 모두 끝나면 자동으로 종료됩니다. 물론 필요하다면 stopSelf()를 호출해 직접 종료할 수도 있습니다.

이 글에서는 10초마다 인텐트 서비스를 시작하는 방법을 단계별로 살펴보겠습니다.

1단계 — 새 프로젝트 만들기

Android Studio에서 File → New Project를 선택한 뒤, 프로젝트 생성에 필요한 정보를 모두 입력하여 새 프로젝트를 만듭니다.

2단계 — 레이아웃 작성(res/layout/activity_main.xml)

res/layout/activity_main.xml 파일에 다음 코드를 추가합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android = "https://schemas.android.com/apk/res/android"
   xmlns:app = "https://schemas.android.com/apk/res-auto"
   xmlns:tools = "https://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent"
   tools:context = ".MainActivity">
   <TextView
      android:id = "@+id/text"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content"
      android:text = "Start Service"
      android:textSize = "25sp"
      app:layout_constraintBottom_toBottomOf = "parent"
      app:layout_constraintLeft_toLeftOf = "parent"
      app:layout_constraintRight_toRightOf = "parent"
      app:layout_constraintTop_toTopOf = "parent" />
</android.support.constraint.ConstraintLayout>

위 코드에는 TextView 하나가 화면 중앙에 배치되어 있습니다. 사용자가 인텐트 서비스로부터 데이터를 전달받으면 이 TextView의 내용이 해당 값으로 갱신됩니다.

3단계 — 메인 액티비티 구현(src/MainActivity.java)

src/MainActivity.java 파일에 다음 코드를 추가합니다.

package com.example.andy.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {
    TextView text;
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String someValue = intent.getStringExtra("someName");
            text.setText(someValue);
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.andy.myapplication");
        LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.text);
        final Handler handler = new Handler();
        TimerTask timertask = new TimerTask() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        startService(new Intent(MainActivity.this, service.class));
                    }
                });
            }
        };
        Timer timer = new Timer();
        timer.schedule(timertask, 0, 10000);
    }

    @Override
    protected void onStop() {
        super.onStop();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
    }
}

여기서 핵심은 TimerHandler입니다. TimerTask가 10초(10,000밀리초) 간격으로 실행되며, Handler.post()를 통해 메인 스레드에서 startService()를 호출함으로써 인텐트 서비스를 주기적으로 시작합니다. 동시에 BroadcastReceiver를 onStart()에서 등록하고 onStop()에서 해제하여, 서비스가 전송하는 데이터를 안전하게 수신해 화면에 반영합니다.

서비스 클래스 작성(service.java)

service라는 이름의 클래스 파일을 생성하고 다음 코드를 추가합니다.

package com.example.andy.myapplication;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;

public class service extends IntentService {
    public static volatile boolean shouldStop = false;
    public service() {
        super(service.class.getSimpleName());
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Intent intent1 = new Intent("com.example.andy.myapplication");
        intent1.putExtra("someName", "Tutorialspoint.com");
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent1);
        if(shouldStop) {
            stopSelf();
            return;
        }
    }
}

onHandleIntent() 내부에서는 LocalBroadcastManager를 통해 com.example.andy.myapplication 액션으로 브로드캐스트를 전송하고, shouldStop 플래그가 true로 설정되어 있으면 stopSelf()를 호출해 서비스를 종료합니다.

4단계 — 매니페스트 설정(manifest.xml)

manifest.xml 파일에 다음 코드를 추가합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "https://schemas.android.com/apk/res/android"
    package = "com.example.andy.myapplication">
    <uses-permission android:name = "android.permission.WAKE_LOCK"/>
    <application
        android:allowBackup = "true"
        android:icon = "@mipmap/ic_launcher"
        android:label = "@string/app_name"
        android:roundIcon = "@mipmap/ic_launcher_round"
        android:supportsRtl = "true"
        android:theme = "@style/AppTheme">
        <activity android:name = ".MainActivity">
            <intent-filter>
                <action android:name = "android.intent.action.MAIN" />
                <category android:name = "android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name = ".service"/>
    </application>
</manifest>

매니페스트에는 WAKE_LOCK 권한과 함께 <service> 태그로 서비스 컴포넌트를 반드시 선언해야 한다는 점에 유의하세요. 서비스가 선언되지 않으면 런타임 오류가 발생합니다.

앱 실행 및 결과 확인

이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤 툴바의 Run 아이콘을 클릭하고, 목록에서 자신의 모바일 기기를 선택하세요. 그러면 기기에 아래와 같은 기본 화면이 표시됩니다.

안드로이드에서 10초마다 인텐트 서비스(IntentService)를 시작하는 방법

위 화면은 앱의 초기 상태입니다. 이후 10초마다 서비스가 시작되어 백그라운드에서 데이터를 확인하고, 그 결과를 화면에 지속적으로 갱신합니다.

참고: 최신 안드로이드 버전에서의 주의 사항

IntentService는 API 30부터 공식적으로 지원 중단(deprecated)되었으며, Android 8.0(API 26) 이상에서는 백그라운드 실행 제한으로 인해 앱이 백그라운드 상태일 때 startService() 호출이 차단될 수 있습니다. 따라서 실무에서 주기적인 백그라운드 작업이 필요하다면 WorkManagerJobScheduler 같은 최신 API를 사용하는 것이 좋습니다. 다만 학습용 예제나 앱이 포그라운드에 있는 경우에는 위 방식을 그대로 활용할 수 있습니다.