Lab 3 - Saving data
- 📝 Worth: 2% (/5pts)
- đź“… Due: Friday March 22, 2024 @End of class
- đź•‘ Late submissions: Not accepted.
- 📥 Submission: In class
Objectives
In this lab, we will attempt to make the Maui Social Media App more persistent to user changes.
- Learn how to use application preferences
- Learn how to use embedded text files
- Learn how to use embedded app settings in a json format
- Learn how to use an API to save images on the cloud.
- Learn how to serialize and deserialize objects and data strucutres.
Setup
-
Clone the following repo
-
Save it on your local drive
C:/Users/<studentId>
, not on One Drive -
Avoid lengthy file directories
-
Open the Lab3 folder containing the
MauiSocial
app, feel free to create a copy of the project so you can push it on a personal repo later on. -
You will not submit this at the end, you will only show me your progress in class.
-
I have already installed the important package :
Cloudinary
(to upload pictures on the cloud)
Target platform
For this lab we will be testing the app on two different form factors:
-
Android Emulator: Pixel 5 - API 34
-
(optional) iOS, Note: I did not configure app entitlements for iOS nor did I test the app on this platform.
Exercise 1 (1 pt) - App Preferences
For this first exercise, you will have to complete the Settings.xaml
page functionality in order to save three user preferences and then use them to define the Username displayed in ProfilePage.xaml
and set the App.Current.UserAppTheme
:
Preference name | Type |
---|---|
“username ” |
string |
"profileuri" |
string |
"apptheme" |
bool |
Setting preferences
- Inspect the
Settings.xaml
file and note theTableView
’s content, these are the entries where the user can set their preferences. - In
Settings.xaml.cs
, implement the event handlers to set each of the preference listed above
To set a preference use
Preferences.Set("nameofthepreference", value);
- For the
AppTheme
inspect theMenuFlyoutItem
and its event handler added to theAppShell.xaml.cs
to know how to get the current app theme. - In addition to saving the new preference, you should set the app theme to Light if the toggle is on, and set it to Dark if the toggle is off.
Using preferences
- Restart the app to test the next few steps
- Inside the
Settings.xaml.cs
page constructor, get the preferences saved to set the entries text and the toggle switch state.
To get a preference use
Preferences.Get("nameofthepreference", defaultvalue);
- Get the preference of the theme to set the App theme inside the
AppShell.xaml.cs
- Get the preference of the username and the user profile to set the username and profile picture inside the
ProfilePage.xaml.cs
and inside theCommentsPage.xaml.cs
✨ Test your understanding Is it possible to serialize an object inside the Preferences?
Exercise 2 (1pt) - Reading an embedded file
-
Open the
InfoPage.xaml
and inspect the UI elements -
This page will serve as a placeholder for a static text contained in the
Files/InfoText.txt
file -
Open your
MSBuild
file and add the file as anEmbeddedResource
-
Implement the private method
LoadFile()
, open the embedded file andHint: Use the
Assembly.GetExecutingAssembly().GetManifestResourceNames()
andGetManifestResourceStream()
methods. -
Using a
StreamReader
, read the content of the file -
Set the
FileEditor.Text
to the content of the file. -
Display its content in the Editor
Do it at the end:
✨ Test your understanding What other files are included as embdedded files?
Exercise 3 (1pt)
- In the
PostPage.xaml.cs
, implement theBtn_Save_Clicked()
event handler - Save the photo to the
FileSystem.AppDataDirectory
:
Hint: Read the stream of the file and use
sourceStream.CopyToAsync(destinationStream);
- You’ll notice that you cannot validate your work because you do not have access to this directory on the Android Emulator.
- To validate that the file was correctly saved, we will upload the image on Cloudinary in Exercise 5.
Exercise 4 (1pt) - Serialization
To ensure the persistence of the app we would like to save the ObservableCollection<Post>
to a json file using the System.Text.Json.JsonSerializer
class. I have already created two methods in the PostsRepo
which you need to implement: LoadPosts()
and SavePosts()
. I have also already added calls to these methods inside the PostsRepo
class.
-
Inside the
App.xaml.cs
, create a new staticstring
variable called"DataFile
” -
Create a file path to a
"posts.json"
file saved in theAppDataDirectory
-
Use this variable to initialize the static
PostsRepo
-
Observe the constructor of the
PostsRepo
and implement theSavePosts()
andLoadPosts()
:- Use a
try/catch
to ensure some error handling and logging of errors. - Make sure that if the file doesn’t exist to not make the app crash, since the first time this file won’t exist.
Hint: Use
JsonSerializer.Serialize<ClassToSerialize>(stream, ObjectToSerialize);
andJsonSerializer.Deserialize<ClassToSerialize>(stream);
- Use a
-
Test it by adding a few comments and likes to some posts and re-starting the app. Your changes should be saved.
✨ Test your understanding: What is the interest of using a static repo as opposed to simply initializing a list of posts in the code behind as we’ve done in the previous demos?
✨ Test your understanding: Why did I make the PostsRepo
implement the INotifyPropertyChanged
interface?
✨ Test your understanding What is the interest of having an UpdatePost()
method when I could simply let the Pages code behind change a given Post directly (ex: Post.Likes++
)?
Exercise 5 (2pt) - Using an API to upload pictures.
Cloudinary- Setup
Cloudinary is a a cloud management service for images and videos which allows programmatical uploads of media files and enables image and video transformations (cropping, filtered, etc). We will use the free license to upload pictures taken with the MauiSocial App.
Before using the service, we need to generate some api keys and secrets:
-
Create an account or use GitHub to login
-
Verify your account
-
Go to the Dashboard
-
Get the Cloud name, API Key, API Secret
-
Save them to an
"appsettings.json"
file inside your project directory.{ "CloudinaryConfig": { "cloudName": "1234", "apiKey": "1234", "apiSecret": "1234" } }
-
If you push your source code somewhere, do not push this
"appsettings.json"
file at the root of the project as these are your confidential keys.
Using the service
-
Add the
"appsettings.json"
as an the embedded resources -
Install the following packages:
- Install the
Nuget Microsoft.Extensions.Configuration.Json
- Install the
Nuget Microsoft.Extensions.Configuration.Binder
I’ve already created a Services folder in which I included a Config class to parse the content of the json
- Install the
-
Complete the constructor of the
CloudinaryService
: -
Get the
"appsettings.json"
stream and use the following line to parse the config:_config = configuration.GetSection(nameof(CloudinaryConfig)).Get<CloudinaryConfig>();
-
Now inside the constructor instanciate the API class:
Account account = new Account( _config.CloudName, _config.ApiKey, _config.ApiSecret ); _cloudinary = new Cloudinary( account );
-
Use a
try/catch
inside the Service to ensure that the embedded file is properly found, parsed and used. -
To test it out, go to your
App.xaml.cs
and create a static instance of this class. -
Run the app and observe any except being thrown.
✨ Test your understanding: What’s is an "appsettings.json"
file typically used for?
✨ Test your understanding: What’s the interest of including it as an embedded file.
- Implement the method which should call
_cloudinary.UploadAsync()
: use proper exception handling to ensure that exceptions are logged to the console.
public async Task<ImageUploadResult> UploadImage(string imageFilePath,string imageName)
- Call the method inside the
Btn_Save_Clicked()
event handler inside thePostPage
:- Use exception handling and display an alert in case of error.
- Get the
secureurl
from the returned result - Add a new post in the
Repo
with thisurl
- You should see the post appearing in the
MainPage
Bonus exercise 1pt
James Montemagno created an Plug-in (installed as a Nuget package) which facilitates the action of taking pictures, saving them and saving them to Gallery.
Create a user preference inside the settings page which allow the user to have the option to automatically save posts to their phone Gallery. Then modify the Save button event handler in the Post Page to save the photo to the Gallery using the Plug-in. Test by insuring that the posts are saved to the gallery and your post page is still functional.
✨ Test your understanding: What can you say about this app’s testability? Is it easily testable? What can we do to improve this?
References
-
How To Upload Image(Cloudinary/Asp.Net Core), Karakiz Leyligul, 2022, March 31. Last Access: 2024, March 20.
-
Dot Net MAUI Configuration, James Montemagno, 2022, March 25. Last Access: 2024, March 20.