mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-09-01 03:55:47 +02:00
Use MediaController for media buttons
This commit is contained in:
parent
c7bb47d6bd
commit
95fdee3cbe
@ -24,6 +24,7 @@ import android.content.Intent;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.media.session.MediaSessionManager;
|
import android.media.session.MediaSessionManager;
|
||||||
|
import android.media.session.PlaybackState;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ import java.util.List;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
public class GBMusicControlReceiver extends BroadcastReceiver {
|
public class GBMusicControlReceiver extends BroadcastReceiver {
|
||||||
@ -43,13 +45,13 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
|
|||||||
public static final String ACTION_MUSICCONTROL = "nodomain.freeyourgadget.gadgetbridge.musiccontrol";
|
public static final String ACTION_MUSICCONTROL = "nodomain.freeyourgadget.gadgetbridge.musiccontrol";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
GBDeviceEventMusicControl.Event musicCmd = GBDeviceEventMusicControl.Event.values()[intent.getIntExtra("event", 0)];
|
final int event = intent.getIntExtra("event", 0);
|
||||||
int keyCode = -1;
|
final GBDeviceEventMusicControl.Event musicCmd = GBDeviceEventMusicControl.Event.values()[event];
|
||||||
int volumeAdjust = AudioManager.ADJUST_LOWER;
|
final int keyCode;
|
||||||
|
|
||||||
|
final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
|
||||||
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
|
|
||||||
switch (musicCmd) {
|
switch (musicCmd) {
|
||||||
case NEXT:
|
case NEXT:
|
||||||
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
|
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
|
||||||
@ -73,70 +75,144 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
|
|||||||
keyCode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
|
keyCode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
|
||||||
break;
|
break;
|
||||||
case VOLUMEUP:
|
case VOLUMEUP:
|
||||||
// change default and fall through, :P
|
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
|
||||||
volumeAdjust = AudioManager.ADJUST_RAISE;
|
sendPhoneVolume(audioManager);
|
||||||
|
return;
|
||||||
case VOLUMEDOWN:
|
case VOLUMEDOWN:
|
||||||
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, volumeAdjust, 0);
|
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0);
|
||||||
|
sendPhoneVolume(audioManager);
|
||||||
final int volumeLevel = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
return;
|
||||||
final int volumeMax = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
|
|
||||||
final int volumePercentage = (byte) Math.round(100 * (volumeLevel / (float) volumeMax));
|
|
||||||
|
|
||||||
GBApplication.deviceService().onSetPhoneVolume(volumePercentage);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
|
LOG.error("Unknown event {}", event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCode != -1) {
|
final GBPrefs prefs = GBApplication.getPrefs();
|
||||||
String audioPlayer = getAudioPlayer(context);
|
|
||||||
|
|
||||||
LOG.debug("keypress: " + musicCmd.toString() + " sent to: " + audioPlayer);
|
if (prefs.getBoolean("pref_deprecated_media_control", false)) {
|
||||||
|
// Deprecated path - mb_intents works for some players and not others, and vice-versa
|
||||||
|
|
||||||
long eventtime = SystemClock.uptimeMillis();
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
if (GBApplication.getPrefs().getBoolean("mb_intents", false)) {
|
if (prefs.getBoolean("mb_intents", false)) {
|
||||||
Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
|
String audioPlayer = getAudioPlayer(context);
|
||||||
KeyEvent downEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_DOWN, keyCode, 0);
|
|
||||||
|
LOG.debug("Sending key press {} to {}", musicCmd, audioPlayer);
|
||||||
|
|
||||||
|
final Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
|
||||||
|
final KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0);
|
||||||
downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent);
|
downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent);
|
||||||
if (!"default".equals(audioPlayer)) {
|
if (!"default".equals(audioPlayer)) {
|
||||||
downIntent.setPackage(audioPlayer);
|
downIntent.setPackage(audioPlayer);
|
||||||
}
|
}
|
||||||
context.sendOrderedBroadcast(downIntent, null);
|
context.sendOrderedBroadcast(downIntent, null);
|
||||||
|
|
||||||
Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
|
final Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
|
||||||
KeyEvent upEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_UP, keyCode, 0);
|
final KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0);
|
||||||
upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent);
|
upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent);
|
||||||
if (!"default".equals(audioPlayer)) {
|
if (!"default".equals(audioPlayer)) {
|
||||||
upIntent.setPackage(audioPlayer);
|
upIntent.setPackage(audioPlayer);
|
||||||
}
|
}
|
||||||
context.sendOrderedBroadcast(upIntent, null);
|
context.sendOrderedBroadcast(upIntent, null);
|
||||||
} else {
|
} else {
|
||||||
KeyEvent downEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_DOWN, keyCode, 0);
|
LOG.debug("Sending key press {} generally", musicCmd);
|
||||||
|
final KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0);
|
||||||
audioManager.dispatchMediaKeyEvent(downEvent);
|
audioManager.dispatchMediaKeyEvent(downEvent);
|
||||||
|
|
||||||
KeyEvent upEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_UP, keyCode, 0);
|
final KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0);
|
||||||
audioManager.dispatchMediaKeyEvent(upEvent);
|
audioManager.dispatchMediaKeyEvent(upEvent);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
final MediaSessionManager mediaSessionManager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||||
|
final List<MediaController> controllers = mediaSessionManager.getActiveSessions(
|
||||||
|
new ComponentName(context, NotificationListener.class)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (controllers.isEmpty()) {
|
||||||
|
LOG.warn("No media controller found to handle {}", musicCmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MediaController controller = controllers.get(0);
|
||||||
|
|
||||||
|
switch (musicCmd) {
|
||||||
|
case NEXT:
|
||||||
|
controller.getTransportControls().skipToNext();
|
||||||
|
return;
|
||||||
|
case PREVIOUS:
|
||||||
|
controller.getTransportControls().skipToPrevious();
|
||||||
|
return;
|
||||||
|
case PLAY:
|
||||||
|
controller.getTransportControls().play();
|
||||||
|
return;
|
||||||
|
case PAUSE:
|
||||||
|
controller.getTransportControls().pause();
|
||||||
|
return;
|
||||||
|
case PLAYPAUSE:
|
||||||
|
final PlaybackState playbackState = controller.getPlaybackState();
|
||||||
|
if (playbackState != null) {
|
||||||
|
switch (playbackState.getState()) {
|
||||||
|
case PlaybackState.STATE_NONE:
|
||||||
|
case PlaybackState.STATE_STOPPED:
|
||||||
|
case PlaybackState.STATE_PAUSED:
|
||||||
|
case PlaybackState.STATE_FAST_FORWARDING:
|
||||||
|
case PlaybackState.STATE_REWINDING:
|
||||||
|
controller.getTransportControls().play();
|
||||||
|
return;
|
||||||
|
case PlaybackState.STATE_PLAYING:
|
||||||
|
controller.getTransportControls().pause();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.warn("Failed to determine playback state, attempting to play");
|
||||||
|
controller.getTransportControls().play();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case REWIND:
|
||||||
|
controller.getTransportControls().rewind();
|
||||||
|
return;
|
||||||
|
case FORWARD:
|
||||||
|
controller.getTransportControls().fastForward();
|
||||||
|
}
|
||||||
|
} catch (final SecurityException e) {
|
||||||
|
LOG.warn("Failed to get media controller - did not grant notification access?", e);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOG.error("Failed to get media controller", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getAudioPlayer(Context context) {
|
private static void sendPhoneVolume(final AudioManager audioManager) {
|
||||||
Prefs prefs = GBApplication.getPrefs();
|
final int volumeLevel = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
|
||||||
String audioPlayer = prefs.getString("audio_player", "default");
|
final int volumeMax = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
|
||||||
MediaSessionManager mediaSessionManager =
|
final int volumePercentage = (byte) Math.round(100 * (volumeLevel / (float) volumeMax));
|
||||||
(MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
|
||||||
|
GBApplication.deviceService().onSetPhoneVolume(volumePercentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
private static String getAudioPlayer(final Context context) {
|
||||||
|
final Prefs prefs = GBApplication.getPrefs();
|
||||||
|
final String audioPlayer = prefs.getString("audio_player", "default");
|
||||||
|
final MediaSessionManager mediaSessionManager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||||
try {
|
try {
|
||||||
List<MediaController> controllers = mediaSessionManager.getActiveSessions(
|
final List<MediaController> controllers = mediaSessionManager.getActiveSessions(
|
||||||
new ComponentName(context, NotificationListener.class));
|
new ComponentName(context, NotificationListener.class)
|
||||||
try {
|
);
|
||||||
MediaController controller = controllers.get(0);
|
|
||||||
audioPlayer = controller.getPackageName();
|
if (controllers.isEmpty()) {
|
||||||
} catch (IndexOutOfBoundsException e) {
|
LOG.warn("No media controller available");
|
||||||
LOG.error("No media controller available", e);
|
return audioPlayer;
|
||||||
}
|
}
|
||||||
} catch (SecurityException e) {
|
|
||||||
|
return controllers.get(0).getPackageName();
|
||||||
|
} catch (final SecurityException e) {
|
||||||
LOG.warn("No permission to get media sessions - did not grant notification access?", e);
|
LOG.warn("No permission to get media sessions - did not grant notification access?", e);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOG.error("Failed to get media controller", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return audioPlayer;
|
return audioPlayer;
|
||||||
|
@ -3234,4 +3234,8 @@
|
|||||||
<string name="insufficient_space_for_upload">"Insufficient space for upload"</string>
|
<string name="insufficient_space_for_upload">"Insufficient space for upload"</string>
|
||||||
<string name="smart_ring_measurement_error_worn_incorrectly">Measurement error. Are the ring\'s sensors oriented correctly?</string>
|
<string name="smart_ring_measurement_error_worn_incorrectly">Measurement error. Are the ring\'s sensors oriented correctly?</string>
|
||||||
<string name="smart_ring_measurement_error_unknown">Unknown measurement error %d received from ring</string>
|
<string name="smart_ring_measurement_error_unknown">Unknown measurement error %d received from ring</string>
|
||||||
|
<string name="pref_header_deprecated_functionalities">Deprecated functionalities</string>
|
||||||
|
<string name="pref_header_deprecated_functionalities_warning">The following functionalities have been deprecated and will be removed soon from the software.\nIf you need to enable one of the following settings be sure to get in touch with the project team.</string>
|
||||||
|
<string name="pref_deprecated_media_control_title">Deprecated media control</string>
|
||||||
|
<string name="pref_deprecated_media_control_summary">Send media control commands as key events instead of the media controller.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -42,22 +42,6 @@
|
|||||||
android:title="@string/pref_title_bottom_navigation_bar"
|
android:title="@string/pref_title_bottom_navigation_bar"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="mb_intents"
|
|
||||||
android:layout="@layout/preference_checkbox"
|
|
||||||
android:summary="@string/pref_summary_mb_intents"
|
|
||||||
android:title="@string/pref_title_mb_intents"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<ListPreference
|
|
||||||
android:defaultValue="default"
|
|
||||||
android:dependency="mb_intents"
|
|
||||||
android:key="audio_player"
|
|
||||||
android:summary="%s"
|
|
||||||
android:title="@string/pref_title_audio_player"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="pref_category_dashboard"
|
android:key="pref_category_dashboard"
|
||||||
android:title="@string/bottom_nav_dashboard"
|
android:title="@string/bottom_nav_dashboard"
|
||||||
@ -403,4 +387,49 @@
|
|||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
|
||||||
|
<PreferenceScreen
|
||||||
|
android:key="pref_screen_deprecated_functionalities"
|
||||||
|
android:title="@string/pref_header_deprecated_functionalities"
|
||||||
|
app:iconSpaceReserved="false">
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_key_deprecated_functionalities"
|
||||||
|
android:title="@string/pref_header_deprecated_functionalities_warning"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:singleLineTitle="false" />
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_header_media_control"
|
||||||
|
android:title="@string/pref_deprecated_media_control_title"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:singleLineTitle="false">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_deprecated_media_control"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:summary="@string/pref_deprecated_media_control_summary"
|
||||||
|
android:title="@string/pref_deprecated_media_control_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:dependency="pref_deprecated_media_control"
|
||||||
|
android:key="mb_intents"
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:summary="@string/pref_summary_mb_intents"
|
||||||
|
android:title="@string/pref_title_mb_intents"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="default"
|
||||||
|
android:dependency="mb_intents"
|
||||||
|
android:key="audio_player"
|
||||||
|
android:summary="%s"
|
||||||
|
android:title="@string/pref_title_audio_player"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
</PreferenceScreen>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
Loading…
Reference in New Issue
Block a user