본문 바로가기
안드로이드 자바

[Java][Android] Service로 음악 재생하는 앱 빠르게 만들기

by teamnova 2021. 2. 10.
728x90

이번 포스팅에선 Service를 사용해 음악을 재생하는 앱을 만들 예정입니다.

핸드폰에 기본으로 설치되어 있는 음악 재생 앱이나 멜론, 지니 등의 앱을 실행해 음악을 재생시키면 홈 버튼을 눌러 다른 작업을 해도 음악이 중간에 멈추는 일 없이 계속 재생되는 걸 보셨을 겁니다.

이렇게 백그라운드에서 계속 동작하는 컴포넌트가 바로 Service입니다.

 

아래 예제 코드는 스틱코드 포스팅에서도 확인해보실 수 있습니다.

stickode.com/detail.html?no=1884

 

스틱코드

 

stickode.com

 

먼저 이 포스팅을 통해 만들 화면입니다. 음악 재생과 중지가 목적이기 때문에 버튼 2개만 배치한 간단한 화면입니다.

 

 

아래는 위 화면을 만드는 데 사용된 MainActivity의 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/play_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="음악 재생"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

    <Button
        android:id="@+id/stop_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="음악 중지"
        android:layout_marginTop="30dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/play_btn"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

다음으로 위 화면에 맞춰 자바 파일을 작성합니다.

 

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity
{
    Button play_btn, stop_btn;

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

        play_btn = findViewById(R.id.play_btn);
        stop_btn = findViewById(R.id.stop_btn);

        // 음악 재생 버튼을 누르면 raw 폴더에 저장된 음악을 재생시킵니다
        play_btn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = new Intent(MainActivity.this, MusicService.class);
                startService(intent);
                Toast.makeText(MainActivity.this, "음악을 재생합니다", Toast.LENGTH_SHORT).show();
                Log.e("메인 액티비티", "startService() 호출");
            }
        });

        // 음악 중지 버튼을 누르면 현재 재생 중인 음악을 정지시킵니다
        stop_btn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = new Intent(MainActivity.this, MusicService.class);
                stopService(intent);
                Toast.makeText(MainActivity.this, "음악을 중지합니다", Toast.LENGTH_SHORT).show();
                Log.e("메인 액티비티", "stopService() 호출");
           }
        });
    }
}

 

 

마지막으로 서비스 파일을 만들어야 합니다.

서비스 파일을 만드는 방법은 아래와 같이 서비스 파일을 저장할 디렉토리 우클릭 > Service > Service를 누르면 됩니다.

버튼의 위치는 다소 다를 수 있습니다

 

그럼 아래와 같이 이름을 입력하고 2개의 체크박스와 사용 언어를 정할 수 있는 화면이 나옵니다.

 

 

Exported와 Enabled라는 체크박스들이 눈에 띕니다.

Exported를 체크하면 내 앱에서만 서비스를 실행하겠다는 의미입니다. false인 경우에는 다른 앱에서 이 서비스를 실행할 수 없습니다.

그리고 Enabled는 시스템에 의해서 객체화시킬 수 있는지를 설정하는 옵션입니다.

체크했을 경우 시스템에 의해서 서비스가 시작되도록 할 수 있습니다.

이 포스팅에선 Enabled만을 체크한 후 서비스를 만들겠습니다.

자세한 설명은 안드로이드 디벨로퍼를 참고하시기 바랍니다.

developer.android.com/guide/topics/manifest/service-element?hl=ko

 

 |  Android 개발자  |  Android Developers

Declares a service (a Service subclass) as one of the application's components. Unlike activities, services lack a visual user interface. They're used to implement long-running background operations or a rich communications API that can be called…

developer.android.com

 

서비스를 만들었다면 매니페스트에 꼭 등록해야 합니다.

아래와 같이 <application> 태그 안에 Service 태그를 넣어줍니다.

 

<service> 태그의 위치는 확인하기 쉬운 곳에 두면 좋을 것 같습니다

 

매니페스트 등록까지 모두 마쳤다면 이제 서비스 파일을 작성해보겠습니다.

이 때 빨리 작성하고 싶다면 스틱코드에 저장해둔 서비스 코드를 가져와서 사용하면 됩니다.

 

스틱코드에 코드를 저장해두면 원할 때 언제든 필요한 코드를 가져와 사용할 수 있습니다

완성된 서비스 파일의 구조는 아래와 같습니다.

 

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

public class MusicService extends Service
{
    private MediaPlayer player;

    public MusicService()
    {
    }

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

    @Override
    public void onCreate()
    {
        Log.e("음악 재생 서비스", "onCreate() 호출");
        super.onCreate();
    }

    //
    @Override
    public void onDestroy()
    {
        Log.e("음악 재생 서비스", "onDestroy() 호출");
        player.stop();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.e("서비스 테스트", "onStartCommand() 호출");
        player = MediaPlayer.create(this, R.raw.music);
        player.setLooping(true);
        player.start();
        return super.onStartCommand(intent, flags, startId);
    }
}

 

완성 후 앱을 빌드하면 아래와 같이 작동합니다.

 

 

이렇게 스틱코드를 사용해서 음악을 재생하고 정지할 수 있는 앱을 빠르게 만들어 보았습니다.