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

안드로이드에서 IntentService 작업 완료 후 액티비티를 새로 고치는 방법

IntentService란 무엇인가?

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

이 글에서는 IntentService의 작업이 완료되었을 때 액티비티 화면을 자동으로 새로 고치는 방법을 단계별로 살펴보겠습니다.

1단계: 새 프로젝트 생성

안드로이드 스튜디오에서 File → New Project를 선택하고, 필요한 정보를 모두 입력해 새 프로젝트를 생성합니다.

2단계: 레이아웃 파일 작성

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 하나만 배치되어 있습니다. 사용자가 IntentService로부터 데이터를 전달받으면 이 TextView가 갱신되는 구조입니다.

3단계: MainActivity 구현

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.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
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);
        text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(new Intent(MainActivity.this, service.class));
            }
        });
    }
    @Override
    protected void onStop() {
        super.onStop();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
    }
}

여기서 핵심은 BroadcastReceiver입니다. 액티비티가 시작될 때(onStart) 리시버를 등록하고, 화면에서 사라질 때(onStop) 등록을 해제함으로써 메모리 누수를 방지합니다. 서비스에서 브로드캐스트가 도착하면 onReceive() 콜백에서 전달받은 데이터로 TextView를 갱신하게 됩니다.

서비스 클래스 작성

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

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를 통해 브로드캐스트를 전송하는 것이 이 예제의 핵심입니다. 서비스는 별도의 스레드에서 동작하기 때문에 UI에 직접 접근할 수 없으므로, 브로드캐스트를 통해 결과를 액티비티에 전달하는 방식을 사용합니다.

4단계: 매니페스트 설정

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>

반드시 <service android:name = ".service"/> 항목을 선언해야 시스템이 해당 서비스를 인식하고 실행할 수 있습니다.

앱 실행 및 결과 확인

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

안드로이드에서 IntentService 작업 완료 후 액티비티를 새로 고치는 방법

위 화면은 애플리케이션의 초기 상태입니다. 여기서 "Start Service"를 클릭하면 서비스가 시작되고, 작업 완료와 함께 브로드캐스트가 전달되어 아래와 같이 TextView가 갱신되는 것을 확인할 수 있습니다.

안드로이드에서 IntentService 작업 완료 후 액티비티를 새로 고치는 방법

참고: 최신 개발 환경에서의 대안

IntentService는 API 30(안드로이드 11)부터 공식적으로 지원 중단(deprecated)되었으며, LocalBroadcastManager 역시 더 이상 권장되지 않습니다. 최신 프로젝트에서는 백그라운드 작업에 WorkManager를, 컴포넌트 간 통신에는 LiveData, Flow 또는 EventBus 같은 대안을 사용하는 것이 좋습니다. 다만 레거시 코드 유지보수나 학습 목적이라면 위 예제처럼 BroadcastReceiver 조합이 여전히 유효한 패턴입니다.