59

ボタンを押すと音を鳴らす非常に単純なアプリケーションを作成しています。デバイスが無音に設定されている場合、そのボタンはあまり意味がないため、デバイスのオーディオ音量がゼロの場合は無効にしたいと考えています。(その後、音量を上げたときに再度有効にします。)

現在の音量設定を検出し、音量レベルが変化したときに通知/コールバックを取得するための有効な (そして AppStore で安全な) 方法を探しています。音量設定を変更したくありません

ViewControllerこれはすべて、上記のボタンが使用されている場所に実装されています。これは、iOS 4.0.1 および 4.0.2 を実行する iPhone 4 と、4.0.1 を実行する iPhone 3G でテストしました。iOS SDK 4.0.2 と llvm 1.5 で構築されています。(gcc または llvm-gcc を使用しても、何も改善されません。) どちらの方法でも、ビルドの実装中に問題はなく、エラーも警告もありません。静的アナライザーも満足です。

これが私がこれまでに試したことですが、すべて成功しませんでした。

Apple のオーディオ サービスのドキュメントに従って、次のように動作するAudioSessionAddPropertyListenerを登録する必要があります。kAudioSessionProperty_CurrentHardwareOutputVolume

// Registering for Volume Change notifications
AudioSessionInitialize(NULL, NULL, NULL, NULL);
returnvalue = AudioSessionAddPropertyListener (

kAudioSessionProperty_CurrentHardwareOutputVolume ,
      audioVolumeChangeListenerCallback,
      self
);

returnvalueこれは0、コールバックの登録が機能したことを意味します。

悲しいことにaudioVolumeChangeListenerCallback、デバイスの音量ボタン、ヘッドセット クリッカー、リンガーサイレント スイッチを押しても、関数へのコールバックが得られません。

に登録するためにまったく同じコードをkAudioSessionProperty_AudioRouteChange使用すると (WWDC ビデオ、開発者ドキュメント、およびインターウェブ上の多数のサイトで類似のサンプル プロジェクトとして使用されます) 、オーディオ ルートを変更するときに実際にコールバックを取得します (プラグイン/アウトによって)ヘッドセットまたはデバイスのドッキング)。

Dougという名前のユーザーは、既に最大の音量の iPhone 音量変更イベントというタイトルのスレッドを開き、この方法を使用して成功していると主張しました (音量が既に最大に設定されているため、実際には音量が変化しない場合を除きます)。それでも、私にはうまくいきません。

私が試した別の方法は、NSNotificationCenterこのように登録することです。

// sharedAVSystemController 
AudioSessionInitialize(NULL, NULL, NULL, NULL);
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
                                         selector:@selector(volumeChanged:) 
                                             name:@"AVSystemController_SystemVolumeDidChangeNotification" 
                                           object:nil];

これにより、メソッドvolumeChangedSystemVolume変更が通知されるはずですが、実際には通知されません。

一般に、Cocoa で何かを達成しようと懸命に働きすぎると、根本的に間違ったことをしているということがわかっているので、ここで何かを見落としていると思います。現在の音量レベルを取得する簡単な方法がないとは信じがたいですが、Apple のドキュメント、サンプル コード、Google、Apple Developer Forums を使用したり、WWDC 2010 のビデオを見たりしても、見つけることができませんでした。

4

10 に答える 10

69

volumeChanged:メソッドの署名を間違えた可能性はありますか?これは私のために働いて、私のappdelegateに捨てられました:

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(volumeChanged:)
     name:@"AVSystemController_SystemVolumeDidChangeNotification"
     object:nil];
}

- (void)volumeChanged:(NSNotification *)notification
{
    float volume =
    [[[notification userInfo]
      objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"]
     floatValue];

    // Do stuff with volume
}

私のvolumeChanged:結果として音量が変化しなくても、ボタンが押されるたびにメソッドがヒットします(すでに最大/最小になっているため)。

于 2011-06-24T18:25:05.110 に答える
56

The AudioSession API used by some answers here has been deprecated as of iOS 7. It was replaced by AVAudioSession, which exposes an outputVolume property for the system wide output volume. This can be observed using KVO to receive notifications when the volume changes, as pointed out in the documentation:

A value in the range 0.0 to 1.0, with 0.0 representing the minimum volume and 1.0 representing the maximum volume.

The system wide output volume can be set directly only by the user; to provide volume control in your app, use the MPVolumeView class.

You can observe changes to the value of this property by using key-value observing.

You need to ensure your app's audio session is active for this to work:

let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setActive(true)
    startObservingVolumeChanges()
} catch {
    print(“Failed to activate audio session")
}

So if all you need is to query the current system volume:

let volume = audioSession.outputVolume

Or we can be notified of changes like so:

private struct Observation {
    static let VolumeKey = "outputVolume"
    static var Context = 0

}

func startObservingVolumeChanges() {
    audioSession.addObserver(self, forKeyPath: Observation.VolumeKey, options: [.Initial, .New], context: &Observation.Context)
}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if context == &Observation.Context {
        if keyPath == Observation.VolumeKey, let volume = (change?[NSKeyValueChangeNewKey] as? NSNumber)?.floatValue {
            // `volume` contains the new system output volume...
            print("Volume: \(volume)")
        }
    } else {
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
    }
}

Don't forget to stop observing before being deallocated:

func stopObservingVolumeChanges() {
    audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}
于 2015-03-20T16:03:08.290 に答える
6
-(float) getVolumeLevel
{
    MPVolumeView *slide = [MPVolumeView new];
    UISlider *volumeViewSlider;

    for (UIView *view in [slide subviews]){
        if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
            volumeViewSlider = (UISlider *) view;
        }
    }

    float val = [volumeViewSlider value];
    [slide release];

    return val;
}

これで、現在の音量レベルが得られるはずです。1 は最大音量、0 は音量なしです。注: これが機能するために UI 要素を表示する必要はありません。また、現在の音量レベルはヘッドフォンまたはスピーカーに相対的であることに注意してください (つまり、2 つの音量レベルは異なり、これにより、デバイスが現在使用している方が得られます。これは、音量が変化したときの通知の受信に関する質問には答えません.

于 2012-02-04T03:41:01.057 に答える
4

AudioSessionSetActive でオーディオ セッションを開始しましたか

于 2010-09-06T13:05:33.633 に答える
1

他の実装に依存すると思います。たとえば、スライダーを使用して音量を制御する場合は、チェック アクションをUIControlEventValueChanged実行できます。値が 0 の場合は、ボタンを非表示または無効に設定できます。

何かのようなもの:

[MusicsliderCtl addTarget:self action:@selector(checkZeroVolume:)forControlEvents:UIControlEventValueChanged];

voidcheckZeroVolumeは、ボリュームの変更後にトリガーされるため、実際のボリュームの比較を行うことができます。

于 2010-09-06T13:23:33.410 に答える
1

スイフト4

func startObservingVolumeChanges() {
    avAudioSession.addObserver(self, forKeyPath: Observation.VolumeKey, options: [.initial, .new], context: &Observation.Context)
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if context == &Observation.Context {
        if keyPath == Observation.VolumeKey, let volume = (change?[NSKeyValueChangeKey.newKey] as? NSNumber)?.floatValue {
            print("\(logClassName): Volume: \(volume)")
        }
    } else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    }
}

func stopObservingVolumeChanges() {
    avAudioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}

そして、あなたは電話します

var avAudioSession = AVAudioSession.sharedInstance()
try? avAudioSession.setActive(true)
startObservingVolumeChanges()
于 2018-01-19T14:11:02.333 に答える
0

設定→サウンド→「ボタンで変更」にチェックを入れます。オフの場合、音量ボタンを押してもシステムの音量は変化しません。通知が届かないのはそのせいかもしれません。

于 2014-04-17T06:43:03.637 に答える