Skip to content

Commit 044a0ec

Browse files
author
eriklimakc
committed
chore: Update MediaGallery to Uno.Sdk 5.4
1 parent e9ccf60 commit 044a0ec

File tree

7 files changed

+219
-207
lines changed

7 files changed

+219
-207
lines changed
Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
1-
<Page
2-
x:Class="MediaGallerySample.MainPage"
3-
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5-
xmlns:local="using:MediaGallerySample"
6-
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
7-
<StackPanel
8-
HorizontalAlignment="Center"
9-
VerticalAlignment="Center"
10-
Spacing="8">
11-
<TextBlock Style="{ThemeResource TitleTextBlockStyle}" Text="MediaGallery Sample" />
12-
<Button HorizontalAlignment="Center" Click="CheckAccessClick">Check access</Button>
13-
<Button HorizontalAlignment="Center" Click="SaveClick">Save UnoLogo.png to gallery</Button>
14-
<Button HorizontalAlignment="Center" Click="SaveRandomNameClick">Save with random name to gallery</Button>
1+
<Page x:Class="MediaGallerySample.MainPage"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:local="using:MediaGallerySample"
5+
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
6+
7+
<StackPanel HorizontalAlignment="Center"
8+
VerticalAlignment="Center"
9+
Spacing="8">
10+
<TextBlock Style="{ThemeResource TitleTextBlockStyle}"
11+
Text="MediaGallery Sample" />
12+
<Button HorizontalAlignment="Center"
13+
Click="CheckAccessClick">
14+
Check access
15+
</Button>
16+
<Button HorizontalAlignment="Center"
17+
Click="SaveClick">
18+
Save UnoLogo.png to gallery
19+
</Button>
20+
<Button HorizontalAlignment="Center"
21+
Click="SaveRandomNameClick">
22+
Save with random name to gallery
23+
</Button>
1524
</StackPanel>
1625
</Page>

UI/MediaGallery/src/MediaGallerySample/MediaGallery/MediaFileType.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ namespace Uno.Samples;
66
/// </summary>
77
public enum MediaFileType
88
{
9-
/// <summary>
10-
/// Image media file type.
11-
/// </summary>
12-
Image,
9+
/// <summary>
10+
/// Image media file type.
11+
/// </summary>
12+
Image,
1313

14-
/// <summary>
15-
/// Video media file type.
16-
/// </summary>
17-
Video,
14+
/// <summary>
15+
/// Video media file type.
16+
/// </summary>
17+
Video,
1818
}
1919
#endif

UI/MediaGallery/src/MediaGallerySample/MediaGallery/MediaGallery.Android.cs

Lines changed: 90 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -20,105 +20,105 @@ namespace Uno.Samples;
2020

2121
partial class MediaGallery
2222
{
23-
private static async Task<bool> CheckAccessAsyncImpl()
24-
{
25-
if ((int)Build.VERSION.SdkInt < 29)
26-
{
27-
return await PermissionsHelper.CheckWriteExternalStoragePermission(default);
28-
}
29-
else
30-
{
31-
return true;
32-
}
33-
}
34-
35-
private static async Task SavePlatformAsyncImpl(MediaFileType type, Stream sourceStream, string targetFileName)
36-
{
37-
var context = Android.App.Application.Context;
38-
var contentResolver = context.ContentResolver ?? throw new InvalidOperationException("ContentResolver is not set.");
39-
40-
var appFolderName = Package.Current.DisplayName;
41-
// Ensure folder name is file system safe
42-
appFolderName = string.Join("_", appFolderName.Split(Path.GetInvalidFileNameChars()));
43-
44-
var dateTimeNow = DateTime.Now;
45-
46-
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(targetFileName);
47-
var extension = Path.GetExtension(targetFileName).ToLower();
48-
49-
using var values = new ContentValues();
50-
51-
values.Put(IMediaColumns.DateAdded, GetUnixTimestampInSeconds(dateTimeNow));
52-
values.Put(IMediaColumns.Title, fileNameWithoutExtension);
53-
values.Put(IMediaColumns.DisplayName, targetFileName);
54-
55-
var mimeTypeMap = MimeTypeMap.Singleton ?? throw new InvalidOperationException("MimeTypeMap is not set.");
56-
57-
var mimeType = mimeTypeMap.GetMimeTypeFromExtension(extension.Replace(".", string.Empty));
58-
if (!string.IsNullOrWhiteSpace(mimeType))
59-
values.Put(IMediaColumns.MimeType, mimeType);
60-
61-
using var externalContentUri = type == MediaFileType.Image
62-
? Images.Media.ExternalContentUri
63-
: Video.Media.ExternalContentUri;
64-
65-
if (externalContentUri is null)
66-
{
67-
throw new InvalidOperationException($"External Content URI for {type} is not available.");
68-
}
69-
70-
var relativePath = type == MediaFileType.Image
71-
? Environment.DirectoryPictures
72-
: Environment.DirectoryMovies;
73-
74-
if (relativePath is null)
75-
{
76-
throw new InvalidOperationException($"Relative path for {type} is not available.");
77-
}
78-
79-
if ((int)Build.VERSION.SdkInt >= 29)
80-
{
81-
values.Put(IMediaColumns.RelativePath, Path.Combine(relativePath, appFolderName));
82-
values.Put(IMediaColumns.IsPending, true);
83-
84-
using var uri = contentResolver.Insert(externalContentUri, values) ??
85-
throw new InvalidOperationException("Could not generate new content URI");
86-
87-
using var stream = contentResolver.OpenOutputStream(uri) ??
88-
throw new InvalidOperationException("Could not open output stream");
89-
90-
await sourceStream.CopyToAsync(stream);
91-
stream.Close();
92-
93-
values.Put(IMediaColumns.IsPending, false);
94-
context.ContentResolver.Update(uri, values, null, null);
95-
}
96-
else
97-
{
23+
private static async Task<bool> CheckAccessAsyncImpl()
24+
{
25+
if ((int)Build.VERSION.SdkInt < 29)
26+
{
27+
return await PermissionsHelper.CheckWriteExternalStoragePermission(default);
28+
}
29+
else
30+
{
31+
return true;
32+
}
33+
}
34+
35+
private static async Task SavePlatformAsyncImpl(MediaFileType type, Stream sourceStream, string targetFileName)
36+
{
37+
var context = Android.App.Application.Context;
38+
var contentResolver = context.ContentResolver ?? throw new InvalidOperationException("ContentResolver is not set.");
39+
40+
var appFolderName = Package.Current.DisplayName;
41+
// Ensure folder name is file system safe
42+
appFolderName = string.Join("_", appFolderName.Split(Path.GetInvalidFileNameChars()));
43+
44+
var dateTimeNow = DateTime.Now;
45+
46+
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(targetFileName);
47+
var extension = Path.GetExtension(targetFileName).ToLower();
48+
49+
using var values = new ContentValues();
50+
51+
values.Put(IMediaColumns.DateAdded, GetUnixTimestampInSeconds(dateTimeNow));
52+
values.Put(IMediaColumns.Title, fileNameWithoutExtension);
53+
values.Put(IMediaColumns.DisplayName, targetFileName);
54+
55+
var mimeTypeMap = MimeTypeMap.Singleton ?? throw new InvalidOperationException("MimeTypeMap is not set.");
56+
57+
var mimeType = mimeTypeMap.GetMimeTypeFromExtension(extension.Replace(".", string.Empty));
58+
if (!string.IsNullOrWhiteSpace(mimeType))
59+
values.Put(IMediaColumns.MimeType, mimeType);
60+
61+
using var externalContentUri = type == MediaFileType.Image
62+
? Images.Media.ExternalContentUri
63+
: Video.Media.ExternalContentUri;
64+
65+
if (externalContentUri is null)
66+
{
67+
throw new InvalidOperationException($"External Content URI for {type} is not available.");
68+
}
69+
70+
var relativePath = type == MediaFileType.Image
71+
? Environment.DirectoryPictures
72+
: Environment.DirectoryMovies;
73+
74+
if (relativePath is null)
75+
{
76+
throw new InvalidOperationException($"Relative path for {type} is not available.");
77+
}
78+
79+
if ((int)Build.VERSION.SdkInt >= 29)
80+
{
81+
values.Put(IMediaColumns.RelativePath, Path.Combine(relativePath, appFolderName));
82+
values.Put(IMediaColumns.IsPending, true);
83+
84+
using var uri = contentResolver.Insert(externalContentUri, values) ??
85+
throw new InvalidOperationException("Could not generate new content URI");
86+
87+
using var stream = contentResolver.OpenOutputStream(uri) ??
88+
throw new InvalidOperationException("Could not open output stream");
89+
90+
await sourceStream.CopyToAsync(stream);
91+
stream.Close();
92+
93+
values.Put(IMediaColumns.IsPending, false);
94+
context.ContentResolver.Update(uri, values, null, null);
95+
}
96+
else
97+
{
9898
#pragma warning disable CS0618 // Type or member is obsolete
99-
using var directory = new NativeFile(Environment.GetExternalStoragePublicDirectory(relativePath), appFolderName);
100-
directory.Mkdirs();
99+
using var directory = new NativeFile(Environment.GetExternalStoragePublicDirectory(relativePath), appFolderName);
100+
directory.Mkdirs();
101101

102-
using var file = new NativeFile(directory, targetFileName);
102+
using var file = new NativeFile(directory, targetFileName);
103103

104-
using var fileOutputStream = System.IO.File.Create(file.AbsolutePath);
105-
await sourceStream.CopyToAsync(fileOutputStream);
106-
fileOutputStream.Close();
104+
using var fileOutputStream = System.IO.File.Create(file.AbsolutePath);
105+
await sourceStream.CopyToAsync(fileOutputStream);
106+
fileOutputStream.Close();
107107

108-
values.Put(IMediaColumns.Data, file.AbsolutePath);
109-
contentResolver.Insert(externalContentUri, values);
108+
values.Put(IMediaColumns.Data, file.AbsolutePath);
109+
contentResolver.Insert(externalContentUri, values);
110110

111111
#pragma warning disable CA1422 // Validate platform compatibility
112-
using var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
112+
using var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
113113
#pragma warning restore CA1422 // Validate platform compatibility
114-
mediaScanIntent.SetData(NativeUri.FromFile(file));
115-
context.SendBroadcast(mediaScanIntent);
114+
mediaScanIntent.SetData(NativeUri.FromFile(file));
115+
context.SendBroadcast(mediaScanIntent);
116116
#pragma warning restore CS0618 // Type or member is obsolete
117-
}
118-
}
117+
}
118+
}
119119

120-
private static long GetUnixTimestampInSeconds(DateTime current) => (long)GetTimeDifference(current).TotalSeconds;
120+
private static long GetUnixTimestampInSeconds(DateTime current) => (long)GetTimeDifference(current).TotalSeconds;
121121

122-
private static TimeSpan GetTimeDifference(DateTime current) => current.ToUniversalTime() - DateTime.UnixEpoch;
122+
private static TimeSpan GetTimeDifference(DateTime current) => current.ToUniversalTime() - DateTime.UnixEpoch;
123123
}
124124
#endif

UI/MediaGallery/src/MediaGallerySample/MediaGallery/MediaGallery.cs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,34 @@ namespace Uno.Samples;
1313
/// </summary>
1414
public static partial class MediaGallery
1515
{
16-
/// <summary>
17-
/// Checks the user's permission to access the device's gallery.
18-
/// Will trigger the permission request if not already granted.
19-
/// </summary>
20-
/// <returns>A value indicating whether the user has access.</returns>
21-
public static async Task<bool> CheckAccessAsync() => await CheckAccessAsyncImpl();
16+
/// <summary>
17+
/// Checks the user's permission to access the device's gallery.
18+
/// Will trigger the permission request if not already granted.
19+
/// </summary>
20+
/// <returns>A value indicating whether the user has access.</returns>
21+
public static async Task<bool> CheckAccessAsync() => await CheckAccessAsyncImpl();
2222

23-
/// <summary>
24-
/// Saves a media file to the device's gallery.
25-
/// </summary>
26-
/// <param name="type">Media file type.</param>
27-
/// <param name="data">Byte array representing the file.</param>
28-
/// <param name="targetFileName">Target file name.</param>
29-
/// <returns>Task representing the progress of the operation.</returns>
30-
public static async Task SaveAsync(MediaFileType type, byte[] data, string targetFileName)
31-
{
32-
using var memoryStream = new MemoryStream(data);
33-
await SaveAsync(type, memoryStream, targetFileName);
34-
}
23+
/// <summary>
24+
/// Saves a media file to the device's gallery.
25+
/// </summary>
26+
/// <param name="type">Media file type.</param>
27+
/// <param name="data">Byte array representing the file.</param>
28+
/// <param name="targetFileName">Target file name.</param>
29+
/// <returns>Task representing the progress of the operation.</returns>
30+
public static async Task SaveAsync(MediaFileType type, byte[] data, string targetFileName)
31+
{
32+
using var memoryStream = new MemoryStream(data);
33+
await SaveAsync(type, memoryStream, targetFileName);
34+
}
3535

36-
/// <summary>
37-
/// Saves a media file to the device's gallery.
38-
/// </summary>
39-
/// <param name="type">Media file type.</param>
40-
/// <param name="stream">Stream representing the file.</param>
41-
/// <param name="targetFileName">Target file name.</param>
42-
/// <returns>Task representing the progress of the operation.</returns>
43-
public static async Task SaveAsync(MediaFileType type, Stream stream, string targetFileName) =>
44-
await SavePlatformAsyncImpl(type, stream, targetFileName);
36+
/// <summary>
37+
/// Saves a media file to the device's gallery.
38+
/// </summary>
39+
/// <param name="type">Media file type.</param>
40+
/// <param name="stream">Stream representing the file.</param>
41+
/// <param name="targetFileName">Target file name.</param>
42+
/// <returns>Task representing the progress of the operation.</returns>
43+
public static async Task SaveAsync(MediaFileType type, Stream stream, string targetFileName) =>
44+
await SavePlatformAsyncImpl(type, stream, targetFileName);
4545
}
4646
#endif

0 commit comments

Comments
 (0)