[UWP]:系统音量设置为关闭时的警报通知音频

时间:2017-01-13 13:53:39

标签: uwp windows-10-mobile

大家好:)我们正在编写一个针对当地消防部门的应用程序,因为他们计划删除两个寻呼机频率中的一个,并将其替换为应用程序(他们有两个警报频道,经典寻呼机和手机)。如果有传入警报,手机会创建带有音频的警报方案ToastNotification。到目前为止一直很好,问题是如果用户将系统主音量设置为零,则不播放音频文件。我知道到目前为止无法从应用程序更改系统音量,但对于我的场景,我需要播放音频通知,无论手机音量设置等。

如果有人知道如何克服这个问题,我将非常感谢:)

2 个答案:

答案 0 :(得分:2)

我知道它不是你想听到的,但Win10Mobile设备是消费者设备。如果你买了一部手机,将它静音,它仍会发出噪音,你会有什么感觉?

当一个人将手机静音时,他们说它不应该发出声音。您是说要覆盖用户设置,而不是设备应该做什么。

如果您有专业要求,可能需要使用专业设备。我还没有检查过,但可能有些设备(不是UWP)没有用户可访问的硬件卷设置。

如果您无法控制正在使用的设备,那么我建议获取(或制作?)一个隐藏访问音量按钮的案例。

如果一个人在收到来电/留言时有责任接听电话,那么在一天结束时,您可以在具有固定功能的设备上进行代码处理。

答案 1 :(得分:0)

我遇到了完全相同的问题。幸运的是,我使用P / Invoke从C#接口使用IAudioEndpointVolume找到了一个有效的解决方案。

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Windows.Media.Devices;

namespace AudioUtils
{
    public static class VolumeControl
    {
        public static void ChangeVolumeToMinLevel(double level)
        {
            if (level > 1)
                level = 1;
            else if (level < 0)
                level = 0;

            try
            {
                var masterVol = GetAudioEndpointVolume();

                if (masterVol == null)
                    return;

                var hr = masterVol.GetMute(out var muted);

                if (hr != (uint)HResult.S_OK)
                    return;

                if (muted)
                {
                    masterVol.SetMute(false, Guid.Empty);
                }

                // Only adapt volume if the current level is below the specified minumum level
                hr = masterVol.GetMasterVolumeLevelScalar(out float currentAudioValue);
                float newAudioValue = Convert.ToSingle(level);
                if (currentAudioValue > newAudioValue)
                    return;

                masterVol.SetMasterVolumeLevelScalar(newAudioValue, Guid.Empty);
            }
            catch { }
        }

        private static IAudioEndpointVolume GetAudioEndpointVolume()
        {
            var speakerId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
            var completionHandler = new ActivateAudioInterfaceCompletionHandler<IAudioEndpointVolume>();

            var hr = ActivateAudioInterfaceAsync(
                speakerId,
                typeof(IAudioEndpointVolume).GetTypeInfo().GUID,
                IntPtr.Zero,
                completionHandler,
                out var activateOperation);

            Debug.Assert(hr == (uint)HResult.S_OK);

            return completionHandler.WaitForCompletion();
        }

        [DllImport("Mmdevapi.dll", ExactSpelling = true, PreserveSig = false)]
        [return: MarshalAs(UnmanagedType.Error)]
        private static extern uint ActivateAudioInterfaceAsync(
                [In, MarshalAs(UnmanagedType.LPWStr)]string deviceInterfacePath,
                [In, MarshalAs(UnmanagedType.LPStruct)]Guid riid,
                [In] IntPtr activationParams,
                [In] IActivateAudioInterfaceCompletionHandler completionHandler,
                out IActivateAudioInterfaceAsyncOperation activationOperation);
    }

    internal class ActivateAudioInterfaceCompletionHandler<T> : IActivateAudioInterfaceCompletionHandler
    {
        private AutoResetEvent _completionEvent;
        private T _result;

        public ActivateAudioInterfaceCompletionHandler()
        {
            _completionEvent = new AutoResetEvent(false);
        }

        public void ActivateCompleted(IActivateAudioInterfaceAsyncOperation operation)
        {
            operation.GetActivateResult(out var hr, out var activatedInterface);

            Debug.Assert(hr == (uint)HResult.S_OK);

            _result = (T)activatedInterface;

            var setResult = _completionEvent.Set();
            Debug.Assert(setResult != false);
        }

        public T WaitForCompletion()
        {
            var waitResult = _completionEvent.WaitOne();
            Debug.Assert(waitResult != false);

            return _result;
        }
    }

    internal enum HResult : uint
    {
        S_OK = 0
    }

    [ComImport]
    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IAudioEndpointVolume
    {
        [PreserveSig]
        int NotImpl1();

        [PreserveSig]
        int NotImpl2();

        [PreserveSig]
        int GetChannelCount([Out] [MarshalAs(UnmanagedType.U4)] out uint channelCount);

        [PreserveSig]
        int SetMasterVolumeLevel(
            [In] [MarshalAs(UnmanagedType.R4)] float level,
            [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int SetMasterVolumeLevelScalar(
            [In] [MarshalAs(UnmanagedType.R4)] float level,
            [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int GetMasterVolumeLevel([Out] [MarshalAs(UnmanagedType.R4)] out float level);

        [PreserveSig]
        int GetMasterVolumeLevelScalar([Out] [MarshalAs(UnmanagedType.R4)] out float level);

        [PreserveSig]
        int SetChannelVolumeLevel(
            [In] [MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
            [In] [MarshalAs(UnmanagedType.R4)] float level,
            [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int SetChannelVolumeLevelScalar(
            [In] [MarshalAs(UnmanagedType.U4)] uint channelNumber,
            [In] [MarshalAs(UnmanagedType.R4)] float level,
            [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        int GetChannelVolumeLevel(
            [In] [MarshalAs(UnmanagedType.U4)] uint channelNumber,
            [Out] [MarshalAs(UnmanagedType.R4)] out float level);

        [PreserveSig]
        int GetChannelVolumeLevelScalar(
            [In] [MarshalAs(UnmanagedType.U4)] uint channelNumber,
            [Out] [MarshalAs(UnmanagedType.R4)] out float level);

        [PreserveSig]
        int SetMute(
            [In] [MarshalAs(UnmanagedType.Bool)] bool isMuted,
            [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int GetMute([Out] [MarshalAs(UnmanagedType.Bool)] out bool isMuted);

        [PreserveSig]
        int GetVolumeStepInfo(
            [Out] [MarshalAs(UnmanagedType.U4)] out uint step,
            [Out] [MarshalAs(UnmanagedType.U4)] out uint stepCount);

        [PreserveSig]
        int VolumeStepUp([In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int VolumeStepDown([In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

        [PreserveSig]
        int QueryHardwareSupport([Out] [MarshalAs(UnmanagedType.U4)] out uint hardwareSupportMask);

        [PreserveSig]
        int GetVolumeRange(
            [Out] [MarshalAs(UnmanagedType.R4)] out float volumeMin,
            [Out] [MarshalAs(UnmanagedType.R4)] out float volumeMax,
            [Out] [MarshalAs(UnmanagedType.R4)] out float volumeStep);
    }

    [ComImport]
    [Guid("72A22D78-CDE4-431D-B8CC-843A71199B6D")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IActivateAudioInterfaceAsyncOperation
    {
        void GetActivateResult(
            [MarshalAs(UnmanagedType.Error)]out uint activateResult,
            [MarshalAs(UnmanagedType.IUnknown)]out object activatedInterface);
    }

    [ComImport]
    [Guid("41D949AB-9862-444A-80F6-C261334DA5EB")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IActivateAudioInterfaceCompletionHandler
    {
        void ActivateCompleted(IActivateAudioInterfaceAsyncOperation activateOperation);
    }
}

<强>积分

sunius提供的代码有两个主要缺点:

  • 它使用不安全的代码
  • 它在发布模式下无效(应用程序崩溃)

为了摆脱不安全的代码和崩溃,使用了更明确的编组属性并保留了签名(请参阅vannatech源代码)