Last active
April 8, 2022 09:04
-
-
Save ericbrunner/5a4c76cb5cbabc3a992c5a97a216c81c to your computer and use it in GitHub Desktop.
Media Plugin Usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Acr.UserDialogs; | |
using Plugin.Connectivity; | |
using Plugin.Media; | |
using Plugin.Media.Abstractions; | |
using Plugin.Permissions; | |
using Plugin.Permissions.Abstractions; | |
using System; | |
using System.Globalization; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using trucker_rolsped.AzureStorage; | |
using trucker_rolsped.Helper.HockeyApp; | |
using trucker_rolsped.Interfaces; | |
using trucker_rolsped.Interfaces.Utils; | |
using trucker_rolsped.Models; | |
using trucker_rolsped.StoreManager; | |
using trucker_rolsped.ViewModels.Media; | |
using Xamarin.Forms; | |
namespace trucker_rolsped.Pages.Media | |
{ | |
[Flags] | |
public enum MediaType : byte | |
{ | |
None = 0x00, // 0d, 0000 0000b | |
Photo = 0x01, // 2^0 = 1d, 0000 0001b | |
Video = 0x02, // 2^1 = 2d, 0000 0010b | |
TakenPhoto = 0x04, // 2^2 = 4d, 0000 0100b | |
PickedPhoto = 0x08 // 2^3 = 8d, 0000 1000b | |
} | |
public enum MediaState | |
{ | |
Created = 0, | |
Uploaded = 1, | |
Queued = 2, | |
Error = 3, | |
NotFound = 4 | |
} | |
public sealed class TruckerAppMediaFile : IDisposable | |
{ | |
public MediaType Type { get; set; } | |
public MediaFile File { get; set; } | |
public string DokArt { get; set; } | |
public MediaState MediaState { get; set; } | |
public int TruckAppId { get; set; } | |
public string FilePath { get; set; } | |
public TruckerAppMediaFile() | |
{ | |
MediaState = MediaState.Created; | |
} | |
public async void Dispose() | |
{ | |
File?.Dispose(); | |
} | |
} | |
public partial class Task70PhotoUploadPage : ContentPage, IRefreshPage | |
{ | |
private readonly string _dokArt; | |
private readonly Task70PhotoUploadViewModel _task70PhotoUploadViewModel; | |
private readonly TaskCompletionSource<bool> _tcs; | |
private readonly int _truckAppId; | |
private readonly WorkflowItem _workflowItem; | |
public Task70PhotoUploadPage(TaskCompletionSource<bool> tcs, WorkflowItem workflowItem, string dokArt) | |
{ | |
InitializeComponent(); | |
_tcs = tcs; | |
_workflowItem = workflowItem; | |
_dokArt = dokArt; | |
_truckAppId = _workflowItem.TruckAppId; | |
_task70PhotoUploadViewModel = new Task70PhotoUploadViewModel(_workflowItem, dokArt); | |
BindingContext = _task70PhotoUploadViewModel; | |
NavigationPage.SetHasNavigationBar(this, false); | |
Device.OnPlatform(iOS: () => { Padding = new Thickness(0, 20, 0, 0); }); | |
} | |
protected override bool OnBackButtonPressed() | |
{ | |
return true; | |
} | |
private void ChangeMediaButtonEnableState(bool enable) | |
{ | |
if (TakePhoto.IsVisible) | |
TakePhoto.IsEnabled = enable; | |
if (PickPhoto.IsVisible) | |
PickPhoto.IsEnabled = enable; | |
if (TakeNextPhoto.IsVisible) | |
TakeNextPhoto.IsEnabled = enable; | |
if (PickNextPhoto.IsVisible) | |
PickNextPhoto.IsEnabled = enable; | |
} | |
private async Task CheckToUploadPhoto() | |
{ | |
try | |
{ | |
if (SelectedMedia?.File != null) | |
{ | |
bool isOk = await DisplayAlert("Foto geladen", "Wollen Sie das Foto zur Roland Spedition senden?", "Ja", "Nein"); | |
if (isOk) | |
{ | |
await UploadPhoto(); | |
} | |
} | |
} | |
finally | |
{ | |
SelectedMedia?.Dispose(); | |
} | |
} | |
private async void CloseFotoDialogClicked(object sender, EventArgs e) | |
{ | |
await CheckToUploadPhoto(); | |
await Navigation.PopAsync(animated: false); | |
_tcs.SetResult(true); | |
} | |
// prevent that a user invoked Take and Pick Photo event at same time | |
private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1); | |
private async void PickPhotoClicked(object sender, EventArgs e) | |
{ | |
await _semaphoreSlim.WaitAsync(); | |
try | |
{ | |
ChangeMediaButtonEnableState(enable: false); | |
SelectedMedia?.Dispose(); | |
SelectedMedia = null; | |
await CrossMedia.Current.Initialize(); | |
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera); | |
var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage); | |
if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted) | |
{ | |
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] {Permission.Camera, Permission.Storage}); | |
cameraStatus = results[Permission.Camera]; | |
storageStatus = results[Permission.Storage]; | |
} | |
if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted) | |
{ | |
if (!CrossMedia.Current.IsPickPhotoSupported) | |
{ | |
await MetricsManagerHelper.Instance.SendGenericMessageToApplicationInsightsAsync($"{nameof(Task70PhotoUploadPage)}", "Not allowed to choose a photo."); | |
await DisplayAlert("Media Info", "Keine Berechtigung ein Foto auszuwählen.", "OK"); | |
return; | |
} | |
SelectedMedia = new TruckerAppMediaFile | |
{ | |
Type = MediaType.Photo | MediaType.PickedPhoto, | |
File = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions | |
{ | |
CompressionQuality = 92, | |
PhotoSize = PhotoSize.Medium | |
}) | |
}; | |
if (SelectedMedia?.File == null) | |
{ | |
SelectedMedia = null; | |
return; | |
} | |
var imageStream = await DependencyService.Get<Interfaces.Media.IMedia>().CopyMediaAsync(SelectedMedia.File.GetStream()); | |
Image.Source = ImageSource.FromStream(() => imageStream); | |
SendMedia.IsEnabled = true; | |
} | |
else | |
{ | |
await MetricsManagerHelper.Instance.SendGenericMessageToApplicationInsightsAsync($"{nameof(Task70PhotoUploadPage)}", "Not allowed to choose a photo."); | |
await DisplayAlert("Media Info", "Keine Berechtigung ein Foto auszuwählen.", "OK"); | |
if (Device.OS == TargetPlatform.iOS) | |
//On iOS you may want to send your user to the settings screen. | |
CrossPermissions.Current.OpenAppSettings(); | |
} | |
} | |
catch (Exception ex) | |
{ | |
await MetricsManagerHelper.Instance.SendExceptionToApplicationInsightsAsync(ex).ConfigureAwait(true); | |
} | |
finally | |
{ | |
ChangeMediaButtonEnableState(enable: true); | |
_semaphoreSlim.Release(); | |
} | |
} | |
private async void TakePhotoClicked(object sender, EventArgs e) | |
{ | |
await _semaphoreSlim.WaitAsync(); | |
try | |
{ | |
ChangeMediaButtonEnableState(enable: false); | |
SelectedMedia?.Dispose(); | |
SelectedMedia = null; | |
await CrossMedia.Current.Initialize(); | |
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera); | |
var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage); | |
if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted) | |
{ | |
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] {Permission.Camera, Permission.Storage}); | |
cameraStatus = results[Permission.Camera]; | |
storageStatus = results[Permission.Storage]; | |
} | |
if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted) | |
{ | |
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported) | |
{ | |
await MetricsManagerHelper.Instance.SendGenericMessageToApplicationInsightsAsync($"{nameof(Task70PhotoUploadPage)}", "No camera available."); | |
await DisplayAlert("Media Info", "Keine Kamera verfügbar.", "OK"); | |
return; | |
} | |
var localFileName = $"{DateTime.Now.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture)}_{_truckAppId}_{_dokArt}.jpg"; | |
SelectedMedia = new TruckerAppMediaFile | |
{ | |
Type = MediaType.Photo | MediaType.TakenPhoto, | |
File = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions | |
{ | |
PhotoSize = PhotoSize.Medium, | |
CompressionQuality = 92, | |
Name = localFileName, | |
Directory = "Truckerapp" | |
}) | |
}; | |
if (SelectedMedia?.File == null) | |
{ | |
SelectedMedia = null; | |
return; | |
} | |
var imageStream = await DependencyService.Get<Interfaces.Media.IMedia>().CopyMediaAsync(SelectedMedia.File.GetStream()); | |
Image.Source = ImageSource.FromStream(() => imageStream); | |
SendMedia.IsEnabled = true; | |
} | |
else | |
{ | |
await MetricsManagerHelper.Instance.SendGenericMessageToApplicationInsightsAsync($"{nameof(Task70PhotoUploadPage)}", "Not allowed to use camera."); | |
await DisplayAlert("Media Info", "Keine Berechtigung die Kamera zu verwenden.", "OK"); | |
if (Device.OS == TargetPlatform.iOS) | |
//On iOS you may want to send your user to the settings screen. | |
CrossPermissions.Current.OpenAppSettings(); | |
} | |
} | |
catch (Exception ex) | |
{ | |
await MetricsManagerHelper.Instance.SendExceptionToApplicationInsightsAsync(ex).ConfigureAwait(true); | |
} | |
finally | |
{ | |
ChangeMediaButtonEnableState(enable: true); | |
_semaphoreSlim.Release(); | |
} | |
} | |
private async void SendMediaOnClicked(object sender, EventArgs e) | |
{ | |
SendMedia.IsEnabled = false; | |
try | |
{ | |
await UploadPhoto(); | |
} | |
catch (Exception exception) | |
{ | |
await MetricsManagerHelper.Instance.SendExceptionToApplicationInsightsAsync(exception); | |
Image.Source = Device.OnPlatform( | |
iOS: ImageSource.FromFile("image_photo_plain.png"), | |
Android: ImageSource.FromFile("image_photo_plain.png"), | |
WinPhone: null | |
); | |
SelectedMedia?.Dispose(); | |
SelectedMedia = null; | |
} | |
finally | |
{ | |
EnabledNextButtons(); | |
} | |
} | |
private async Task UploadPhoto() | |
{ | |
try | |
{ | |
SelectedMedia.DokArt = _dokArt; | |
SelectedMedia.TruckAppId = _truckAppId; | |
UserDialogs.Instance.ShowLoading("Foto wird hochgeladen..."); | |
await AzureBlobStorageManager.Instance.UploadMediaAsync(SelectedMedia); | |
UserDialogs.Instance.HideLoading(); | |
switch (SelectedMedia.MediaState) | |
{ | |
case MediaState.Uploaded: | |
//var result = await DisplayAlert("Foto Upload", "Foto wurde erfolgreich hochgeladen. Möchten Sie das Foto jetzt vom Handy löschen?", "Ja", "Nein"); | |
break; | |
case MediaState.Queued: | |
UserDialogs.Instance.ShowLoading("Upload erfolgt automatisch wenn Sie wieder mit Internet oder dem mobilem Netz verbunden sind!"); | |
await Task.Delay(1500); | |
UserDialogs.Instance.HideLoading(); | |
break; | |
case MediaState.Created: | |
await DisplayAlert("Foto Upload", "Sie müssen das Foto erneut auswählen bzw. machen, da es nicht gesendet wurde!", "Ok"); | |
break; | |
case MediaState.Error: | |
await DisplayAlert("Foto Upload", "Sie müssen das Foto erneut auswählen bzw. machen, da es nicht gesendet wurde!", "Ok"); | |
break; | |
default: | |
await DisplayAlert("Foto Upload", "Sie müssen das Foto erneut auswählen bzw. machen, da es nicht gesendet wurde!", "Ok"); | |
break; | |
} | |
} | |
catch (Exception ex) | |
{ | |
SelectedMedia.MediaState = MediaState.Error; | |
await DisplayAlert("Sende Media Fehler", ex.Message, "Ok"); | |
} | |
finally | |
{ | |
Image.Source = Device.OnPlatform( | |
iOS: ImageSource.FromFile("image_photo_plain.png"), | |
Android: ImageSource.FromFile("image_photo_plain.png"), | |
WinPhone: null | |
); | |
if (SelectedMedia.MediaState == MediaState.Uploaded || SelectedMedia.MediaState == MediaState.Queued) | |
{ | |
_workflowItem.TruckAuftragWorkFlow.DokAnzahl++; | |
} | |
SelectedMedia?.Dispose(); | |
if (SelectedMedia?.MediaState == MediaState.Uploaded) | |
{ | |
await DeleteFileAfterUploadAsync(); | |
} | |
SelectedMedia = null; | |
} | |
} | |
private async Task DeleteFileAfterUploadAsync() | |
{ | |
//Platform specific file delete | |
var truckerappMedia = SelectedMedia.FilePath; | |
var platformFileHandler = DependencyService.Get<IFileHandling>(); | |
if (platformFileHandler != null) | |
if (await platformFileHandler.FileExistsAsync(truckerappMedia)) | |
{ | |
var deleted = await platformFileHandler.DeleteFileAsync(truckerappMedia); | |
if (!deleted) | |
{ | |
await MetricsManagerHelper.Instance.SendErrorToApplicationInsightsAsync($"Photo couldn't be deleted: {truckerappMedia}"); | |
} | |
} | |
} | |
private void EnabledNextButtons() | |
{ | |
TakePhoto.IsVisible = false; | |
PickPhoto.IsVisible = false; | |
TakeNextPhoto.IsVisible = true; | |
PickNextPhoto.IsVisible = true; | |
} | |
private bool IsTakenPhoto => (SelectedMedia.Type & MediaType.TakenPhoto) != 0x00; | |
private TruckerAppMediaFile SelectedMedia { get; set; } | |
protected override async void OnAppearing() | |
{ | |
base.OnAppearing(); | |
try | |
{ | |
await RefreshItemsAsync(showActivityIndicator: false, syncItems: false); | |
} | |
catch (Exception e) | |
{ | |
await MetricsManagerHelper.Instance.SendExceptionToApplicationInsightsAsync(e); | |
} | |
} | |
public async Task RefreshItemsAsync(bool showActivityIndicator, bool syncItems) | |
{ | |
syncItems = syncItems && CrossConnectivity.Current.IsConnected; | |
//UserDialogs.Instance.ShowLoading("Daten werden geladen...", MaskType.Black); | |
_task70PhotoUploadViewModel.LanguageItems = await OfflineSyncStoreManager.Instance.TagSpracheStore.GetTagSpracheItemsAsync(syncItems); | |
//UserDialogs.Instance.HideLoading(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ericbrunner Thank you very much for your response. I'll put into practice. All the best :)