서비스는 백그라운드에서 실행되는 프로세스를 의미한다. 액티비티처럼 화면이 존재하지는 않지만 중요한 애플리케이션 4대 컴포넌트 중 하나이다. 카카오톡이나 문자앱 처럼 화면에 떠있지 않아도 메시지가 도착하면 알림을 받을 수 있는것도 서비스 덕분이다.

서비스 역시 액티비티와 똑같이 시스템에서 관리하므로 AndroidManifest.xml 파일에 등록된다. 서비스는 앱이 종료되어 있는 상태에서도 동작하면서 다른 구성요소와 데이터를 주고받거나 특정 이벤트를 항상 모니터링 하는 중요한 역할을 한다. 따라서 서비스가 실행되어있는 상태에서는 안드로이드 시스템이 왠만하면 서비스 프로세스가 죽지 않도록 계속 관리한다. 만약 서비스가 비정상적으로 종료되면 시스템이 자동으로 재시작한다.

서비스는 startService() 메소드를 통해 실행할 수 있다. startActivity() 메소드처럼 인텐트를 통해 부가데이터를 전달할 수도 있다. 그런데 서비스는 실행중인 상태라면 startService() 메소드를 여러 번 호출하더라도 상태변화가 없다. 따라서 startService() 메소드는 서비스의 시작보다는 인텐트의 전달을 목적으로 자주 사용한다.

서비스가 실행되어 있는 상태에서는 startService()를 실행하여도 서비스의 onCreate() 메소드가 호출되지 않는다. 따라서 인텐트를 처리하려면 onStartCommand() 메소드를 통해서 해야한다. 서비스의 수명주기는 onCreate()-생성과 onDestroy()-해제 뿐이다.

액티비티에서 서비스를 시작하면서 인텐트를 통해 부가데이터를 보내면 서비스에서 이를 토스트 메시지로 출력하도록 하여 서비스의 실행을 눈으로 확인해보자.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="30dp"/>
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="서비스로 보내기"
        android:textSize="24dp"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>

입력상자와 버튼을 하나 추가하였다. 버튼을 누르면 입력상자의 텍스트를 가져와 서비스로 보내는 인텐트의 부가 데이터에 추가해보자.

package io.swnomad.sampleservice;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = editText.getText().toString(); //입력상자 텍스트 읽어서 저장

                Intent intent = new Intent(getApplicationContext(), MyService.class); //서비스를 띄우기 위한 인텐트 객체 생성
                intent.putExtra("command", "show"); //서비스에 부가데이터 추가
                intent.putExtra("name", name); //서비스에 부가데이터 추가
                startService(intent); // 서비스 시작하기
            }
        });
    }
}

인텐트를 통해 서비스를 띄우면서 부가데이터를 2개 보냈다. 서비스 클래스를 만들어 이를 처리해보도록 하자.

package io.swnomad.sampleservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class MyService extends Service {

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(intent == null){
            return Service.START_STICKY; // START_STICKY 값을 반환받은 서비스는 비정상 종료 되면 자동으로 재시작되도록 설정
        }else{
            String command = intent.getStringExtra("command"); //"coomand" key의 value 가져오기
            String name = intent.getStringExtra("name"); //"name" key의 value 가져오기

            Toast.makeText(this, "command: "+command+" name: "+name, Toast.LENGTH_LONG).show();

        }
        return super.onStartCommand(intent, flags, startId);
    }

}

서비스에서는 onStartCommand() 메소드를 통해 인텐트를 전달받는다. 전달받은 인텐트에 들어있는 부가 데이터를 토스트 메시지로 출력하게 되어있다.

1

+ Recent posts