アクティビティで音量ボタンを聞く方法を知っています。しかし、バックグラウンド サービスでそれを行うことはできますか? はいの場合、それを行う方法は?
10 に答える
可能です。以下のコードを使用してください(新しいAndroidバージョン、特にマシュマロについては、回答の下部を参照してください):
public class SettingsContentObserver extends ContentObserver {
int previousVolume;
Context context;
public SettingsContentObserver(Context c, Handler handler) {
super(handler);
context=c;
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
previousVolume = 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 = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
int delta=previousVolume-currentVolume;
if(delta>0)
{
Logger.d("Ściszył!"); // volume decreased.
previousVolume=currentVolume;
}
else if(delta<0)
{
Logger.d("Zrobił głośniej!"); // volume increased.
previousVolume=currentVolume;
}
}
}
次に、サービスonCreateで登録します。
mSettingsContentObserver = new SettingsContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
次に、onDestroyで登録を解除します。
getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
この例では、メディアの音量を変更して判断します。他の音量を使用する場合は、変更してください。
アップデート:
上記の方法はマシュマロでは機能しないと思われますが、MediaSessionが導入されて以来、はるかに優れた方法があります。したがって、最初にコードをMediaController / MediaSessionパターンに移行してから、次のコードを使用する必要があります。
private VolumeProviderCompat myVolumeProvider = null;
myVolumeProvider = new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
@Override
public void onAdjustVolume(int direction) {
// <0 volume down
// >0 volume up
}
};
mSession.setPlaybackToRemote(myVolumeProvider);
画面がオフの場合でも、どういうわけか音量ボタンの押下が検出されます(プラットフォームに該当する場合は、適切なメディアボタンインテントレシーバーを登録してください!)
GalDudeがメディアMediaSession/MediaControllerの取得に関する詳細情報を要求したため、UPDATE2。申し訳ありませんが、Javaの使用をやめたので、Kotlinになります。
lateinit var mediaSession: MediaSessionCompat // you have to initialize it in your onCreate method
val kontroler: MediaControllerCompat
get() = mediaSession.controller // in Java it's just getController() on mediaSession
// in your onCreate/start method:
mediaSession = MediaSessionCompat(this, "YourPlayerName", receiver, null)
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
mediaSession.isActive = true
if (ratingIsWorking) // note: rating crashes on some machines you have to check it!
mediaSession.setRatingType(RatingCompat.RATING_5_STARS)
mediaSession.setCallback(object : MediaSessionCompat.Callback() {
...
// here you have to implement what happens with your player when play/pause/stop/ffw etc. is requested - see exaples elsewhere
})
// onDestroy/exit method:
mediaSession.isActive = false
mediaSession.release()
AOSP Musicアプリには、BroadcastReceiver( MediaButtonIntentReceiver )を登録することでボリュームキーイベントに応答するサービス( MediaPlaybackService )があります。
受信者を登録するコードスニペットは次のとおりです。
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
ComponentName rec = new ComponentName(getPackageName(),
MediaButtonIntentReceiver.class.getName());
mAudioManager.registerMediaButtonEventReceiver(rec);
また、マニフェストを忘れないでください。
<receiver android:name="com.android.music.MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
これは、ミュージックアプリがフォアグラウンドにない場合でも機能します。それはあなたが望むものではありませんか?
注:これはアクティビティに対してのみ機能し、質問に記載されているようにサービスに対しては機能しません。
コールバックが必要なコンテキストに応じて、代替ソリューションが利用できる場合があります。
音量ボタンを検出できるようにするには、アクティビティでdispatchKeyEvent
関数をオーバーライドする必要があります。これが複数のアクティビティに存在するためには、後続のすべてのアクティビティによって拡張されるオーバーライドされた関数を含むスーパークラスを作成できます。
音量アップ/ダウンキーの押下を検出するためのコードは次のとおりです。
// Over-ride this function to define what should happen when keys are pressed (e.g. Home button, Back button, etc.)
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_DOWN)
{
switch (event.getKeyCode())
{
case KeyEvent.KEYCODE_VOLUME_UP:
// Volume up key detected
// Do something
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
// Volume down key detected
// Do something
return true;
}
}
return super.dispatchKeyEvent(event);
}
その場合、Android は音量ボタンの操作に関する API を文書化していません。ですから、答えはノーだと思います…</p>
チェックアウトアプリの音量と再生を制御する...これは問題を解決するのに役立ちます...複数のアプリケーションがバックグラウンドからボタンの押下をリッスンする場合があります。これが、キーイベントがインターフェイスであるため、アクティビティによってのみ処理できる理由である可能性がありますキーを押すユーザーに。