Question

I'm developing a plugin to record audio for Droid, Touch and Phone projects. I did it in the .Droid project, and it is perfect, working 100%.

In .Touch, I have to implement my ViewController, and this one, will record the audio, and soon it is done, it has to return the mediaFile back.

What I've done so far is:

Plugin Interface

public interface IMvxAudioChooserService
{
    void RecordAudio(Action<Stream> audioAvailable, Action assumeCancelled);
}

Plugin Touch Implementation

public class MvxAudioChooserService: MvxTouchTask, IMvxMultimediaChooserService
{
    public MvxAudioChooserService()
    {
        modalHost = Mvx.Resolve<IMvxTouchModalHost>();
    }
    public void RecordAudio(Action<Stream> audioAvailable, Action assumeCancelled)
    {
        var recordAudioViewController = new MvxRecordAudioViewController ();
        recordAudioViewController.AudioAvailable = ProcessAudio;
        modalHost.PresentModalViewController (recordAudioViewController, true);
    }
    public void ProcessAudio(object sender, MvxRecordAudioViewController e)
    {
        //getaudiofromMediaFile
    }
}

MvxAudioRecorderViewController

public partial class MvxRecordAudioViewController : MvxViewController
{
    private AVAudioRecorder audioRecorder;
    private NSDictionary mediaSettings;
    private NSError audioError = new NSError ();
    private NSUrl mediaURL;
    private Stopwatch stopWatch;
    public string FolderName;
    public EventHandler<MvxAudioRecorderEventArgs> AudioAvailable;


    public MvxRecordAudioViewController () : base ("MvxRecordAudioViewController", null)
    {
        SetDictionarySettingsForAudio ();
    }


    private void SetDictionarySettingsForAudio()
    {
        //Set up the NSObject Array of keys that will be combined with the values to make the NSDictionary
        NSObject[] keys = new NSObject[]
        {
            AVAudioSettings.AVSampleRateKey,
            AVAudioSettings.AVFormatIDKey,
            AVAudioSettings.AVNumberOfChannelsKey,
            AVAudioSettings.AVLinearPCMBitDepthKey,
            AVAudioSettings.AVLinearPCMIsBigEndianKey,
            AVAudioSettings.AVLinearPCMIsFloatKey
        };

        NSObject[] values = new NSObject[]
        {
            NSNumber.FromFloat (44100.0f), //Sample Rate
            NSNumber.FromInt32 ((int)MonoTouch.AudioToolbox.AudioFormatType.MPEG4AAC), //AVFormat
            NSNumber.FromInt32 (2), //Channels
            NSNumber.FromInt32 (16), //PCMBitDepth
            NSNumber.FromBoolean (false), //IsBigEndianKey
            NSNumber.FromBoolean (false) //IsFloatKey
        };

        mediaSettings = NSDictionary.FromObjectsAndKeys (values, keys);
    }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        // Perform any additional setup after loading the view, typically from a nib.
    }

    partial void Record (MonoTouch.Foundation.NSObject sender)
    {
        var session = AVAudioSession.SharedInstance();

        NSError error = null;
        session.SetCategory(AVAudioSession.CategoryRecord, out error);
        if(error != null)
        {
            Console.WriteLine(error);
            return;
        }

        session.SetActive(true, out error);
        if(error != null)
        {
            Console.WriteLine(error);
            return;
        }

        if(!PrepareAudioRecording())
        {
            isRecording.Text = "Error preparing";
            return;
        }

        if(!audioRecorder.Record())
        {
            isRecording.Text = "Error preparing";
            return;
        }

        this.stopWatch = new Stopwatch();
        this.stopWatch.Start();
        this.isRecording.Text = "Recording";
        this.recordButton.Enabled = false;
        this.stopButton.Enabled = true;
    }

    partial void Stop (MonoTouch.Foundation.NSObject sender)
    {
        audioRecorder.Stop ();
        AudioAvailable.Invoke (this, new MvxAudioRecorderEventArgs(this.mediaURL));
        DismissViewController (true, () => {});
    }

    bool PrepareAudioRecording()
    {
        //Declare string for application temp path and tack on the file extension
        this.mediaURL =  NSUrl.FromFilename(NSBundle.MainBundle.BundlePath + ((FolderName != "") ? "/" + FolderName : "") + "/AUD" + Guid.NewGuid() + ".aac");

        //Set recorder parameters
        NSError error;
        audioRecorder = AVAudioRecorder.ToUrl(mediaURL, mediaSettings, out error);
        if((audioRecorder == null) || (error != null))
        {
            Console.WriteLine(error);
            return false;
        }

        //Set Recorder to Prepare To Record
        if(!audioRecorder.PrepareToRecord())
        {
            audioRecorder.Dispose();
            audioRecorder = null;
            return false;
        }

        audioRecorder.FinishedRecording += delegate (object sender, AVStatusEventArgs e) {
            audioRecorder.Dispose();
            audioRecorder = null;
            Console.WriteLine("Done Recording (status: {0})", e.Status);
        };

        return true;
    }

    public class MvxAudioRecorderEventArgs : EventArgs
    {
        public NSUrl MediaUrl;

        public MvxAudioRecorderEventArgs(NSUrl mediaUrl)
        {
            this.MediaUrl = mediaUrl;
        }
    }
}

But then, when calling audioService.RecordAudio(), it is not opening the viewcontroller, and in output it is tracing:

 Request is null - assuming this is a TabBar type situation where ViewDidLoad is called during construction... patching the request now - but watch out for problems with virtual calls during construction

Thanks in regards, Gabriel

Was it helpful?

Solution

Since your recording ViewController is not using any binding and doesn't have a ViewModel, then why not just inherit from UIViewController instead of MvxViewController - that will mean MvvmCross doesn't try to look up a MvxViewModelRequest or a ViewModel for it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top