Lautstärketasten im Hintergrunddienst anhören?

Lesezeit: 11 Minuten

Ich weiß, wie man Lautstärketasten in einer Aktivität anhört. Aber kann ich das in einem Hintergrunddienst tun? Wenn ja, wie macht man das?

  • Müssen Sie auf die Lautstärketaste oder auf eine Änderung der Lautstärke hören?

    – Stobor

    16. Juli 2012 um 5:36 Uhr

  • Beachten Sie, dass dies derzeit nicht auf Android 12 (im Hintergrund) funktioniert: issuetracker.google.com/issues/201546605

    – Merthan Erdem

    10. November 2021 um 18:49 Uhr


Lautstarketasten im Hintergrunddienst anhoren
ssuukk

Es ist möglich. Verwenden Sie den folgenden Code (für neuere Android-Versionen, insbesondere Marshmallow, siehe unten in der Antwort):

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;
        }
    }
}

Dann registrieren Sie es in Ihrem Dienst onCreate mit:

mSettingsContentObserver = new SettingsContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );

Dann deregistrieren Sie sich in onDestroy:

getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);

Beachten Sie, dass dieses Beispiel anhand der Änderung der Medienlautstärke beurteilt wird. Wenn Sie eine andere Lautstärke verwenden möchten, ändern Sie sie!

AKTUALISIEREN:

Die obige Methode funktioniert angeblich nicht auf Marshmallow, ABER es gibt jetzt einen viel besseren Weg, seit MediaSession eingeführt wurde! Also müssen Sie zuerst Ihren Code zum MediaController/MediaSession-Muster migrieren und dann diesen Code verwenden:

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);

Irgendwie wird das Drücken der Lautstärketaste auch bei ausgeschaltetem Bildschirm erkannt (stellen Sie nur sicher, dass Sie den richtigen Empfänger für die Absicht der Medientaste registrieren, falls für Ihre Plattform zutreffend!)

UPDATE 2, da GalDude weitere Informationen zum Abrufen von MediaSession/MediaController angefordert hat. Entschuldigung, aber seit ich aufgehört habe, Java zu verwenden, wird es in Kotlin sein:

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()

  • @ssuukk: Werden Lautstärketasten erkannt, wenn der Bildschirm ausgeschaltet ist? ODER funktioniert Ihre Lösung nur für den Fall, wenn der Bildschirm eingeschaltet ist?

    – Basher51

    11. September 2014 um 6:01 Uhr

  • Dieser Code funktioniert, während sich die Anwendung im Pausenzustand befindet. So erkennen Sie die Lautstärkeänderung nach dem Entfernen der Anwendung aus dem laufenden Zustand.?

    – Karthick

    28. Dezember 2014 um 18:27 Uhr

  • Dies ist mit Android Marshmallow nicht mehr möglich, alle Lautstärkeeinstellungen wurden aus android.provider.Settings.System entfernt. – developer.android.com/sdk/api_diff/23/changes/…

    – dsemi

    10. November 2015 um 22:52 Uhr


  • Es IST noch möglich. Ich werde meine Antwort gleich aktualisieren!

    – ssuukk

    11. November 2015 um 7:17 Uhr

  • Randnotiz: VolumeProviderCompat funktioniert nur auf API 21(+). Und auf meinem Nexus 5X die Systemeinstellungen beobachten tut tatsächlich funktionieren, genau wie auf älteren Plattformen.

    – MH.

    23. November 2015 um 14:56 Uhr

Lautstarketasten im Hintergrunddienst anhoren
Jo

Die AOSP Music App hat einen Dienst (MediaPlaybackService), der auf Lautstärketastenereignisse reagiert, indem er einen BroadcastReceiver (MediaButtonIntentReceiver).

Hier ist das Code-Snippet, in dem der Empfänger registriert wird:

    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    ComponentName rec = new ComponentName(getPackageName(),
            MediaButtonIntentReceiver.class.getName());
    mAudioManager.registerMediaButtonEventReceiver(rec);

Vergessen Sie auch nicht das Manifest:

    <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>

Dies funktioniert auch, wenn die Musik-App nicht im Vordergrund ist. Ist es nicht das, was du willst?

  • Lautstärketasten werden im Standard-ROM nicht als “Medientasten” betrachtet. Ich denke, diese App kann Lautstärketasten bekommen, weil sie mit einem benutzerdefinierten Android-ROM läuft …

    – elgui

    5. Dezember 2012 um 12:30 Uhr

  • @elgui Könnten Sie bitte einen Link zu einer Dokumentation bereitstellen, die Ihre Worte unterstützt?

    – CAMOBAP

    28. Juni 2013 um 14:08 Uhr

  • Nun, mit Stock-ROM erstellen Sie einen Empfänger, der auf Medientasten hört, drücken Sie eine Lautstärketaste und beobachten Sie, dass nichts passiert …

    – elgui

    29. Juni 2013 um 10:51 Uhr

  • hier ist der Dokumentationslink androidxref.com/4.4.4_r1/xref/frameworks/base/media/java/…

    – Goran Horia Mihail

    5. Januar 2015 um 20:31 Uhr

  • Was ist mit Google Play Musik? Es ist nicht der Standardplayer, aber er verwaltet auch Medientasten, auch wenn er nicht im Vordergrund ist …

    – Massimo

    26. Januar 2017 um 16:34 Uhr

Ich konnte es auf Android 5+ Geräten zum Laufen bringen MediaSession. Aber,ContentObserver vorgeschlagen von @ssuukk hat bei mir sowohl auf 4.4- als auch auf 7.0-Geräten nicht funktioniert (zumindest auf ROMs, auf denen ich getestet habe). Hier ist ein vollständiges Beispiel, das auf Android 5+ funktioniert.

Bedienung:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.media.VolumeProviderCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;

public class PlayerService extends Service {
    private MediaSessionCompat mediaSession;

    @Override
    public void onCreate() {
        super.onCreate();
        mediaSession = new MediaSessionCompat(this, "PlayerService");
        mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0) //you simulate a player which plays something.
                .build());

        //this will only work on Lollipop and up, see https://code.google.com/p/android/issues/detail?id=224134
        VolumeProviderCompat myVolumeProvider =
                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, /*max volume*/100, /*initial volume level*/50) {
            @Override
            public void onAdjustVolume(int direction) {
                /*
                -1 -- volume down
                1 -- volume up
                0 -- volume button released
                 */
            }
        };

        mediaSession.setPlaybackToRemote(myVolumeProvider);
        mediaSession.setActive(true);
    }


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

    @Override
    public void onDestroy() {
        super.onDestroy();
        mediaSession.release();
    }
}

Im AndroidManifest.xml:

<application ...>
    ...
    <service android:name=".PlayerService"/>
</application>

In Ihrer Tätigkeit:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    startService(new Intent(this, PlayerService.class));
}

Es gibt mehrere Dinge zu beachten:

  • Es fängt Lautstärketasten ab vollständig Während dieser Code ausgeführt wird, können Sie die Klingeltonlautstärke nicht mit den Lautstärketasten anpassen. Vielleicht lässt sich das beheben, ich habe es nur nicht versucht.
  • Wenn Sie das Beispiel unverändert ausführen, bleiben die Lautstärketasten von der App gesteuert, auch wenn der Bildschirm ausgeschaltet ist und die App aus der Liste „Letzte Apps“ entfernt wurde. Sie müssen zu gehen Settings->Applicationsfinden Sie die App und erzwingen Sie das Stoppen, um die Lautstärketasten wieder zu erhalten.

  • innerhalb von onAdjustVolume nichts bekommen. Ich arbeite mit Nexus 5

    – Gottessklave

    21. April 2017 um 10:43 Uhr

  • Wenn Sie diesen Code der Zeile hinzufügen, funktioniert es. : if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mediaSession.setCallback(new MediaSessionCompat.Callback(){ }); }

    – Vasilisfoo

    8. Mai 2017 um 12:52 Uhr


  • Diese Lösung ist ziemlich gut, funktioniert aber nicht, wenn der Bildschirm ausgeschaltet ist. Gibt es eine Lösung? Danke

    – Daniele

    3. Februar 2018 um 0:10 Uhr

  • @Daniele Es funktioniert bei mir, wenn der Bildschirm ausgeschaltet ist, wie beim Antwortschreiber (Denis). (Mein Handy: Android 9, Mi Mix 3)

    – Venryx

    6. August 2019 um 8:51 Uhr

  • Überprüfen Sie diese Antwort, wenn Ihre IDE die MediaSessionCompat-Klasse stackoverflow.com/a/52019860/7953908 nicht erkennen kann

    – Gilian Marques

    14. Mai 2020 um 0:08 Uhr

1646247789 137 Lautstarketasten im Hintergrunddienst anhoren
Venryx

Leider ist dies ein weiterer Bereich von Android, in dem es fünf verschiedene Möglichkeiten gibt, “das Problem zu lösen”, aber die meisten von ihnen funktionieren nicht sehr gut. Für meine eigene geistige Gesundheit werde ich versuchen, alle verschiedenen Ansätze unten aufzulisten.

Lösungen

1) MediaSession (vom Dienst)

Antwort von Denis Kniazhev: https://stackoverflow.com/a/43304591/2441655

Nachteile:

  1. Erfordert Android-API-Level 21+ (Android 5.0+).

2) android.media.VOLUME_CHANGED_ACTION (vom Dienst)

Antwort von Nikhil: https://stackoverflow.com/a/44040282/2441655

Nachteile:

  1. Kein offizieller Teil des SDK: https://stackoverflow.com/a/8974510/2441655
  2. Ignoriert das erste Drücken der Lautstärketaste (da nur die Lautstärkeleiste angezeigt wird).
  3. Ignoriert die Lauter-Taste bei 100 % und die Leiser-Taste bei 0 %.

3) ContentObserver (vom Dienst)

Antwort von ssuukk: https://stackoverflow.com/a/15292255/2441655 (erster Teil)

Nachteile:

  1. Funktioniert nicht in neueren Versionen von Android: Kommentar von dsemi
  2. Ignoriert das erste Drücken der Lautstärketaste (da nur die Lautstärkeleiste angezeigt wird).
  3. Ignoriert die Lauter-Taste bei 100 % und die Leiser-Taste bei 0 %.

4) AudioManager.registerMediaButtonEventReceiver (vom Dienst)

Antwort von Joe: https://stackoverflow.com/a/11510564/2441655

Nachteile:

  1. Funktioniert bei den meisten Roms nicht: Kommentar von elgui

5) onKeyDown (aus Aktivität)

Antwort von dipali: https://stackoverflow.com/a/21086563/2441655

Nachteile:

  1. Funktioniert nicht, wenn der Bildschirm ausgeschaltet ist, in einer anderen App usw.

6) dispatchKeyEvent (aus Aktivität)

Antwort von Maurice Gavin: https://stackoverflow.com/a/11462962/2441655

Nachteile:

  1. Funktioniert nicht, wenn der Bildschirm ausgeschaltet ist, in einer anderen App usw.

Fazit

Die Lösung, die ich derzeit verwende, ist Nr. 1, weil:

  1. Es ist ein offizieller Teil des SDK.
  2. Es kann von einem Dienst verwendet werden. (dh unabhängig davon, in welcher App Sie sich befinden)
  3. Es erfasst jeden Lautstärketastendruck, unabhängig vom aktuellen Lautstärke-/UI-Status.
  4. Es funktioniert, wenn der Bildschirm ausgeschaltet ist.

Lassen Sie mich wissen, wenn Sie andere finden – oder wenn Sie bei einigen von ihnen weitere Nachteile gefunden haben!

1646247789 197 Lautstarketasten im Hintergrunddienst anhoren
Bryan Herbst

Nach den paar anderen Fragen zu diesem Thema zu urteilen, nein.

Andere Frage 1, Andere Frage 2

Dienste empfangen einfach keine KeyEvent-Rückrufe.

  • Sehen Sie sich meine Antwort hier an, um zu sehen, wie die AOSP Music App sie implementieren konnte 🙂

    – Jo

    16. Juli 2012 um 20:12 Uhr

  • Es gibt Möglichkeiten, Lautstärketastenereignisse von einem Dienst zu empfangen. Tatsächlich gibt es vier verschiedene Möglichkeiten! Siehe meine Antwort hier für eine Zusammenfassung der verschiedenen Ansätze.

    – Venryx

    6. August 2019 um 9:29 Uhr

1646247790 487 Lautstarketasten im Hintergrunddienst anhoren
Chetan Ashtivkar

Sie müssen einen leeren Ton vom Dienst abspielen, dann können nur Sie Lautstärkeänderungen hören. Folgendes hat bei mir funktioniert

Schritte

1. Legen Sie blank.mp3 in den RAW-Ordner (Download from Hier)

2. Medien bei onStartCommand() starten

private MediaPlayer mediaPlayer;

public MyService() {
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    ........

    mediaPlayer = MediaPlayer.create(this, R.raw.blank);
    mediaPlayer.setLooping(true);
    mediaPlayer.start();

    .......

    return START_STICKY;
}

3. Sie müssen Mediaplayer stoppen und freigeben. Es ist besser, dies in onDestroy() zu tun

@Override
public void onDestroy() {

    mediaPlayer.stop();
    mediaPlayer.release();

    super.onDestroy();
}

4. Erstellen Sie einen Broadcast-Empfänger, der auf Lautstärkeänderungen lauscht

int volumePrev = 0;

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        if ("android.media.VOLUME_CHANGED_ACTION".equals(intent.getAction())) {

            int volume = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_VALUE",0);

            Log.i(TAG, "volume = " + volume);

            if (volumePrev  < volume) {
                Log.i(TAG, "You have pressed volume up button");
            } else {
                Log.i(TAG, "You have pressed volume down button");
            }
            volumePrev = volume;
        }
    }
};

5. Registrieren Sie den Broadcast-Empfänger in onStartCommand()

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    .....

    IntentFilter filter = new IntentFilter();
    filter.addAction("android.media.VOLUME_CHANGED_ACTION");
    registerReceiver(broadcastReceiver, filter);

    ....

    return START_STICKY;
}

6. Registrierung des Broadcast-Empfängers in onDestroy() aufheben

 @Override
public void onDestroy() {
    .....

    unregisterReceiver(broadcastReceiver);

    .....

    super.onDestroy();
}

Das ist alles

  • Sehen Sie sich meine Antwort hier an, um zu sehen, wie die AOSP Music App sie implementieren konnte 🙂

    – Jo

    16. Juli 2012 um 20:12 Uhr

  • Es gibt Möglichkeiten, Lautstärketastenereignisse von einem Dienst zu empfangen. Tatsächlich gibt es vier verschiedene Möglichkeiten! Siehe meine Antwort hier für eine Zusammenfassung der verschiedenen Ansätze.

    – Venryx

    6. August 2019 um 9:29 Uhr

1646247790 487 Lautstarketasten im Hintergrunddienst anhoren
Gemeinschaft

Dies erfordert Lollipop (v5.0/API 21) oder höher

Mein Ziel war es, die Systemlautstärke von einem Dienst aus anzupassen. Auf der Presse können jedoch alle Maßnahmen ergriffen werden.

public class VolumeKeyController {

    private MediaSessionCompat mMediaSession;
    private final Context mContext;

    public VolumeKeyController(Context context) {
        mContext = context;
    }

    private void createMediaSession() {
        mMediaSession = new MediaSessionCompat(mContext, KeyUtil.log);

        mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mMediaSession.setPlaybackState(new Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0)
                .build());
        mMediaSession.setPlaybackToRemote(getVolumeProvider());
        mMediaSession.setActive(true);
    }

    private VolumeProviderCompat getVolumeProvider() {
        final AudioManager audio = mContext.getSystemService(Context.AUDIO_SERVICE);

        int STREAM_TYPE = AudioManager.STREAM_MUSIC;
        int currentVolume = audio.getStreamVolume(STREAM_TYPE);
        int maxVolume = audio.getStreamMaxVolume(STREAM_TYPE);
        final int VOLUME_UP = 1;
        final int VOLUME_DOWN = -1;

        return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
            @Override
            public void onAdjustVolume(int direction) {
                // Up = 1, Down = -1, Release = 0
                // Replace with your action, if you don't want to adjust system volume
                if (direction == VOLUME_UP) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                else if (direction == VOLUME_DOWN) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                setCurrentVolume(audio.getStreamVolume(STREAM_TYPE));
            }
        };
    }

    // Call when control needed, add a call to constructor if needed immediately
    public void setActive(boolean active) {
        if (mMediaSession != null) {
            mMediaSession.setActive(active);
            return;
        }
        createMediaSession();
    }

    // Call from Service's onDestroy method
    public void destroy() {
        if (mMediaSession != null) {
            mMediaSession.release();
        }
    }
}

915170cookie-checkLautstärketasten im Hintergrunddienst anhören?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy