フォト

最近のトラックバック

無料ブログはココログ

« ロボットの国・日本 | トップページ | うるせー!!!! »

2011年4月28日 (木)

AVAudioRecorderDelegateについて

忘備録、というか、プログラムで困ったことがありまして珍しく、技術的なことについて記述します。

iPhone向けにアプリを作っており、特に録音・録画するためのアプリを作っています。
そのなかで、「AVAudioRecorderDelegate」というものを使っているのですが、この中で定義されちている、「audioRecorderBeginInterruption」の仕様がいつの間にか変更されてしまっていたらしく、急ぎ、プログラムを直した次第。

今回、修正したバグは、かなり致命的。

他の録音アプリで、対応してるものは見たことがないのですが、実は、録音中に着信があった場合、自動で一時停止し、電話、もしくは着信が終わったら、録音を再開する仕組みが盛り込まれております。
が、今日気がついたのですが、これが使えなくなっていたのです。

iPhone自体、着信があるとどんな状況であろうと、一時中断、もしくは、強制終了させてしまいます。しかしながら、そのためにデータが保存できなかったり、編集中も文章が消えてしまったりするおそれがあります。
そのため、iPhoneでは、アプリ側に、「割り込み処理」が入ったことを通知する仕組みがあり、その通知があった場合、データを一時的に保存するなどの処理を開発者側が組み込めるようになっております。

今回、問題になったaudioRecorderBeginInterruption、audioRecorderEndInterruptionもその、割り込み処理の一部。
これらを用いて、録音中であっても自動で一時停止、録音の再開を実現させていた次第。

今までは、録音を開始すると、「音をファイルにする」処理が実行され、割り込みがあった場合、一時停止を行い、終わったら再開する、でよかったのです。

しかしながら、その流れが失われ、「音をファイルにする」処理が実行され、割り込みがあった場合、「音をファイルにする」処理を一時停止、そして、なぜか新しく、「音をファイルにする」処理を作り、録音を続けるような流れになっていたのです。
では、最初の「音をファイルにする」処理はどうなるのか? 新しい「音をファイルにする処理」によって上書きされてしまい、無くなってしまうのです。

「 iOS 4 Programming CookBook 」という本によれば、確かに、着信などの割り込み処理があった場合、新しく処理を創りだしてしまうことが書かれており、その回避方法として、もとの「音をファイルにする」処理を、指定してプログラムを書かないとだめだよん、

って書いてありました。
ちなみに、うまくいきませんでした。

おそらく蓄積したデータを引き継がずに、インスタンス自体をコピーしている模様。

実際にコードを書いてみよう。

BOOL isRecording =FALSE;

- (void)viewDidLoad {

   NSURL *url = [NSURL alloc] initFileURLWithPath : ファイルパス]

    NSError *error = [[NSError alloc] init];
    recorder = [[AVAudioRecorder alloc]initWithURL:url
                                    settings:nil
                                    error:&error];

    [ recorder record ];

}

// 割り込みが入った際の処理を書く。録音中は一時停止になる。

-(void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder{

}

// 割り込みが終わった際の処理を書く
-(void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder{
    if  ( isRecording ) {
        [recorder record]; // 割り込みが終わるので、録音を再開する。

    }         

}

以前はこれで、割り込みが入った際に一時停止、割り込み処理が終わったら、録音を再開してくれていた。

しかし、今では通用しない。録音を再開するが、電話が掛かってくる前の録音の内容は失われてしまう。

海外で出版されている最新の書籍によると、インスタンスが上書きされるので、それまで録音していたインスタンスを指定して、再開するように、と書かれていた。

インスタンス名で解決できるかと思ったができなかった・・・。仕方ないので、この手法は使わないようにしました。

そこで、使ったのが「AVAudioSessionDelegate」。下記のコードで代替を行った。

-(void)setAudioRecordingSession{

    AudioSessionInitialize(NULL, NULL, interruption, self);

}

static void interruption(void *inClientData, UInt32 inInteruputionState) {
    AVAudioRecorderViewController *controller = inClientData;
   
    if ( isRecording ){
        if(inInteruputionState == kAudioSessionBeginInterruption){
             [ controller.recorder pause];            
        }else{
            // 割り込み終了
             [ controller.recorder record];          
        }
    }
}

これも、割り込みが発生した際に実行されるコードである。これで、インスタンスが上書きされることなく、録音を一時停止、割り込み終了時に、再開する、という機能を実現させることができた。

今回のようなことは、たびたびあると困るのだが・・・。

« ロボットの国・日本 | トップページ | うるせー!!!! »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/144298/51512298

この記事へのトラックバック一覧です: AVAudioRecorderDelegateについて:

« ロボットの国・日本 | トップページ | うるせー!!!! »

最近の写真