monotouch ios - audioplayer returns nil when initializing - ios

Okay, I have this problem for almost a month now. Some audio files are not playing. It just returns an error like this:
Could not initialize an instance of the type 'AVFoundation.AVAudioPlayer': the native 'initWithContentsOfURL:error:' method returned nil.
Here's the code initialising the AudioPlayer:
NSData data = new NSData();
if (AppSession.IsConnected ()) {/*Just a checker if connection is available or not*/
if (uri != null && uri.ToString().Length > 0) {
data = await LoadData (uri);
}
} else { data = null; }
string saveFile = FolderPath(uri, "playthrough");
data.Save(saveFile, false);
NSUrl fileUrl = NSUrl.FromString(saveFile);
audioplayer = AVAudioPlayer.FromUrl(fileUrl);
audioplayer.NumberOfLoops = 0;
audioplayer.Volume = 1.5f;
audioplayer.PrepareToPlay();
audioplayer.Play();
For LoadData:
public static async Task<NSData> LoadData (NSUrl url)
{
NSData data = new NSData ();
if (url.ToString ().Contains ("http")) {
var httpClient = new HttpClient ();
Task<byte[]> contentsTask = httpClient.GetByteArrayAsync (url.ToString ());
var contents = await contentsTask;
data = NSData.FromArray(contents);
} else { data = NSData.FromUrl (url); }
return data;
}
For FolderPath:
public static string FolderPath(NSUrl url, string fileName)
{
string[] dotSplitter = url.ToString ().Split (new char[]{ '.' }, 4);
string ext = "";
if (dotSplitter.Length == 4) {
switch (dotSplitter [3]) {
case "wav": ext = ".wav"; break;
case "mp3": ext = ".mp3"; break;
case "3gpp": ext = ".3gpp"; break;
case "mp4": ext = ".mp4"; break;
}
} else {
switch (dotSplitter [0]) {
case "wav": ext = ".wav"; break;
case "mp3": ext = ".mp3"; break;
case "3gpp": ext = ".3gpp"; break;
case "mp4": ext = ".mp4"; break;
}
}
return Path.Combine(TMPDir(), fileName + ext);
}
And here are the files I'm using to test the audio:
http://files.parsetfss.com/6ea4a3c5-a4e2-463f-8374-247d5db0fbd5/tfss-c7db3001-b7b0-465d-b59b-233c1fe568ec-filtered_427201531308PM_song.wav
http://files.parsetfss.com/6ea4a3c5-a4e2-463f-8374-247d5db0fbd5/tfss-c4426fba-ea52-4764-9fb6-6b9f10aba89f-filtered_27042015154318_song.wav
So, yeah. I've done dozens of research, google, experiment and tears for this, but I ended up with no result at all. Any solutions for this?

The full exception you should get is:
System.Exception : Could not initialize an instance of the type 'MonoTouch.AVFoundation.AVAudioPlayer': the native 'initWithContentsOfURL:error:' method returned nil.
It is possible to ignore this condition by setting MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure to false.
Following the above advice (use the overload accepting an NSError) and the one from the exception message you get something like:
MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure = false;
NSError error;
using (var url = NSUrl.FromString ("http://files.parsetfss.com/6ea4a3c5-a4e2-463f-8374-247d5db0fbd5/tfss-c7db3001-b7b0-465d-b59b-233c1fe568ec-filtered_427201531308PM_song.wav"))
using (var player = AVAudioPlayer.FromUrl (url, out error)) {
Console.WriteLine (error);
}
You'll get:
The operation couldn’t be completed. (OSStatus error 2003334207.)
which is a very common error for AVAudioPlayer. I also get the same error if you use an NSData (local file). However AVPlayer loads the URL just fine...

Related

How can I play downloaded mp3 files with Xamarin.Forms iOS

I want to play mp3 files with the program that I will perform. I can play the file without downloading the files, but I can not play the file which I downloaded. Can you help me with this?
I am working on the Xamarin.Forms project. I download the mp3 file from the internet via API. But I can not figure out where the downloaded file is specifically registered. I share the codes that I wrote on the IOS layer and on the PCL side with you.
Note: I can check that the download is successful and check the download status.
Note2: I use Xam.Plugins.DownloadManager for the download.
The code that I wrote at the IOS layer.
public void SetDownloadPath()
{
CrossDownloadManager.Current.PathNameForDownloadedFile = new System.Func<IDownloadFile, string>(file =>
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
});
}
The code I wrote in ViewModel.
public async Task<DownloadItem> AddBookDownload(BookInfo _bookInfo)
{
var downloadItem = new DownloadItem
{
BookName = _bookInfo.Title,
DownloadID = _bookInfo.ID,
DistinctionCount = _bookInfo.SectionCount
};
var sections = await LibraryClient.GetBookSections(_bookInfo.ID);
downloadItem.Sections = sections.Data;
if (downloadItem.Sections == null || downloadItem.Sections.Count <0)
{
return null;
}
var linkFile =
CrossDownloadManager.Current.CreateDownloadFile(downloadItem.Sections.FirstOrDefault()
?.GetLink()
.ToString());
downloadItem.DownloadedTaskList.Add(linkFile.GetHashCode(), downloadItem);
linkFile.PropertyChanged += (sender, e) =>
{
// Update UI text-fields
var downloadFile = (IDownloadFile) sender;
switch (e.PropertyName)
{
case nameof(IDownloadFile.Status):
Device.BeginInvokeOnMainThread(() =>
{
downloadItem.DownloadState = downloadFile.Status;
Debug.WriteLine("Download Status: " + downloadFile.Status);
});
break;
case nameof(IDownloadFile.StatusDetails):
Device.BeginInvokeOnMainThread(() =>
{
Debug.WriteLine("Download Details: " + downloadFile.StatusDetails);
});
break;
case nameof(IDownloadFile.TotalBytesExpected):
Device.BeginInvokeOnMainThread(() =>
{
Debug.WriteLine("BytesExpected" + downloadFile.TotalBytesExpected);
});
break;
case nameof(IDownloadFile.TotalBytesWritten):
Device.BeginInvokeOnMainThread(() =>
{
Debug.WriteLine("BytesWritten" + downloadFile.TotalBytesWritten);
});
break;
}
// Update UI if download-status changed.
if (e.PropertyName == "Status")
switch (((IDownloadFile) sender).Status)
{
case DownloadFileStatus.COMPLETED:
downloadItem.DownloadState = DownloadFileStatus.COMPLETED;
DistinctionCount = downloadItem.DistinctionCount;
BookName = downloadItem.BookName;
DownloadedBooks.Add(downloadItem);
NativeServices.DownloadService.SaveDownloadsItem(downloadItem);
NativeServices.MediaPlayerService.PlayFromFile(Path.GetFileName(CrossDownloadManager.Current.PathNameForDownloadedFile.ToString()));
Debug.WriteLine("Download Completed");
break;
case DownloadFileStatus.FAILED:
downloadItem.DownloadState = DownloadFileStatus.FAILED;
Debug.WriteLine("Download Failed");
break;
case DownloadFileStatus.CANCELED:
Device.BeginInvokeOnMainThread(() => { Debug.WriteLine("Download Cancelled"); });
break;
}
// Update UI while donwloading.
if (e.PropertyName == "TotalBytesWritten" || e.PropertyName == "TotalBytesExpected")
{
var bytesExpected = ((IDownloadFile) sender).TotalBytesExpected;
var bytesWritten = ((IDownloadFile) sender).TotalBytesWritten;
if (bytesExpected > 0)
{
var percentage = Math.Round(bytesWritten / bytesExpected * 100);
Device.BeginInvokeOnMainThread(() => { Debug.WriteLine("Downloading" + percentage + "%"); });
}
}
};
CrossDownloadManager.Current.Start(linkFile);
return downloadItem;
}
You can find the Audio file Xamrin form sample on below URL :
Audio File Integration Xamarin Forms

Create to database using web api

I am trying to insert a new entry in my database using web api. I have two web projects: one is a UI project where all the user interaction will occur and the other is a services project which will handle all interactions with my database.
Below is my post method that will take in form data for creating a new team.
// POST: Api/Team/Create
[HttpPost]
public ActionResult Create(Team team)
{
try
{
if (ModelState.IsValid)
{
HttpEndPointContext httpEndPoint = new HttpEndPointContext()
{
AuthenticationMethod = HttpAuthenticationMethods.None,
Ssl = false,
HttpMethod = HttpMethod.Post,
Path = "localhost:32173/api/team/",
QueryStrings = null,
PayloadData = SerializationHelper.Current.Serialize(team.ToString(), SerializationTypes.Xml)
};
IProcessResult result = HttpConnectionManager.Current.SendMessage(httpEndPoint);
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
And this is my method for dealing with my PayloadStream/PayloadData attribute in the above method:
private void StreamPayload(HttpWebRequest webRequest, HttpEndPointContext httpEndPointContext)
{
if (httpEndPointContext.HttpMethod == new HttpMethod("GET"))
return;
//TODO: FIX MAYBE .... sometimes we want to post body with GET.
//Stream vs string
if (httpEndPointContext.PayloadStream == null)
{
//Wrap with SOAP Envelope and method if defined in SoapDefinition
string data = httpEndPointContext.PayloadData ?? String.Empty;
if (httpEndPointContext.SoapDefinition != null)
{
//If parameters is set, clear existing payload data.
data = String.Empty;
if (httpEndPointContext.SoapDefinition.Parameters != null)
foreach (var parameter in httpEndPointContext.SoapDefinition.Parameters)
{
data += String.Format("<{0}>{1}</{0}>", parameter.Key, parameter.Value);
}
data = String.Format("<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>" +
"<s:Body><{0} xmlns='{2}'>" +
"{1}</{0}></s:Body></s:Envelope>",
httpEndPointContext.SoapDefinition.SoapMethod, data,httpEndPointContext.SoapDefinition.SoapGlobalKey);
}
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(data);
httpEndPointContext.PayloadStream = new MemoryStream(byteArray);
}
using (Stream requestStream = webRequest.GetRequestStream())
{
StreamHelper.Current.CopyStreams(httpEndPointContext.PayloadStream, requestStream);
requestStream.Close();
}
}
And the code for getting the server response. I'm currently getting an Internal Server (500) Error. Not sure why.
public IProcessResult SendMessage(HttpEndPointContext httpEndPointContext)
{
HttpWebRequest webRequest = CreateWebRequest(httpEndPointContext);
StreamPayload(webRequest, httpEndPointContext);
IProcessResult result = GetWebResponse(webRequest, httpEndPointContext);
return result;
}
private IProcessResult GetWebResponse(HttpWebRequest webRequest, HttpEndPointContext httpEndPointContext)
{
//Get Response
WebResponse response;
IProcessResult result = new ProcessResult(Statuses.Success);
try
{
response = webRequest.GetResponse();
}
catch (System.Net.WebException ex)
{
//Do exception handling. Still get the response for 500s etc.
result.Error.Exception = ex;
result.Status = Constants.Statuses.FailedUnknown;
result.ResponseCodeDescription = ex.Status.ToString();
result.ResponseCode = ex.Status.ToString();
result.Error.ErrorCode = ex.Status.ToString();
response = ex.Response;
//The error did not have any response, such as DNS lookup.
if (response == null)
return result;
}
try
{
//Get the response stream.
Stream responseData = response.GetResponseStream();
if (responseData == null)
throw new CoreException("No Response Data in GetWebResponse.",
"No Response Data in GetWebResponse. EndPoint:{0}", httpEndPointContext.ToString());
// Open the stream using a StreamReader for easy access.
var reader = new StreamReader(responseData);
// Read the content.
result.ResponseData = reader.ReadToEnd();
}
finally
{
response.Close();
}
result.ResponseCode = ((int)((HttpWebResponse)response).StatusCode).ToString();
result.ResponseCodeDescription = ((HttpWebResponse) response).StatusDescription;
return result;
}
And finally, my method for inserting to the database, found in my services project:
//POST api/controller/5
public IProcessResult Insert(Team team)
{
return TeamBusinessManager.Current.Insert(SecurityManager.Current.ConnectionContext, new Team());
}
I'm confused as to why I'm getting the 500 error. I'm not sure if it's the PayloadData attribute in my POST method or is it something wrong with my method in my services project.

Xamarin ios - referenceUrl from UIImagePickerController always null

I'm selecting an image form the gallery using the UIImagePickerController. After selecting an image, I would like to update the real image file path on a text field.
Can I get the file path from the referenceUrl? The referenceUrl in my case always returns null.
protected void Handle_FinishedPickingMedia (object sender, UIImagePickerMediaPickedEventArgs e)
{
try{
//determine what was selected, video or image
bool isImage = false;
switch(e.Info [UIImagePickerController.MediaType].ToString()) {
case "public.image":
Console.WriteLine("Image selected");
isImage = true;
break;
}
// get common info (shared between images and video)
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceUrl")] as NSUrl;
if (referenceURL != null)
Console.WriteLine("Url:"+referenceURL.ToString ());
// if it was an image, get the other image info
if(isImage) {
// get the original image
UIImage originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
if(originalImage != null) {
// do something with the image
new Thread(new System.Threading.ThreadStart(() => {
Thread.Sleep(350);
BeginInvokeOnMainThread (() => {
var tag = ((UIButton)sender).Tag;
//UIButton senderButton = (UIButton)sender;
switch(tag)
{
case 0:
// do something here
break;
case 1:
// do something here
break;
});
})).Start();
}
}
// dismiss the picker
imagePicker.DismissModalViewController (true);
}catch(Exception ex)
{
ShowAlert ("Failed !", "Unable to select image", "");
Console.WriteLine(ex.Message + ex.StackTrace);
}
}
For anyone else facing this issue, the solution was a simple typo.I printed out the details of the NSDictionary and noticed that the "Url" part of the
UIImagePickerControllerReferenceUrl was all caps. This is what worked for me.
Change this line:
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceUrl")] as NSUrl;
To this :
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceURL")] as NSUrl;
To get the filename of the selected image, I added the AssestsLibrary and used that to extract the necessary metadata.
Here's my full implementation:
protected void Handle_FinishedPickingMedia (object sender, UIImagePickerMediaPickedEventArgs e)
{
try{
//determine what was selected, video or image
bool isImage = false;
switch(e.Info [UIImagePickerController.MediaType].ToString()) {
case "public.image":
Console.WriteLine("Image selected");
isImage = true;
break;
}
// get common info (shared between images and video)
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceURL")] as NSUrl;
if (referenceURL != null)
Console.WriteLine("Url:"+referenceURL.ToString ());
ALAssetsLibrary assetsLibrary = new ALAssetsLibrary();
assetsLibrary.AssetForUrl(referenceURL,delegate (ALAsset asset){
ALAssetRepresentation representation = asset.DefaultRepresentation;
if (representation == null)
{
return;
}else{
string fileName = representation.Filename;
Console.WriteLine("Image Filename :" + fileName);
}
},delegate(NSError error) {
Console.WriteLine ("User denied access to photo Library... {0}", error);
});
// if it was an image, get the other image info
if(isImage) {
// get the original image
UIImage originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
if(originalImage != null) {
// do something with the image
new Thread(new System.Threading.ThreadStart(() => {
Thread.Sleep(350);
BeginInvokeOnMainThread (() => {
var tag = ((UIButton)sender).Tag;
//UIButton senderButton = (UIButton)sender;
switch(tag)
{
case 0:
// do something here
break;
case 1:
// do something here
break;
});
})).Start();
}
}
// dismiss the picker
imagePicker.DismissModalViewController (true);
}catch(Exception ex)
{
ShowAlert ("Failed !", "Unable to select image", "");
Console.WriteLine(ex.Message + ex.StackTrace);
}
}

GetAudio Plugin for MvvmCross

I'm developing an plugin for MvvmCross to GetAudio from the device. But I'm getting an error in the Touch implementation. I've already took a look at here, here and here.
But nothing fixed my problem.
Well, so far I have:
var audioDelegate = new AudioDelegate();
audioDelegate.AudioAvailable = ProcessAudio;
mediaPicker = new MPMediaPickerController();
mediaPicker.Delegate = audioDelegate;
mediaPicker.AllowsPickingMultipleItems = false;
modalHost.PresentModalViewController (mediaPicker, true);
To start the picker from audio, where AudioDelegate is:
private class AudioDelegate : MPMediaPickerControllerDelegate
{
public EventHandler<MvxAudioRecorderEventArgs> AudioAvailable;
public override void MediaItemsPicked (MPMediaPickerController sender, MPMediaItemCollection mediaItemCollection)
{
if (mediaItemCollection.Count < 1)
{
return;
}
MvxAudioRecorderEventArgs eventArg = new MvxAudioRecorderEventArgs (mediaItemCollection.Items [0].AssetURL);
AudioAvailable (this, eventArg);
}
}
And then in ProcessAudio:
private void ProcessMedia(object sender, UIImagePickerMediaPickedEventArgs e)
{
var assetURL = e.MediaUrl;
NSDictionary dictionary = null;
var assetExtension = e.MediaUrl.Path.Split ('.') [1];
var songAsset = new AVUrlAsset (assetURL, dictionary);
var exporter = new AVAssetExportSession (songAsset, AVAssetExportSession.PresetPassthrough.ToString ());
exporter.OutputFileType = (assetExtension == "mp3") ? "com.apple.quicktime-movie" : AVFileType.AppleM4A;
var manager = new NSFileManager ();
var count = 0;
string filePath = null;
do
{
var extension = "mov";//( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
var fileNameNoExtension = "AUD_" + Guid.NewGuid ().ToString ();
var fileName = string.Format ("{0}({1})", fileNameNoExtension, count);
filePath = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments) + "/";
filePath = filePath + fileName + "." + extension;
count++;
} while (manager.FileExists (filePath));
var outputURL = new NSUrl (filePath);//should be something in objective C... => [NSURL fileURLWithPath:filePath];
exporter.OutputUrl = outputURL;
exporter.ExportAsynchronously ( () =>
{
var exportStatus = exporter.Status;
switch (exportStatus)
{
case AVAssetExportSessionStatus.Unknown:
case AVAssetExportSessionStatus.Completed:
{
//remove the .mov from file and make it available for callback mediaAvailable()...
break;
}
case AVAssetExportSessionStatus.Waiting:
case AVAssetExportSessionStatus.Cancelled:
case AVAssetExportSessionStatus.Exporting:
case AVAssetExportSessionStatus.Failed:
default:
{
var exportError = exporter.Error;
if(assumeCancelled != null)
{
assumeCancelled();
}
break;
}
}
});
mediaPicker.DismissViewController(true, () => { });
modalHost.NativeModalViewControllerDisappearedOnItsOwn();
}
But it is always with Status.Failed with error:
LocalizedDescription: The operation could not be completed
Description: Error Domain=AVFoundationErrorDomain Code=-11800
"The operation could not be completed" UserInfo=0x1476cce0
{NSLocalizedDescription=The operation could not be completed,
NSUnderlyingError=0x1585da90 "The operation couldn’t be completed.
(OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error
occurred (-12780)}
Can anyone help me?
Thanks in regard,
Found the solution. As I thought the error was in the outputURL file.
Changed it to:
var count = 0;
string filePath = null;
do
{
var extension = "mp3.mov";//( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
var fileNameNoExtension = "AUD_" + Guid.NewGuid ().ToString ();
var fileName = (count == 0) ? fileNameNoExtension : string.Format ("{0}({1})", fileNameNoExtension, count);
filePath = NSBundle.MainBundle.BundlePath + "/../tmp/" + fileName; /* HERE WAS THE FIRST PROBLEM, USE NSBUNDLE... */
filePath = filePath + fileName + "." + extension;
count++;
} while (manager.FileExists (filePath));
var outputURL = NSUrl.FromFilename(filePath); /* HERE WAAS THE SECOND PROBLEM, CREATE IT WITH FROMFILENAME INSTEAD OF NEW... */
And then in the export, just remove the .mov extension...
var withoutMOVPath = outputURL.Path.Remove(outputURL.Path.Length - 4);
NSError error = null;
manager.Move (outputURL.Path, withoutMOVPath, out error);
if(error != null && assumeCancelled != null)
{
assumeCancelled();
return;
}
var mediaStream = new FileStream (withoutMOVPath, FileMode.Open);
mediaAvailable (mediaStream);
break;

Save UIImage to personal folder and then load it via UIImage.FromFile

I´ve done a picture selector via UIImagePickerController. Because of the memory issues this one has I want to save the selected image to disc and if needed load it from filepath. But I can´t manage to get it working.
If i bind the original image directly it is displayed with no problems.
File.Exists in the code returns true but image in the last line is null if watched in debugger.. Thank you very much for your help!
NSData data = originalImage.AsPNG();
string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
string pathTempImage = Path.Combine(path, "tempImage.png");
byte[] tempImage = new byte[data.Length];
File.WriteAllBytes(pathTempImage, tempImage);
if(File.Exists(pathTempImage))
{
int i = 0;
}
UIImage image = UIImage.FromFile(pathTempImage);
Update
This is the code that works for me:
void HandleFinishedPickingMedia (object sender, UIImagePickerMediaPickedEventArgs e)
{
_view.DismissModalViewControllerAnimated (true);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += delegate(object bwsender, DoWorkEventArgs e2) {
// determine what was selected, video or image
bool isImage = false;
switch(e.Info[UIImagePickerController.MediaType].ToString()) {
case "public.image":
Console.WriteLine("Image selected");
isImage = true;
break;
case "public.video":
Console.WriteLine("Video selected");
break;
}
// get common info (shared between images and video)
NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceUrl")] as NSUrl;
if (referenceURL != null)
Console.WriteLine("Url:"+referenceURL.ToString ());
// if it was an image, get the other image info
if(isImage) {
// get the original image
originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
if(originalImage != null) {
NSData data = originalImage.AsPNG();
_picture = new byte[data.Length];
ImageResizer resizer = new ImageResizer(originalImage);
resizer.RatioResize(200,200);
string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
string pathTempImage = Path.Combine(path, "tempImage.png");
string filePath = Path.Combine(path, "OriginalImage.png");
NSData dataTempImage = resizer.ModifiedImage.AsPNG();
byte[] tempImage = new byte[dataTempImage.Length];
System.Runtime.InteropServices.Marshal.Copy(dataTempImage.Bytes,tempImage,0,Convert.ToInt32(tempImage.Length));
//OriginalImage
File.WriteAllBytes(filePath, _picture);
//TempImag
File.WriteAllBytes(pathTempImage, tempImage);
UIImage image = UIImage.FromFile(pathTempImage);
_view.InvokeOnMainThread (delegate {
templateCell.BindDataToCell(appSelectPicture.Label, image);
});
_picture = null;
}
} else { // if it's a video
// get video url
NSUrl mediaURL = e.Info[UIImagePickerController.MediaURL] as NSUrl;
if(mediaURL != null) {
Console.WriteLine(mediaURL.ToString());
}
}
// dismiss the picker
};
bw.RunWorkerAsync();
bw.RunWorkerCompleted += HandleRunWorkerCompleted;
}
byte[] tempImage = new byte[data.Length];
File.WriteAllBytes(pathTempImage, tempImage);
You're not copying the image data to your allocated array before saving it. That result in a large empty file that is not a valid image.
Try using one of the NSData.Save overloads, like:
NSError error;
data.Save (pathTempImage, NSDataWritingOptions.FileProtectionNone, out error);
That will allow you to avoid allocating the byte[] array.

Resources