I am getting an image stream from TakePhotoAsync Method? Where do I need to change the code?
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("Alert", "No camera is available!", "OK");
return;
}
camreaFile = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Small,
//SaveToAlbum = true,
Directory = "Sample",
Name = "test.jpg"
});
//mediaFile = await CrossMedia.Current.TakePhotoAsync();
if (camreaFile == null)
return;
fileName.Text = camreaFile.AlbumPath;
await DisplayAlert("File Location", camreaFile.Path, "OK");
image.Source = ImageSource.FromStream(() =>
{
var stream = camreaFile.GetStream();
//camreaFile.Dispose();
return stream;
});
--Pass parameter for server
if(mediaFile !=null)
{
MultipartFormDataContent content = new
MultipartFormDataContent();
content.Add(new StringContent(AppSetting.UserName),
"userId");
content.Add(new StringContent(remark), "remarks");
content.Add(new StringContent(AppSetting.ConsignmentNumebr), "consignmentNo");
content.Add(new StringContent(AppSetting.TaskId), "jobId");
content.Add(new StreamContent(cameraFile.GetStream()),"\"file\"",$"\"{AppSetting.ConsignmentNumebr + ".png"}\"");
var httpClient = new HttpClient();
var uploadServiceBaseAddress = "myserver/api/UploadContainerImage/"; var uploadResponseMessage = await httpClient.PostAsync(uploadServiceBaseAddress, content);uploadResponseMessage.Content.ReadAsStringAsync(); }
--I expect the output that successfully reaches the server.
Dispose of the Media file after you send it to the server to avoid this exception.
If you do that before you are sending it to the server, of course, it will give you an ObjectDisposedException
If you want to dispose of this variable just do it after the service call something like below:
FooServiceMethod();
mediaFile.Dispose();
Related
I am using ImageCropper and MediaPlugin to Upload images. However I have problem getting the image after cropping the image.
string imagefile;
protected void OnClickedRectangle(object sender, EventArgs e)
{
new ImageCropper()
{
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
});
}
}.Show(this);
}
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var content = new MultipartFormDataContent();
content.Add(new StreamContent(imageFile), "files", imagefile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxx/api/Upload", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
However how can I get the Image to upload. note that view_imageavatar still shows the image after cropping. Tks!
Update...
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var fileStream = File.OpenRead(imageFile);
var fileContent = new StreamContent(fileStream);
var content = new MultipartFormDataContent();
content.Add(fileContent, "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
It still doesn't work?
Update 2
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var upfilebytes = File.ReadAllBytes(imageFile);
var ms = new MemoryStream(upfilebytes);
var content = new MultipartFormDataContent();
content.Add(new StreamContent(ms), "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
-> It still can't upload photos through the API?
However I try not to use ImageCropper. I upload directly.
async void edit_avatar_Tapped(object sender, EventArgs e)
{
var file = await MediaPicker.PickPhotoAsync();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(await file.OpenReadAsync()), "files", file.FileName);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
string a = responses.StatusCode.ToString();
}
--> Then it works fine, the image is uploaded through the API
Does the image load from content.Add(new StreamContent(ms), "files", imageFile); it doesn't work with API? Looking for solutions from everyone.
Have you actually checked what StreamContent takes as arguments?
It takes a Stream not a path to a file.
You need to open the file first like so:
using var fileStream = File.Open(imageFile);
using var fileContent = new StreamContent(fileStream);
Have you tried something like that?
I'm trying to use the Azure OCR API in Xamarin Forms. Here is the important bits of code. I'm using the ComputerVisionClient .net client
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
SaveToAlbum = false
});
Img = new Image
{
Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
return stream;
}),
};
using (var photoStream = file.GetStream())
{
var text = await _client.RecognizePrintedTextInStreamAsync(true, photoStream);
}
The Img is bound to an image on the view and it shows up when I take a picture so there is definetly an image. However RecognizePrintedTextInStreamAsync returns back "System.IO.FileNotFoundException: 'Invalid Image'" and I'm not sure why. Any ideas?
Edit. Added _client code
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}
Called from my constructor and set as a global var
_client = Authenticate(endpoint, subscriptionKey);
Thanks
I am trying to capture an image/pick up an image from gallery in Xamarin Forms app. I have installed the nuget manager > Birdie.MediaPlugin. During On click on the button in the Register page throws below error;
Plugin.Media.Abstractions.MediaPermissionException: <Timeout exceeded getting exception details Could someone please advise where should we add persmission in Xamarin.Forms app ?
// Register.xaml:
<Image x:Name="imageDisplay" />
<Button x:Name="uploadButton"
Text="Upload Image" Clicked="UploadButton_Clicked"/>
// PlayerDetails.cs
public ImageSource Source { get; internal set; }
//Register.xaml.cs
PlayerDetails myDetails;
public Register(PlayerDetails playD)
{
InitializeComponent();
BindingContext = myDetails;
}
private async void UploadButton_Clicked(object sender, EventArgs e)
{
//myDetails.Image = new Image();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
var status = await GetPermissions();
if(status == true)
{
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
Directory = "Sample",
Name = "flower1.jpg"
});
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
myDetails.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
}
else
{
await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
//On iOS you may want to send your user to the settings screen.
if (Device.RuntimePlatform == Device.iOS)
CrossPermissions.Current.OpenAppSettings();
}
}
//I have split the permission function as below;
public static async Task<bool> GetPermissions()
{
bool permissionsGranted = true;
var permissionsStartList = new List<Permission>()
{
Permission.Location,
Permission.LocationAlways,
Permission.LocationWhenInUse,
Permission.Storage,
Permission.Camera
};
var permissionsNeededList = new List<Permission>();
try
{
foreach (var permission in permissionsStartList)
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
if (status != PermissionStatus.Granted)
{
permissionsNeededList.Add(permission);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Nice, exception! " + ex);
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(permissionsNeededList.ToArray());
try
{
foreach (var permission in permissionsNeededList)
{
var status = PermissionStatus.Unknown;
//Best practice to always check that the key exists
if (results.ContainsKey(permission))
status = results[permission];
if (status == PermissionStatus.Granted || status == PermissionStatus.Unknown)
{
permissionsGranted = true;
}
else
{
permissionsGranted = false;
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Last, exception! " + ex);
}
return permissionsGranted;
}
You can update your OnClick event code to add the permissions logic as well:
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<CameraPermission>();
var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<StoragePermission>();
if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted)
{
cameraStatus = await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
storageStatus = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
}
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted)
{
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
Directory = "Sample",
Name = "flower1.jpg"
});
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
myDetails.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
}
else
{
await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
//On iOS you may want to send your user to the settings screen.
if (Device.RuntimePlatform == Device.iOS)
CrossPermissions.Current.OpenAppSettings();
}
Note:It will become a long function so I recommend breaking it up into different functions.
I added the Xam.Plugin.Media to capture image. The problem is I want to save the picture to my SD Card if there is a SD Card and if not stick to the internal storage. How can I check if there is an sd card present? and if so, how can I get the directory?
My code below is the function to capture the image
try
{
var cafNo = entCafNo.Text;
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", "No Camera Available", "Ok");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(
new StoreCameraMediaOptions
{
SaveToAlbum = true,
Name = cafNo + "_IMG_01.png",
CompressionQuality = 80,
PhotoSize = PhotoSize.Medium,
DefaultCamera = Plugin.Media.Abstractions.CameraDevice.Front
}
);
entPhoto1Url.Text = file.Path;
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
When I use HttpClient.GetAsync(url),but the url is not a reachable address,but it always redirect to another address,and it return a statuecode with ok.
var httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.ExpectContinue = false;
//using ()
{
HttpResponseMessage response = new HttpResponseMessage();
response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync();
Debug.WriteLine(response.StatusCode.ToString());
}
else
{
// problems handling here
Debug.WriteLine(
"Error occurred, the status code is: {0}",
response.StatusCode
);
}
}