짱짱해커가 되고 싶은 나

14-1. 서비스 본문

모바일

14-1. 서비스

동로시 2021. 2. 27. 20:24

* 서비스

일반적으로 화면 없이 동작하는 프로그램을 의미 ( == 데몬, 백그라운드 프로세스)

액티비티 응용 프로그램은 액티비티(화면)이 종료되면 동작하지 않지만 서비스는 백그라운드에서 실행되므로 화면과 상관없이 계속 동작한다. 서비스의 생명주기는 액티비티의 생명주기보다 단순한다.

 

getStartService() -> 시작 -> onCreate() -> onStartCommand() -> 동작 -> onStopService() -> onDestroy() -> 종료

 

프로젝트1: 음악 서비스

Button 2개 - 음악 서비스 시작, 음악 서비스 중지

 

<MusicService.java>

package com.example.project14;

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

import androidx.annotation.Nullable;

public class MusicService extends Service {
    MediaPlayer mp;

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

    @Override
    public void onCreate() {
        android.util.Log.i("서비스 테스트", "onCreate()");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        android.util.Log.i("서비스 테스트", "onDestroy()");
        mp.stop();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mp = MediaPlayer.create(this, R.raw.song1);
        mp.setLooping(true);
        mp.start();
        android.util.Log.i("서비스 테스트", "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }
}

Service 클래스를 상속받는 클래스를 만든다.

startCommand()가 오면 MediaPlayer가 시작하게 했다.

노래가 끝나도 다시 반복하도록 looping을 true로 설정했다.

Destroy()가 오면 stop을 한다.

 

<AndroidMainfest.xml>

서비스도 액티비티와 마찬가지로 Mainfest에 등록해야 사용할 수 있다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.project14">

    <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/Theme.Project14">
        <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=".MusicService">
            <intent-filter>
                <action android:name="com.example.MusicService"/>
            </intent-filter>
        </service>
    </application>

</manifest>

만약에 다른 응용 프로그램에서도 서비를 사용하게 하려면 인텐트 필터를 등록해야한다.

 

<MainActivity.java>

package com.example.project14;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {
    Intent intent;
    Button btn1, btn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("서비스 테스트");

        intent = new Intent(this, MusicService.class);
        btn1 = (Button)findViewById(R.id.btn1);
        btn2 = (Button)findViewById(R.id.btn2);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(intent);
                android.util.Log.i("서비스 테스트", "startService()");
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
                android.util.Log.i("서비스 테스트", "stopService()");
            }
        });
    }
}

Intent로 MusicService 클래스를 생성자에 넘겨서 intent 변수를 만든다.

 

서비스 로그

프로젝트2: 음악 서비스 여러 곡 반복 재생

 

<MainActivity.java>

package com.example.project14_1;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

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

public class MainActivity extends AppCompatActivity {
    Intent intent;
    Button btn1, btn2;

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

        intent = new Intent(this, MusicService.class);
        btn1 = (Button)findViewById(R.id.btn1);
        btn2 = (Button)findViewById(R.id.btn2);

        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(intent);
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
            }
        });
    }
}

<MusicService.java>

package com.example.project14_1;

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

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.util.ArrayList;

public class MusicService extends Service {
    MediaPlayer mp;
    File[] listFiles;
    int index=0;


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

    @Override
    public void onCreate() {
        super.onCreate();
        listFiles = new File("/sdcard/Music/").listFiles();
    }

    @Override
    public void onDestroy() {
        mp.stop();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            mp = new MediaPlayer();
            mp.setDataSource(listFiles[index].getPath());
            mp.prepare();
            mp.start();
            mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    index++;
                    if(index > listFiles.length)
                        index = 0;
                    try{
                        mp = new MediaPlayer();
                        mp.setDataSource(listFiles[index].getPath());
                        mp.prepare();
                        mp.start();
                    } catch (Exception e){

                    }
                }
            });
        } catch (Exception e) {
        }

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

}

OnCompletionListener를 사용하기 위해서는 반드시 looping을 flase로 설정해줘야한다.

문제점) sd 카드에 접근하기 위한 ActivityCompat.requestPermissons는 서비스에서는 할 수 없어서 액티비티를 종료하면 음악 재생이 안된다.. 어떻게 해야할지 고민 중..

 

'모바일' 카테고리의 다른 글

14-3. 콘텐트 프로바이더  (0) 2021.02.27
14-2. 브로드캐스트 리시버  (0) 2021.02.27
13-3. 구글 지도  (0) 2021.02.27
13-2. 스레드  (0) 2021.02.27
13-1. 오디오  (0) 2021.02.27
Comments