Xamarinaszklarp/archiwum/2018/... · 2019-03-12 · Xamarin.Forms first app 3 projects.Net Standard...

Post on 27-May-2020

4 views 0 download

Transcript of Xamarinaszklarp/archiwum/2018/... · 2019-03-12 · Xamarin.Forms first app 3 projects.Net Standard...

Xamarin.Forms

Radosław Osiński

Xamarin.Forms first app

3 projects

.Net Standard → Shared code

iOS → platform specyfic code

Android → platform specyfic project

App.xaml.cspublic partial class App : Application

{public App(){

InitializeComponent();

MainPage = new MainPage();}protected override void OnStart(){

// Handle when your app starts}protected override void OnSleep(){

// Handle when your app sleeps}protected override void OnResume(){

// Handle when your app resumes}

}

Three virtual methods that can be overridden

to handle lifecycle methods:

OnStart - Called when the application starts.

OnSleep - Called each time the application

goes to the background.

OnResume - Called when the application is

resumed, after being sent to the background.

MainPage.xaml

<StackLayout><!-- Place new controls here --><Label Text="Welcome to Xamarin.Forms!"

HorizontalOptions="Center"VerticalOptions="CenterAndExpand" />

</StackLayout>

Page content

https://docs.microsoft.com/en-us/xamarin/get-started/first-app/?pivots=windows

Button

<StackLayout><!-- Place new controls here --><Label Text="Welcome to Xamarin.Forms!"

HorizontalOptions="Center"VerticalOptions="CenterAndExpand" />

<Button Text="Click me!" Clicked="Button_Clicked" /></StackLayout>

int count = 0;private void Button_Clicked(object sender, EventArgs e){

count++;((Button)sender).Text = $"You clicked {count} times";

}

Simple form

<StackLayout Margin="10,35,10,10"><Label Text="Notes"

HorizontalOptions="Center"FontAttributes="Bold" />

<Editor x:Name="_editor"Placeholder="Enter your note"HeightRequest="100" />

<Grid><Grid.ColumnDefinitions>

<ColumnDefinition Width="*" /><ColumnDefinition Width="*" />

</Grid.ColumnDefinitions><Button Text="Save"

Clicked="OnSaveButtonClicked" /><Button Grid.Column="1"

Text="Delete"Clicked="OnDeleteButtonClicked"/>

</Grid></StackLayout>

https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/single-page?pivots=windows

<Editor x:Name="_editor"

• _editor visible on code behind

• Receive info from controlString text = _editor.Text;

• Send info to control_editor.Text = File.ReadAllText(_fileName);

Interacting with local filestring _fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.txt");

public MainPage(){

InitializeComponent();if (File.Exists(_fileName)){

_editor.Text = File.ReadAllText(_fileName);}

}void OnSaveButtonClicked(object sender, EventArgs e){

File.WriteAllText(_fileName, _editor.Text);}void OnDeleteButtonClicked(object sender, EventArgs e){

if (File.Exists(_fileName)){

File.Delete(_fileName);}_editor.Text = string.Empty;

}

Multipage

From where navigation came from?

App.xaml.cs

public App(){

InitializeComponent();MainPage = new NavigationPage(new NotesPage());

}

Without navigation

public App(){

InitializeComponent();MainPage = new NotesPage();

}

Multipage

1. Create folder2. Create model

namespace Notes.Models{

public class Note{

public string Filename { get; set; }public string Text { get; set; }public DateTime Date { get; set; }

}}

Multipage

New page for adding notes

<StackLayout Margin="20"><Editor Placeholder="Enter your note"

Text="{Binding Text}"HeightRequest="100" />

<Grid><Grid.ColumnDefinitions>

<ColumnDefinition Width="*" /><ColumnDefinition Width="*" />

</Grid.ColumnDefinitions><Button Text="Save"

Clicked="OnSaveButtonClicked" /><Button Grid.Column="1"

Text="Delete"Clicked="OnDeleteButtonClicked"/>

</Grid></StackLayout>

Multipage – note entry code behindasync void OnSaveButtonClicked(object sender, EventArgs e)

{var note = (Note)BindingContext;

if (string.IsNullOrWhiteSpace(note.Filename)){ // Save

var filename = Path.Combine(App.FolderPath, $"{Path.GetRandomFileName()}.notes.txt");File.WriteAllText(filename, note.Text);

}else{ // Update

File.WriteAllText(note.Filename, note.Text);}await Navigation.PopAsync();

}

async void OnDeleteButtonClicked(object sender, EventArgs e){

var note = (Note)BindingContext;if (File.Exists(note.Filename)){

File.Delete(note.Filename);}

await Navigation.PopAsync();}

Asynchronously removes the top

page from the navigation stack.

Multipage – creating NotesPage

<ContentPage.ToolbarItems><ToolbarItem Text="+"

Clicked="OnNoteAddedClicked" /></ContentPage.ToolbarItems>

<ListView x:Name="listView"Margin="20"ItemSelected="OnListViewItemSelected">

<ListView.ItemTemplate><DataTemplate>

<TextCell Text="{Binding Text}"Detail="{Binding Date}" />

</DataTemplate></ListView.ItemTemplate>

</ListView>

Multipage – set NotesPage as default

public App(){

InitializeComponent();

MainPage = new NavigationPage(new NotesPage());}

Constructor in App.xaml.cs:

Multipage – NotesPage code behind

protected override void OnAppearing(){

base.OnAppearing();

var notes = new List<Note>();

var files = Directory.EnumerateFiles(App.FolderPath, "*.notes.txt");foreach (var filename in files){

notes.Add(new Note{

Filename = filename,Text = File.ReadAllText(filename),Date = File.GetCreationTime(filename)

});}

listView.ItemsSource = notes.OrderBy(d => d.Date).ToList();

}

Run before page loading

Two events on the Application class that providenotification of pages appearing and disappearing:

PageAppearing - raised when a page is aboutto appear on the screen.

PageDisappearing - raised when a page is about to disappear from the screen.

Multipage - NotesPage code behind

<ContentPage.ToolbarItems><ToolbarItem Text="+" Clicked="OnNoteAddedClicked" />

</ContentPage.ToolbarItems>

async void OnNoteAddedClicked(object sender, EventArgs e){

await Navigation.PushAsync(new NoteEntryPage{

BindingContext = new Note()});

}

Multipage - NotesPage code behind<ListView x:Name="listView"

Margin="20"ItemSelected="OnListViewItemSelected">

<ListView.ItemTemplate><DataTemplate>

<TextCell Text="{Binding Text}" Detail="{Binding Date}" /></DataTemplate>

</ListView.ItemTemplate></ListView>

async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs e){

if (e.SelectedItem != null){

await Navigation.PushAsync(new NoteEntryPage{

BindingContext = e.SelectedItem as Note});

}}

App lifecycle

Lifecycle Methods

OnStart

OnSleep

OnResume

Page navigation events

PageApearing

PageDisapearing

ModalNavigationEvents

ModalPushing

ModalPushed

ModalPopping

ModalPopped

Navigation typesModal Navigation

• Full screen view leads to another full screen view

• View in background is inaccessible

• User need to interact with a view until it is removed

• To complete some task before continuing

• Examples

• Creating new email

• Adding item to list

Hierarchical Navigation

• User is led through a view series with ability to go back to previous screen

• Access to data previously inserted

• Examples

• Few step registration process

• Jumping between application pages Navigation.PushAsync();

Navigation.PushModalAsync();

Hierarchical NavigationUser is able to navigate through pages, forwards and backwards, as desired.

Modal Navigation Events

ModalPopped Event that is raised after a view has been popped modally.

ModalPopping Event that is raised when a view is modally popped.

ModalPushed Event that is raised after a view has been pushed modally.

ModalPushing Event that is raised when a view is modally pushed.

A modal page can be any of the Page types supported by Xamarin.Forms. To display a modal page the application willpush it onto the modal stack, where it will become the active page, as shown in the following diagram:

To return to the previous page the application will pop the current page from the modal stack, and the new topmost pagebecomes the active page, as shown in the following diagram:

Which navigation type should I use?

Design user flow First!

Questions you should ask:

What user should see?

What data user should provide?

What would be the next step?

Local SQLite.NET Database

https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/database?pivots=windows

Adopting model

using System;using SQLite;

namespace Notes.Models{

public class Note{

[PrimaryKey, AutoIncrement]public int ID { get; set; }public string Text { get; set; }public DateTime Date { get; set; }

}}

using System.Collections.Generic;using System.Threading.Tasks;using SQLite;using Notes.Models;

namespace Notes.Data{

public class NoteDatabase{

readonly SQLiteAsyncConnection _database;

public NoteDatabase(string dbPath){

_database = new SQLiteAsyncConnection(dbPath);_database.CreateTableAsync<Note>().Wait();

}

public Task<List<Note>> GetNotesAsync(){

return_database.Table<Note>().ToListAsync();

}

public Task<Note> GetNoteAsync(int id){

return _database.Table<Note>().Where(i => i.ID == id).FirstOrDefaultAsync();

}public Task<int> SaveNoteAsync(Note note)

{if (note.ID != 0){

return _database.UpdateAsync(note);}else{

return _database.InsertAsync(note);}

}

public Task<int> DeleteNoteAsync(Note note){

return _database.DeleteAsync(note);}

}}

Create the database.

Read data from it.

Write data to it. Delete data from it.

Update App.xaml.cs

static NoteDatabase database;

public static NoteDatabase Database{

get{

if (database == null){

database = newNoteDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Notes.db3"));

}return database;

}}

Read data when application loads

NotesPage.xaml.cs

protected override async void OnAppearing(){

base.OnAppearing();

listView.ItemsSource = await App.Database.GetNotesAsync();}

Save

Delete

async void OnSaveButtonClicked(object sender, EventArgs e){

var note = (Note)BindingContext;note.Date = DateTime.UtcNow;await App.Database.SaveNoteAsync(note);await Navigation.PopAsync();

}

async void OnDeleteButtonClicked(object sender, EventArgs e){

var note = (Note)BindingContext;await App.Database.DeleteNoteAsync(note);await Navigation.PopAsync();

}

Styling

• Colours

• Fonts

• Controls

https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/styling?pivots=windows

Styling Application Level – App.xaml<Application.Resources>

<Thickness x:Key="PageMargin">20</Thickness>

<!-- Colors --><Color x:Key="AppBackgroundColor">WhiteSmoke</Color><Color x:Key="iOSNavigationBarColor">WhiteSmoke</Color><Color x:Key="AndroidNavigationBarColor">#2196F3</Color><Color x:Key="iOSNavigationBarTextColor">Black</Color><Color x:Key="AndroidNavigationBarTextColor">White</Color>

<!-- Implicit styles --><Style TargetType="{x:Type NavigationPage}">

<Setter Property="BarBackgroundColor"Value="{OnPlatform iOS={StaticResource iOSNavigationBarColor},

Android={StaticResource AndroidNavigationBarColor}}" /><Setter Property="BarTextColor"

Value="{OnPlatform iOS={StaticResource iOSNavigationBarTextColor},Android={StaticResource AndroidNavigationBarTextColor}}" />

</Style>

<Style TargetType="{x:Type ContentPage}"ApplyToDerivedTypes="True">

<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />

</Style></Application.Resources>

Thickness around the edges

Represents a color and

exposes it as RGBA and HSL values

Impact NavigationPage

Impact all ContentPages

Styles available in the application-level ResourceDictionary can be consumed throughout the application

Styling Page Level – ListView

<ContentPage.Resources><!-- Implicit styles --><Style TargetType="{x:Type ListView}">

<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />

</Style></ContentPage.Resources>

Impact ListView background

+

ListView.Margin defined in application-Level

<Thickness x:Key="PageMargin">20</Thickness>

Styling Page Level – Modal Page

<ContentPage.Resources><!-- Implicit styles --><Style TargetType="{x:Type Editor}">

<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />

</Style>

<Style TargetType="Button"ApplyToDerivedTypes="True"CanCascade="True">

<Setter Property="FontSize" Value="Medium" /><Setter Property="BackgroundColor" Value="LightGray" /><Setter Property="TextColor" Value="Black" /><Setter Property="BorderRadius" Value="5" />

</Style></ContentPage.Resources>

This code adds implicit styles for the Editor and Button views to the page-level ResourceDictionary, and sets the StackLayout.Margin property to a value defined in the application-level ResourceDictionary.

App Center

• Automate the lifecycle of your iOS, Android, Windows and macOS apps

• Connect your git repo (Azure DevOps, GitHub, Bitbucket)

• Test on thousands of real devices

• Distribute beta testers and app stores

• Monitor real-world usage with crash and analytics data

https://docs.microsoft.com/en-us/appcenter/

App Center

• CI – Continuous Integration• Managing development quality

• CQ – Continuous Quality• Support for multiple real devices

• CD – Continuous Delivery• Managing deployments

• CM – Continuous Monitoring• Monitoring traffic and use behaviour

• CE – Continuous Engagement• Push notification

https://docs.microsoft.com/en-us/appcenter/

Xamarin UI Tests – Testing on real devices

Memory and CPU usage

Ho long test took

Logs after test

https://channel9.msdn.com/Shows/XamarinShow/User-Interface-Automation-with-App-Center-Test?term=Xamarin%20UI%20test&lang-en=true

Xamarin UI Tests – Testing on real devices

https://channel9.msdn.com/Shows/XamarinShow/User-Interface-Automation-with-App-Center-Test?term=Xamarin%20UI%20test&lang-en=true

Screens from each device

Different android versions

Different device models

Select the tier for check the most popular devices

AppCenter - Supported test frameworks

• Appium

• Calabash

• Espresso

• Xamarin.UITests

Monitoring with AppCenter• Nuget packages

Microsoft.AppCenter.Analytics

Microsoft.AppCenter.Crashespackages

• App.xaml.cs

• On Start:

Tracking custom events: Analytics.TrackEvent("My custom event");

protected override void OnStart(){

// Handle when your app startsAppCenter.Start("android=64996e3f-eed7-40db-a47b-a0cbd25f222d;" +

"uwp={Your UWP App secret here};" +"ios={Your iOS App secret here}",typeof(Analytics), typeof(Crashes));

}

using Microsoft.AppCenter;using Microsoft.AppCenter.Analytics;using Microsoft.AppCenter.Crashes;

Push notifications with AppCenter

• NugetMicrosoft.AppCenter.Push

protected override void OnStart(){

// Handle when your app startsAppCenter.Start("android=64996e3f-eed7-40db-a47b-a0cbd25f222d;" +

"uwp={Your UWP App secret here};" +"ios={Your iOS App secret here}",typeof(Analytics), typeof(Crashes), typeof(Push));

}

Push notifications with AppCenter +

Set up Firebase Cloud Messaging• Create a project on the Firebase console.

• Then, press on the Android logo to create an application matching your package name. (Package name from AndrofidManifest.xml

• Go to the settings of the application.

• Download the google-services.json file.

• Copy this file to your Android project.

https://console.firebase.google.com/

https://channel9.msdn.com/Shows/XamarinShow/Push-Notifications-Made-Easy-with-App-Center?term=app%20center&lang-en=true

Integrate Firebase in application

• Close and reopen your solution.

• Open context menu on google-services.json file.

• Select GoogleServicesJson in Build Action. (VS: → GoogleServicesJson→ Properties → Build Action dropdown → GoogleServicesJson)

• Edit AndroidManifest.xml and insert the following elements inside the <application> section:

Finally last step:

Result:

Full architecture example

https://azure.microsoft.com/en-us/solutions/architecture/social-mobile-and-web-app-with-authentication/

Application Monitoring

Platform Monitoring Application Monitoring OMS Solutions Security Center

SmartHotel360 is a fictitious smart hospitality company showcasing the future of connected travel.

We built intelligent and personalized apps for guests, business travelers, and hotel managers. All powered

by the cloud, our best-in-class tools, our data platform, and Artificial Intelligence.

People. Process. Products.

What is DevOps?

DevOps is the union of people, process, and products to enable continuous delivery of value to your end users.

Build& Test

ContinuousDelivery

Deploy

Operate

Monitor &

Learn

Plan &

Track

Develop

DevOps it’s not a tool, it’s a process

Azure DevOps

Deliver value to your users faster using proven agile tools to plan, track, and discuss work across your teams.

Build, test, and deploy with CI/CD that works with any language, platform, and cloud. Connect to GitHub or any other Git provider and deploy continuously.

Get unlimited, cloud-hosted private Git repos and collaborate to build better code with pull requests and advanced file management.

Test and ship with confidence using manual and exploratory testing tools.

Create, host, and share packages with your team, and add artifacts to your CI/CD pipelines with a single click.

Azure Boards Azure ReposAzure Pipelines

Azure Test Plans Azure Artifacts

https://azure.com/devops

Demo

https://github.com/Microsoft/SmartHotel360

The Xamarin Show

https://channel9.msdn.com/Shows/XamarinShow