본문 바로가기

안드로이드

서비스

반응형
https://developer.android.com/guide/components/services?hl=ko

 

서비스를 실행하려면 메인액티비티에서 startService 메소드를 호출하면 된다

서비스를 시작시키기 위해 startService 메소드를 호출할 때는 인텐트 객체를 파라미터로 전달한다
인텐트 객체는 어떤 서비스를 실행할 것인지에 대한 정보를 담고 있으며
시스템은 서비스를 시작시킨 후 인텐트 객체를 서비스에 전달한다

startService 메소드가 호출되어 이미 메모리에 올라가있는 상태라면
시스템이 onCreate가 아니라 onStartCommand 메소드를 실행한다

onStartCommand 메소드는 서비스로 전달된 인텐트 객체를 처리하는 메소드이다

 

 

MyService.java 파일이 생성되고, AndroidManifest.xml에 <service> 태그가 추가된다

서비스는 시스템에서 관리하므로 매니페스트에 넣어 앱 설치 시에 시스템이 살 수 있게 해야한다

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>

 

 

activity_main.xml

<?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:layout_marginBottom="348dp"
        android:text="서비스로 보내기"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent" />

    <EditText
        android:id="@+id/editTextTextPersonName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:ems="10"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

MyService.java

package com.example.a37_service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

    private static final String TAG = "MyService";

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() 호출됨");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

//        첫 번째 파라미터로 로그를 구분할 수 있는 문자열 전달
        Log.d(TAG, "onStartCommand() 호출됨");

//        서비스는 시스템에 의해 자동으로 다시 시작될 수 있기 때문에 null인 경우도 검사해야한다
        if (intent == null) {
//            Service.START_STICKY가 반환되면 서비스가 비정상 종료되었다는 의미이므로 시스템이 자동으로 재시작한다
//            자동으로 재시작하지 않도록 만들고 싶다면 다른 상수를 사용하면 된다
            return Service.START_STICKY;
        } else {
            processCommand(intent);
        }

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

    private void processCommand(Intent intent) {
        String command = intent.getStringExtra("command");
        String name = intent.getStringExtra("name");

        Log.d(TAG, "command : " + command + ", name : " + name);

        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {

            }

            Log.d(TAG, "waiting " + i + " seconds");
        }

//
//
//        서비스에서 액티비티로 데이터 보내기
        Intent showIntent = new Intent(getApplicationContext(), MainActivity.class);

//        서비스에서 startActivity 메소드를 호출할 때는 새로운 태스크를 생성하도록 FLAG_ACTIVITY_NEW_TASK 플래그를 인텐트에 추가
//        서비스는 화면이 없기 때문에 화면이 없는 서비스에서 화면이 있는 액티비티를 띄우려면 새로운 태스크를 만들어어야 하기 때문
//        MainActivity 객체가 이미 메모리에 만들어져 있을 때 재사용하도록 FLAG_ACTIVITY_SINGLE_TOP과 FLAG_ACTIVITY_CLEAR_TOP 추가
        showIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        showIntent.putExtra("command", "show");
        showIntent.putExtra("name", name + " from service");
//        서비스에서 액티비티로 인텐트를 보내는 메소드
        startActivity(showIntent);
    }

//    서비스가 서버 역할을 하면서 액티비티와 연결될 수 있도록 만드는 것을 바인딩이라고 한다
//    이를 위해서 onBind 메소드를 재정의 해야한다
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

 

 

MainActivity

package com.example.a37_service;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

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.editTextTextPersonName);
        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 메소드에 담은 인텐트 객체는 MyService 클래스의 onStartCommand 메소드로 전달된다
                startService(intent);
            }
        });

//        액티비티가 새로 만들어질때 전달된 인텐트 처리하기
        Intent passedIntent = getIntent();
        processIntent(passedIntent);

    }

    //    액티비티가 새로 만들어지지 않고 재사용될 경우 액티비티의 onCreate 메소드가 호출되지않는데
//    재사용되는 액티비티에서 인텐트를 처리하려면 onNewIntent 메소드를 써야한다
    @Override
    protected void onNewIntent(Intent intent) {
        processIntent(intent);
        super.onNewIntent(intent);
    }

    private void processIntent(Intent intent) {
        if (intent != null) {
            String command = intent.getStringExtra("command");
            String name = intent.getStringExtra("name");

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

 

 

Service 외에 IntentService 클래스가 있다

IntentService는 필요한 함수가 수행되고 나면 종료된다

백그라운드에서 실행되는 것은 같지만 길게 지속되는 서비스는 아니고, 한 번 실행되고 끝나는 작업을 수행할 때 사용한다

onStartCOmmand 메소드로 전달된 인텐트를 onHandleIntent 메소드가 받으면서 실행된다

그리고 이 함수의 실행이 끝나면 서비스는 자동 종료된다

반응형

'안드로이드' 카테고리의 다른 글

위험 권한 부여  (0) 2021.10.22
브로드캐스트  (0) 2021.10.22
바로가기 메뉴, Navigation Drawer  (0) 2021.10.21
ViewPager2로 여러 프래그먼트 간 슬라이드  (0) 2021.10.21
하단 탭 만들기  (0) 2021.10.20