【问题标题】:Android link headphone volume to master volumeAndroid 将耳机音量关联到主音量
【发布时间】:2017-03-14 00:04:01
【问题描述】:

我有一台安卓电视(飞利浦 49PUS6401) 我想连接一个环绕声系统,即使只用于立体声,它的质量也比内置扬声器好得多。

但是,这台电视将主输出和耳机输出的音量控制分开,结果是即使电视内的扬声器关闭,遥控器上的音量键也不能调节耳机音量(我正在使用作为线路输出)

我打算编写一个简单的应用程序来在桅杆音量更改时调整耳机音量,但我似乎无法弄清楚如何获取或设置耳机音量,因为音频管理器处理流而不是输出,所以我能从中得到的唯一价值就是主人。

如何找到获取/设置耳机音量的方法? 我通过 adb 获得了 shell 访问权限,但我无法获得 root。

作为参考,电视正在运行最新的固件,即 android 5.1.1

【问题讨论】:

  • android 没有区分主输出和耳机输出。您只能调整流developer.android.com/reference/android/media/…
  • 我知道通常情况下不会,但不知何故,这台电视的制造商设法将输出配对,以便耳机始终处于活动状态,并且音量单独控制,这在支持论坛,一些索尼电视也有这个问题:supportforum.philips.com/en/archive/index.php/t-1361.html
  • 我认为电视耳机输出仅用于来自 HDMI 输入的音频,对吗?
  • 不,无论电视正在播放什么音频(无论是来自 HDMI 输入、电视输入、scart 等),都会同时通过电视扬声器和耳机播放,每个都有单独的音量控制
  • 飞利浦 49PUS6401 环绕声系统的哪个端口连接了“耳机”或“数字音频输出”或其他?

标签: android android-audiomanager android-tv


【解决方案1】:

据我了解,这是飞利浦 Android TV 用户的常见问题(例如,this 线程或that 讨论中的第 22 页)。 一般来说,您的任务模板是Service,它跟踪“系统/音乐”音频流(或媒体按钮按下)的插入/拔出事件和音量,而不是对“有线耳机”音频“流”进行相应的更改(没有“标准”Android中的这种流,但显然 类似的东西出现在"Android Philips") 级别。问题是,仅使用没有“Philips Android TV API”的 Android SDK 似乎不可能更改音量“有线耳机”音频流级别(可能不是公开的)。

“VolumeTrackingService”的模板源代码可能是这样的:

public class VolumeTrackingService extends Service {

    private static final String TAG = VolumeTrackingService.class.getSimpleName();

    public static final String ACTION_START = "VolumeTrackingService.ACTION_START";
    public static final String ACTION_STOP = "VolumeTrackingService.ACTION_STOP";

    HeadsetPlugIntentReceiver mHeadsetPlugReceiver;
    private static boolean mHeadsetPlugged = false;

    private SettingsContentObserver mSettingsContentObserver;

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

    @Override
    public void onCreate() {
        super.onCreate();
        mHeadsetPlugReceiver = new HeadsetPlugIntentReceiver();
        registerReceiver(mHeadsetPlugReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
        mSettingsContentObserver = new SettingsContentObserver(new Handler());
        getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver);
    }

    @Override
    public void onDestroy() {
        getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
        unregisterReceiver(mHeadsetPlugReceiver);
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            String actionRequested = intent.getAction();
            if (ACTION_START.equals(actionRequested)) {
            } else if (ACTION_STOP.equals(actionRequested)) {
                stopSelf();
            }
        }
        return START_STICKY;
    }

    private int getSystemVolumeInPercentage() {
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        final int streamVolumeMax = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        final int streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        return 100 * streamVolume / streamVolumeMax;
    }

    private void setHeadphonesVolume(int volumeInPercentage) {
        // there should be magic of wired headphones volume level changing
    }

    private void processVolumeChanges() {
        if (mHeadsetPlugged) {
            int systemVolumeInPercentage = getSystemVolumeInPercentage();
            setHeadphonesVolume(systemVolumeInPercentage);
        }
    }


    public class SettingsContentObserver extends ContentObserver {

        public SettingsContentObserver(Handler handler) {
            super(handler);
        }

        @Override
        public boolean deliverSelfNotifications() {
            return super.deliverSelfNotifications();
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            if (mHeadsetPlugged ) {
                processVolumeChanges();
            }
        }
    }

    public class HeadsetPlugIntentReceiver extends android.content.BroadcastReceiver {
        @Override
        public void onReceive(Context ctx, Intent intent) {
            if (intent.getAction().equals(android.media.AudioManager.ACTION_HEADSET_PLUG)) {
                mHeadsetPlugged = intent.getIntExtra("state", 0) == 1;
            }
        }
    }
}

不幸的是,它没有解决主要问题:改变有线耳机的音量(如果没有“Philips Android TV API”,这可能是不可能的)。

但如果您的环绕声系统有遥控器,您可以采取一些解决方法:模拟上述Service 中的音​​响系统远程控制命令,并通过连接到飞利浦 49PUS6401 Android 电视的 USB 主机的 IR 加密狗发送。

【讨论】:

  • 虽然我非常感谢您花时间编写一个简单的框架来帮助我,但我正在努力解决 // there should be magic of wired headphones volume level changing 位...
  • 我明白)。实际上,我认为“但是,如果您的环绕声系统具有遥控器,您可以采取一些解决方法:在上述服务中模拟音响系统远程控制命令,并通过连接到飞利浦 49PUS6401 Android 电视的 USB 主机的 IR 加密狗发送它。” - 是答案的主要部分,服务模板 - 只是介绍。我认为只有普通的 Android SDK 无法做你想做的事。
  • 通过模拟遥控信号对环绕声系统的音量控制在任何情况下都可以正常工作。而且IR dongle可能简单又便宜,比如this就是100%的解决方案。因为问题出在飞利浦 Android TV 上(例如在 SONY BRAVIA 上,一切都如您所愿)。
  • 我的音响系统没有遥控器,所以这对我不起作用,可能对其他人有用,但不幸的是这并不能解决我的问题。
  • 好的。您也可以尝试模拟“按键”事件序列来更改耳机音量(如在this 回答中),但它会在电视屏幕上可见。但最好在电视和音响系统之间添加带有音量控制的放大器。
猜你喜欢
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 2021-06-21
  • 2022-07-04
  • 2014-11-03
  • 1970-01-01
相关资源
最近更新 更多