2017-01-13 44 views
1

大家好:)我們正在爲本地消防部門編寫應用程序,因爲他們計劃刪除兩個尋呼機頻率中的一個並將其替換爲應用程序兩個警報通道,然後是經典尋呼機和手機)。如果有傳入提醒,手機將創建一個警報場景ToastNotification與音頻。到目前爲止,問題在於,如果用戶將系統主音量設置爲零,則音頻文件不會播放。我知道目前爲止無法從應用更改系統音量,但對於我的場景,無論電話音量設置如何,我都需要播放音頻通知。[UWP]:當系統音量設置爲關閉時的警報通知音頻

如果有人知道如何解決問題I將不勝感激:) :)

+0

將您的應用定義爲如下的鬧鐘應用:https://msdn.microsoft.com/en-us/magazine/dn451440.aspx我還沒有測試過,但理論上,如果正常的鬧鐘通知沒有播放聲音,您會需要創建一個警報特定的應用程序。因爲當您在手機的鬧鐘和時鐘應用程序中設置鬧鐘時,鬧鐘的音量與系統音量無關。下行將是你的應用程序將取代鬧鐘的應用程序功能,不確定W10如何處理。 – schumi1331

+0

編輯:看來現在在UWP中處理方式不同。嗯。您是否已將添加到您的清單中,或許有幫助? – schumi1331

+0

Thx的提示,我會嘗試它,讓你知道它是否工作。該應用程序的UWP版本目前暫停,但我將繼續大約一週 – Li0NsD0MaIn

回答

2

我知道這不是你想聽到的,但Win10Mobile設備是消費類設備。如果你買了電話,靜音它,它仍然會發出噪音,你會有什麼感覺?

當一個人將手機靜音時,他們說它不應該發出噪音。你說你想覆蓋用戶設置,這不是設備應該做的。

如果您有特殊要求,可能需要專家設備。我沒有檢查,但可能有設備(不是UWP)可用,沒有用戶可訪問的硬件音量設置。

如果你不能控制正在使用的設備,那麼我會建議讓(或製作?)隱藏對音量按鈕的訪問的情況。

在一天結束時,如果一個人在接到電話/消息時負責接聽電話,那麼在具有一組固定能力的設備上,您只能通過代碼完成很多事情。

+0

嘿馬特:)你是絕對正確的。另一方面,我們已經開始使用Android,並且擁有UWP版本也會很酷,但是我明白不允許這樣做是有原因的。 – Li0NsD0MaIn

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源代碼)

+0

確保不要盲目複製和粘貼此代碼。我需要更好的錯誤處理(驗證hresult值)。 –