iOS에서 오디오 볼륨 레벨 및 볼륨 변경 알림을받는 방법은 무엇입니까?
저는 버튼을 눌렀을 때 소리를내는 아주 간단한 애플리케이션을 작성하고 있습니다. 이 버튼은 장치가 무음으로 설정되어있을 때 의미가 없기 때문에 장치의 오디오 볼륨이 0 일 때 비활성화하고 싶습니다. (그리고 나중에 볼륨이 다시 크랭크되면 다시 활성화합니다.)
현재 볼륨 설정 을 감지 하고 볼륨 레벨이 변경 될 때 알림 / 콜백을받을 수 있는 작동하는 (및 AppStore 안전한) 방법을 찾고 있습니다. 나는 볼륨 변경하지 않으려는 설정.
이 모든 것은 내 ViewController
버튼이 사용되는 곳 에서 구현 됩니다. iOS 4.0.1 및 4.0.2를 실행하는 iPhone 4와 4.0.1을 실행하는 iPhone 3G에서 이것을 테스트했습니다. llvm 1.5와 함께 iOS SDK 4.0.2로 빌드되었습니다. (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];
이것은 내 방법 volumeChanged
에 SystemVolume
변경 사항을 알려 주지만 실제로는 그렇게하지 않습니다.
코코아로 무언가를 달성하기 위해 너무 열심히 일한다면 근본적으로 잘못된 일을하고 있다는 공통의 믿음이 있기 때문에 여기서 무언가를 놓칠 것으로 예상됩니다. 현재 볼륨 수준 을 얻는 간단한 방법 이 없다고 믿기는 어렵지만 Apple의 문서, 샘플 코드, Google, Apple Developer Forums를 사용하거나 WWDC 2010 비디오를 시청하여 찾을 수 없었습니다.
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 : 결과적으로 볼륨이 변경되지 않더라도 버튼을 누를 때마다 메서드가 히트합니다 (이미 최대 / 분에 있기 때문에).
AudioSession
여기에 몇 가지 답변에 의해 사용되는 API는하여 교체 된 아이폰 OS 7의로 사용되지 않습니다 AVAudioSession
노출하는, outputVolume
시스템 전체 출력 볼륨에 대한 속성을. 이는 KVO를 사용하여 문서에서 지적한 것처럼 볼륨이 변경 될 때 알림을 수신하는 것을 관찰 할 수 있습니다.
0.0에서 1.0 사이의 값으로 0.0은 최소 볼륨을 나타내고 1.0은 최대 볼륨을 나타냅니다.
시스템 전체 출력 볼륨은 사용자 만 직접 설정할 수 있습니다. 앱에서 볼륨 제어를 제공하려면 MPVolumeView 클래스를 사용하십시오.
키-값 관찰을 사용하여이 속성 값의 변화를 관찰 할 수 있습니다.
이 작업을 수행하려면 앱의 오디오 세션이 활성 상태인지 확인해야합니다.
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
startObservingVolumeChanges()
} catch {
print(“Failed to activate audio session")
}
따라서 현재 시스템 볼륨을 쿼리하기 만하면됩니다.
let volume = audioSession.outputVolume
또는 다음과 같이 변경 사항에 대한 알림을받을 수 있습니다.
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)
}
}
할당이 해제되기 전에 관찰을 중단하는 것을 잊지 마십시오 .
func stopObservingVolumeChanges() {
audioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}
-(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 요소를 표시 할 필요가 없습니다. 또한 현재 볼륨 레벨은 헤드폰 또는 스피커와 관련이 있습니다 (즉, 두 볼륨 레벨이 다르므로 현재 사용중인 기기가 무엇이든 알 수 있습니다. 이는 볼륨 변경 알림 수신에 관한 질문에 대한 답변이 아닙니다.
AudioSessionSetActive로 오디오 세션을 시작 했습니까?
Stuart의 탁월한 답변의 Swift 3 버전 :
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
startObservingVolumeChanges()
}
catch {
print("Failed to activate audio session")
}
let volume = audioSession.outputVolume
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)
}
}
다른 구현에 달려 있다고 생각합니다. 예를 들어 사운드 볼륨을 제어하기 위해 슬라이더를 사용하는 UIControlEventValueChanged
경우 확인 작업을 수행 할 수 있으며 값이 0이면 단추를 숨기거나 비활성화 할 수 있습니다.
다음과 같은 것 :
[MusicsliderCtl addTarget:self action:@selector(checkZeroVolume:)forControlEvents:UIControlEventValueChanged];
where void checkZeroVolume
could do the comparing of the actual volume since it is triggered after any volume change.
Adding on to Stuart's answer using AVAudioSession to account for some changes in Swift 3. I hope the code will make it clear as to where each component goes.
override func viewWillAppear(_ animated: Bool) {
listenVolumeButton()
}
func listenVolumeButton(){
let audioSession = AVAudioSession.sharedInstance()
do{
try audioSession.setActive(true)
let vol = audioSession.outputVolume
print(vol.description) //gets initial volume
}
catch{
print("Error info: \(error)")
}
audioSession.addObserver(self, forKeyPath: "outputVolume", options:
NSKeyValueObservingOptions.new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume"{
let volume = (change?[NSKeyValueChangeKey.newKey] as
NSNumber)?.floatValue
print("volume " + volume!.description)
}
}
override func viewWillDisappear(_ animated: Bool) {
audioSession.removeObserver(self, forKeyPath: "outputVolume")
}
Swift 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)
}
and then you call
var avAudioSession = AVAudioSession.sharedInstance()
try? avAudioSession.setActive(true)
startObservingVolumeChanges()
Go into settings->sounds and check 'Change with Buttons'. If it's off the system volume won't change when pressing the volume buttons. Maybe that's the reason why you didn't get notified.
ReferenceURL : https://stackoverflow.com/questions/3651252/how-to-get-audio-volume-level-and-volume-changed-notifications-on-ios
'IT박스' 카테고리의 다른 글
문자열에서 "두 번 나타나는 한 글자"찾기 (0) | 2020.12.30 |
---|---|
가져 오기 : JSON 오류 객체로 약속 거부 (0) | 2020.12.29 |
.Contains가 느린 이유는 무엇입니까? (0) | 2020.12.29 |
std :: string을 std :: vector에 복사하는 방법 (0) | 2020.12.29 |
Jekyll과 함께 Live Reload 사용 (0) | 2020.12.29 |