서비스를 생성하려면 Service의 하위 클래스(또는 이것의 기존 하위 클래스 중 하나)를 생성해야 합니다. 다음은 재정의가 필요한 가장 중요한 콜백 메서드입니다.
액티비티 및 다른 구성 요소와 마찬가지로, 서비스는 모두 애플리케이션의 매니페스트 파일에서 선언해야 합니다.
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
음악 파일 준비
MusicService 클래스 구현
public class MusicService extends Service {
private final String TAG="MusicService";
private MediaPlayer mMediaPlayer;
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"onBind()");
return null;
}
@Override
public void onCreate() {
Log.d(TAG,"onCreate()");
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(this, R.raw.instrumental);
mMediaPlayer.setLooping(true);
}
}
@Override
public void onDestroy() {
Log.d(TAG,"onDestroy()");
if (mMediaPlayer !=null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand()");
if (mMediaPlayer != null) {
mMediaPlayer.start();
Toast.makeText(this,"음악 재생 시작",Toast.LENGTH_LONG).show();
}
return START_STICKY;
}
}
activity_main.xml 파일 작성
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="음악 서비스 테스트"
android:textSize="20sp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/start"
android:text="시작"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/stop"
android:text="중지"
/>
</LinearLayout>
MainActivity 클래스 구현
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = findViewById(R.id.start);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(MainActivity.this,MusicService.class));
}
});
Button stop = findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(MainActivity.this,MusicService.class));
}
});
}
}
서비스가 해당 애플리케이션에서만 사용되는 경우, 자체적인 Binder 클래스를 구현하여 클라이언트가 서비스 내의 공개 메서드에 직접 액세스하도록 할 수도 있습니다.
설정 절차
예제 프로젝트 Github 링크
Service의 서브 클래스에서 Binder 객체를 반환하는 onBind() 콜백 메서드를 구현해야 합니다.
public class MusicBoundService extends Service {
private final String TAG = "BoundMusicService";
// 클라이언트에 반환할 바인더 객체 생성
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
// 클라이언트는 이 메소드를 이용하여 MusicBoundService 객체 인스턴스를 얻음
MusicBoundService getService() {
return MusicBoundService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// ...
}
필요한 수명주기 콜백 메소드를 재정의하고, 클라이언트가 사용할 공개 메소드를 정의한다.
public class MusicBoundService extends Service {
private final String TAG = "BoundMusicService";
//...
private MediaPlayer mMediaPlayer;
private int mPlaybackPosition;
@Override
public void onCreate() {
Log.d(TAG, "onCreate()");
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(this, R.raw.instrumental);
mMediaPlayer.setLooping(true);
mPlaybackPosition = 0;
}
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
public void startPlaying() {
Log.d(TAG, "startPlaying()");
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(this, R.raw.instrumental);
mMediaPlayer.setLooping(true);
mPlaybackPosition = 0;
}
mMediaPlayer.seekTo(mPlaybackPosition);
mMediaPlayer.start();
Toast.makeText(this, "음악 재생 시작", Toast.LENGTH_LONG).show();
}
public void stopPlaying() {
Log.d(TAG, "stopPlaying()");
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
Toast.makeText(this, "음악 재생 중지", Toast.LENGTH_LONG).show();
}
}
public void pausePlaying() {
Log.d(TAG, "pausePlaying()");
if (mMediaPlayer != null) {
mPlaybackPosition = mMediaPlayer.getCurrentPosition();
mMediaPlayer.pause();
Toast.makeText(this, "음악 재생 일시 중지", Toast.LENGTH_LONG).show();
}
}
}
클라이언트는 확보된 서비스 객체 인스턴스를 통해 서비스 객체의 공개 메소드를 사용합니다.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = findViewById(R.id.start);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//4. 서비스 객체의 공개 메소드 사용
mService.startPlaying();
}
});
// ...생략
}
MusicBoundService mService;
boolean mBound = false;
// 1. 서비스와의 연결 상태를 모니터링하는 ServiceConnection 구현 객체 생성
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicBoundService.LocalBinder binder = (MusicBoundService.LocalBinder)service;
// 3. 클라이언트는 바인딩된 서비스 객체 인스턴스를 얻습니다.
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
@Override
protected void onStart() {
super.onStart();
// 2. 클라이언트는 bindService() 를 호출하여 서비스에 바인딩합니다.
bindService(new Intent(MainActivity.this, MusicBoundService.class),
mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
unbindService(mConnection);
super.onStop();
}
}