Is it possible to record audio in iOS with Codenam

2019-05-21 00:49发布

问题:

My app features a button to record audio (and another to play it back when the recording is over). I send the recorded audio files on a server. On Android the files is recorded as .amr (mime type audio/amr) and can be played back.

On iOS however the file can neither be played back on the device (iPhone 4 or 4S) nor on a computer. ffmpeg -i reports

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x2fac120] moov atom not found
9gMjOnnmsj9JJZR3.m4a: Invalid data found when processing input

Please note that VLC cannot play it either.

I give the m4a extension because Voice recorder uses it (along with aac codec).

Here is the code I use (mostly based on https://github.com/codenameone/CodenameOne/blob/master/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java#L2768-L2794 ) :

audioMemoPath = ParametresGeneraux.getWRITABLE_DIR() + "AudioMemo-"
            + System.currentTimeMillis() + 
            (Display.getInstance().getPlatformName().equals("and")
            ? ".amr"
            : ".m4a");
audioMemoMimeType = MediaManager.getAvailableRecordingMimeTypes()[0];

audioMemoRecorder = MediaManager.createMediaRecorder(audioMemoPath, audioMemoMimeType);

// If the permission audio has not been granted 
// the audiomemorecoreder will be null
     if (audioMemoRecorder != null) {
           audioMemoRecorder.play();
           boolean b = Dialog.show("Recording", "", "Save", "Cancel");
           audioMemoRecorder.pause();
           audioMemoRecorder.cleanup();

            ...
        }

Moreover if I display the available mime types on iOS, it yields "audio/amr" which I doubt according to all the posts I could read that tell you amr is not supported on iOS. Looking at the source it appears amr is the by default mime type because it is always returned :

/**
 * Gets the available recording MimeTypes
 */ 
public String [] getAvailableRecordingMimeTypes(){
    return new String[]{"audio/amr"};
}

So my question : is it possible to record audio on iOS, and if it is, how can it be done ?

Any help appreciated,

回答1:

Have you looked at the Capture class? That seems to be more straightforward.

https://www.codenameone.com/javadoc/index.html



回答2:

Ok I got it working by overloading some methods of the MediaManager, namely getAvailableRecordingMimeTypes() and also createMediaRecorder() to prevent it from using its getAvailableRecordingMimeTypes method.

Here is the code for getAvailableRecordingMimeTypes():

    /**
 * Normally the method returns amr even for ios. So we overload the original
 * method to return aac on ios.
 * @return 
 */
public static String[] getAvailableRecordingMimeTypes() {
    if (Display.getInstance().getPlatformName().equals("ios")) {
        return new String[]{"audio/aac"};
    } else {
        return new String[]{"audio/amr"};
    }

}

createMediaRecorder() is left as is (copied without changes).

Now it is possible to record audio in iOS and play it back in both iOS and Android!