이 튜토리얼에서는 Android 백그라운드 상태에서 볼륨 버튼(볼륨 증가·감소) 이벤트를 감지하는 방법을 단계별로 살펴봅니다. Android는 볼륨 키를 직접 가로채는 공개 API를 제공하지 않기 때문에, 시스템 볼륨 값의 변화를 ContentObserver로 관찰하는 방식으로 구현하게 됩니다.
1단계 – 새 프로젝트 생성
Android Studio에서 File → New Project 메뉴로 이동한 후, 필요한 정보를 모두 입력하여 새 프로젝트를 만듭니다.
2단계 – 레이아웃 작성
res/layout/activity_main.xml 파일에 아래 코드를 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="볼륨 증가 및 감소"
android:textSize="24sp"
android:textStyle="bold" />
</LinearLayout>
3단계 – MainActivity 작성
src/MainActivity.java 파일에 아래 코드를 추가합니다. 핵심은 Settings.System.CONTENT_URI에 ContentObserver를 등록하여 볼륨 변경을 실시간으로 감지하고, 이전 볼륨 값과 현재 값을 비교해 증가/감소 여부를 판별하는 부분입니다.
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.database.ContentObserver;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;
import java.util.Objects;
public class MainActivity extends AppCompatActivity {
SettingsContentObserver settingsContentObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
settingsContentObserver = new SettingsContentObserver(this, new Handler());
getApplicationContext().getContentResolver().registerContentObserver(
android.provider.Settings.System.CONTENT_URI,
true,
settingsContentObserver);
}
public class SettingsContentObserver extends ContentObserver {
int previousVolume;
Context context;
SettingsContentObserver(Context c, Handler handler) {
super(handler);
context = c;
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
previousVolume =
Objects.requireNonNull(audio).getStreamVolume(AudioManager.STREAM_MUSIC);
}
@Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int currentVolume =
Objects.requireNonNull(audio).getStreamVolume(AudioManager.STREAM_MUSIC);
int delta = previousVolume - currentVolume;
if (delta > 0) {
Toast.makeText(MainActivity.this, "볼륨 감소됨", Toast.LENGTH_SHORT).show();
previousVolume = currentVolume;
} else if (delta < 0) {
Toast.makeText(MainActivity.this, "볼륨 증가됨", Toast.LENGTH_SHORT).show();
previousVolume = currentVolume;
}
}
}
@Override
protected void onDestroy() {
getApplicationContext().getContentResolver().unregisterContentObserver(settingsContentObserver);
super.onDestroy();
}
}
4단계 – 매니페스트 설정
AndroidManifest.xml 파일에 아래 코드를 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
앱 실행 및 결과 확인
이제 애플리케이션을 실행해 보겠습니다. 실제 Android 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run 아이콘을 클릭하고 목록에서 자신의 모바일 기기를 선택하면 해당 기기에 앱이 설치되고 실행됩니다.
앱이 실행되면 기본 화면이 표시됩니다. 이후 기기의 볼륨 업/다운 버튼을 눌러보면, 볼륨이 증가했을 때와 감소했을 때 각각 토스트 메시지로 결과가 표시되는 것을 확인할 수 있습니다. 이처럼 ContentObserver를 활용하면 앱이 포그라운드에 있지 않은 상황에서도 시스템 볼륨의 변화를 안정적으로 감지할 수 있습니다.