web-dev-qa-db-ja.com

AVAudioPlayerを使用してiPhoneのリング/サイレント/ミュートスイッチを検出できない

リング/サイレントスイッチがアクティブかどうかを検出するために、これらの方法を使用してみました。

プログラムでiPhoneのミュートスイッチを検知する方法は?

AVAudioSessionカテゴリがドキュメントの指示どおりに機能しない

しかし、私のiPhone 4では、「状態」の値は常に「スピーカー」です(CFStringGetLength(state)によって返される長さの値は常に7です)。誰かがこの方法をうまく使用しましたか?その場合、どの種類のデバイスとSDKバージョンを使用しますか?

私はそれを次のように呼んでいます:


- (BOOL)deviceIsSilenced {
    CFStringRef state;
    UInt32 propertySize = sizeof(CFStringRef);
    OSStatus audioStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
    if (audioStatus == kAudioSessionNoError) {
        NSLog(@"audio route: %@", state) // "Speaker" regardless of silent switch setting, but "Headphone" when my headphones are plugged in
        return (CFStringGetLength(state) <= 0);
    }
    return NO;
}

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    audioSession.delegate = self;
    [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    [audioSession setActive:YES error:nil];
    NSLog(@"muted? %i", [self deviceIsSilenced]);
    ...
}

電話の物理的なスイッチが切り替わると、他の(より正確な)kAudioSessionPropertyイベントが発生するのではないかと考えていました。誰かアイデアはありますか?

ちなみに、[AVAudioSession sharedInstance]でAVAudioSessionCategoryAmbientカテゴリを使用しています。

更新:さまざまなオーディオカテゴリと他の少数のオーディオセッションプロパティを使用してみましたが、スイッチをミュート/ミュート解除したときに何も起動しないようです。 :(

1月。 2014年1月1日更新:これはちょっとしたハックで、iPhone 5Sでマルチタスクを実行しているときにクラッシュしましたが、 SoundSwitch ライブラリがサイレントスイッチを検出したい場合は、新しく受け入れられた回答が適切です。 iOS 7でも動作します。

31
taber

このVSsilentSwitchライブラリを調べました。
私にとっては機能しませんでした(実際にオーディオを使い始めても機能しません)。
私は彼がどうやってそれをしたのかを考えていたところ、私たちが沈黙しているときに音が鳴り始めるとほぼ同時にオーディオ完了呼び出しが呼び出されていることに気付きました。
もう少し具体的に:
AudioServicesPlaySystemSoundを使用して再生されているシステムサウンドは、開始するとすぐに再生を完了します。
もちろん、これはサイレントスイッチを尊重するオーディオカテゴリでのみ機能します(デフォルトのAVAudioSessionCategoryAmbientはそれを尊重します)。
つまり、再生から完了までの時間を確認しながら、できればサイレントサウンドのシステムサウンドを作成し、何度も繰り返し再生するのがコツです(AudioServicesAddSystemSoundCompletion)。
完了プロシージャがすぐに呼び出される場合(許可someしきい値)-サイレントスイッチがオンであることを意味します。
このトリックには多くの注意事項がありますが、最大の問題は、すべてのオーディオカテゴリでは機能しないということです。
アプリがバックグラウンドでオーディオを再生する場合-バックグラウンドでこのテストを停止することを確認してください。そうしないと、アプリはバックグラウンドで永久に実行されます(Appleによっても拒否されます)。

3
Moshe Gottlieb

さて、私は開発者フォーラムの誰かのおかげで答えを見つけました、そしてあなたたちはみんなそれが好きではないでしょう!

これについてAppleから返信がありました。

彼らは、ハードウェアのミュートスイッチを検出する方法を提供していないし、提供したこともないと述べています。

:(

IMOサイレントスイッチを検出して、オンになっていることを忘れた場合にユーザーに通知することには間違いなく価値があります...音が聞こえず、サイレントスイッチが原因であると不満を言う人がいました。しかたがない。

PS:Appleでこの機能を追加したい場合(そしてもちろんそうです!)) http://bugreport.Apple.com/ にある「iPhone SDK」の「拡張」バグレポート

更新:ミュートスイッチのステータスを確認する正式な方法はまだありませんが、「SoundSwitch」と呼ばれる回避策/ライブラリがあり、騙す。リンクの新しい承認済み回答を確認してください。

29
taber

「しかし、もし誰かがこのAudioSessionProperty_AudioRouteDescriptionの使い方を教えてくれれば、報奨金は当然のことです。」

まあ、ちょうどNSLog()結果とあなたが得る

routes: {
    "RouteDetailedDescription_Inputs" =     (
    );
    "RouteDetailedDescription_Outputs" =     (
                {
            "RouteDetailedDescription_PortType" = Speaker;
        }
    );
}

残念ながら、iPad2/OS 5.0でも同じ結果が得られます。したがって、機能的にはkAudioSessionProperty_AudioRouteと同等であるように見え、喜びはありません。

開発者用ボードを見ると、これが頻繁に発生する問題であることがわかります。

「7月にこの問題をrdar:// 9781189で報告しましたが、GMにはまだ問題が残っています。」

だからそう...確かにあなたはSOLこれは5.0でこれをしているようです。

補遺:

「しかし、ログに記録しているそのCFDictionaryはどうですか。「RouteDetailedDescription_PortType」キーにアクセスするにはどうすればよいですか?」

無料のブリッジはあなたの友達です。

  CFDictionaryRef asCFType = nil;
  UInt32 dataSize = sizeof(asCFType);
  AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &asCFType);
  NSDictionary *easyPeasy = (NSDictionary *)asCFType;
  NSDictionary *firstOutput = (NSDictionary *)[[easyPeasy valueForKey:@"RouteDetailedDescription_Outputs"] objectAtIndex:0];
  NSString *portType = (NSString *)[firstOutput valueForKey:@"RouteDetailedDescription_PortType"];
  NSLog(@"first output port type is: %@!", portType);

作り出す

最初の出力ポートタイプは、スピーカーです。

多くの一般的なCFTypeは、より便利なタイプにブリッジされます。

http://developer.Apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html

さて、上記のように辞書から魔法の呪文のキャストが何か役立つものを正しく推測するには少し練習が必要です。これらの行に沿ったクラスダンプヘルパーは、それに慣れるのに役立ちます。

  - (void)whatsInThis:(CFDictionaryRef)thingy
  {
     NSDictionary *dict = (NSDictionary *)thingy;
     for (NSString *key in dict.allKeys)
     {
        id value = [dict valueForKey:key];
        NSLog(@"key: %@ value type %@", key, [value class]);
        if ([value isKindOfClass:[NSArray class]])
        {
           NSArray *array = (NSArray *)value;
           for (id item in array)
           {
              NSLog(@" -- object type %@", [item class]);
              if ([item isKindOfClass:[NSDictionary class]])
                 [self whatsInThis:item];
           }
        }
     }
  }

これは、手元の辞書で生成されます(明確にするためにインデントを追加)

key: RouteDetailedDescription_Inputs value type __NSCFArray
key: RouteDetailedDescription_Outputs value type __NSCFArray
  -- object type __NSCFDictionary
    key: RouteDetailedDescription_PortType value type __NSCFString

これにより、元のログから何を推測できたかを確実に知ることができ、NSLogは()内の配列と{}内のディクショナリを表示するため、正しいキャストが非常に推測しやすいことがわかります。ただし、一部のCFType構造は、それよりも解析が困難です。

11
Alex Curylo

あなたは間違った印象を持っていると思います。ルートはそれが行くところです。音量レベルを知りたい。使用する kAudioSessionProperty_CurrentHardwareOutputVolume

0
slf

このライブラリが見つかりました http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115

Appleそれを許可しますか?それはオーディオと電話の設定でいくつかの黒魔術を行う500Kbライブラリです

0
Carl D'Halluin

OK、CMD +クリックを使用してkAudioSessionProperty_AudioRouteをフォローした後、これを見つけました:(

/*!
 @enum           AudioSession audio categories states
 @abstract       Deprecated AudioSession properties
 @constant       kAudioSessionProperty_AudioRoute 
 Deprecated in iOS 5.0; Use kAudioSessionProperty_AudioRouteDescription 
 */
enum {
    kAudioSessionProperty_AudioRoute                            = 'rout',   // CFStringRef      (get only)        
};

kAudioSessionProperty_AudioRouteDescriptionを使用する必要があることがわかりましたが、この男はCFDictionaryRefまたは何かを返します。どうすれば対処できるかまったくわかりません...

誰もkAudioSessionProperty_AudioRouteDescriptionの使い方を教えてくれない場合に備えて、これを答えにしました。そこで、私の答えを受け入れようとします...

ただし、これをkAudioSessionProperty_AudioRouteDescriptionの使用方法を示すことができる場合、報奨金は当然のことです。

編集:

明らかに、これはiOS 5の問題です。あまりに明白に見えたので、私はこれを以前に述べませんでしたが、それから、私が意味を理解すれば、検索エンジンにはそれほど明白ではないかもしれないと思いました。

そのため、参照されている廃止された値のため、iOS 5はiPhoneのサイレント/ミュートスイッチでは機能しません。

0
Mazyod

DeviceIsSilenced内のAudioSessionGetPropertyの呼び出しの上にこの行を挿入してみてください

AudioSessionInitialize(NULL、NULL、NULL、NULL);

次に、スイッチがダウンすると空の文字列が返されるようになります(ただし、BTヘッドセットやアクセサリが接続されている場合は、ヘッドフォンやその他の状態が表示されます)。

FWIW実際のスイッチが移動されたときに起動するパブリックAPIには何もないと思います。

0
flake