2. Classi di IO
Xamarin.Forms gira su pi湛 piattaforme ciascuna delle quali possiede un proprio filesystem
Le classi del namespace System.IO possono essere utilizzate per accedere al filesystem di ciascuna piattaforma
La classe File permette di creare, eliminare e leggere file
La classe Directory permette di creare, eliminare o di mostrare il contenuto delle directory
possibile anche utilizzare le classi che derivano da Stream per ottenere un pi湛 alto grado di controllo sulle operazioni su
file come compressione o posizionamento allinterno di un file
3. File (1)
Un file di testo pu嘆 essere scritto usando il metodo File.WriteAllText
es. File.WriteAllText(filename, text);
Un file di testo pu嘆 essre scritto usando il metodo File.ReadAllText
es. string text = File.ReadAllText(filename);
Si pu嘆 verificare che un file esista usando il metodo File.Exists
es. bool doesExist = File.Exists(filename);
4. File (2)
Il percorso della parte del filesystem riservata alla applicazione di ogni
piattaforma 竪 determinato da .NET Standard usando lenumerativo
Environment.SpecialFolder come primo argomento del metodo
Environment.GetFolderPAth
Questo pu嘆 essere concatenato con il nome del file usando il metodo Path.Combine
Es string fileName =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicati
onData), "temp.txt");
9. Android File Storage
Una requisito fondamentale per App Android 竪 quello di
manipolare file
Salvare immagini, scaricare documenti esprtare data
Aandroid possiede due gruppi di filesystem che risiedono in due tipi di
storage:
Internal storage 竪 la porzione di filesystem che pu嘆 essere utilizzata
solamente dalle app e dal sistema operativo
External storage 竪 una porzione di filesystem accessibile da tutte le
apps, dagli utenti. In alcuni device 竪 rimovibile
10. Internal vs external storage (1)
Concettualmente, l'archiviazione interna e l'archiviazione esterna sono molto
simili: sono entrambi i luoghi in cui un'app Xamarin.Android pu嘆 salvare il file
Internal Storage 竪 la memoria non-volatile che Android alloca per sistema
operativo e APKs.
Android alloca un directory nella internal storage partition per ogni App
Quando unapp viene disinstallata tutti i file presenti nella memoria interna
vengono cancellati
11. Internal vs external storage (2)
In Android 6.0 e superiori i file presenti nella memoria
interna possono essere sfruttare la feature di auto
backup di Google
La memoria interna hanno degli svantaggi:
I file non possono essere condivisi
I file vengono cancellati se lapp viene cancellata
Lo spazio disponibile 竪 limitato
12. External strorage
Il compito principale della external storage 竪 disporre di uno spazio non esclusivamente accessibile dallapp
o per ottenere spazio per una grande allocazione di spazio
Private: i file privati sono file specifici dell'applicazione (ma sono ancora accessibili dalle altre app). Android si
aspetta che i file privati siano archiviati in una directory specifica su una memoria esterna. Anche se i file sono
chiamati "privati", sono ancora visibili e accessibili da altre app sul dispositivo, non gli viene fornita alcuna protezione
speciale da parte di Android.
Public: si tratta di file che non sono considerati specifici dell'applicazione e devono essere condivisi
liberamente.
13. Private external files (1)
Sono considerati specifici di unapplicazione (simili ai file interni) ma vengono conservati su una
memoria esterna per un numero qualsiasi di motivi (ad esempio, sono troppo grandi per
l'archiviazione interna). Simili ai file interni, questi file verranno eliminati quando l'app
viene disinstallata dall'utente.
Es. Android.Content.Context.GetExternalFilesDir(null) restituisce
/storage/emulated/0/Android/data/com.companyname.app/files/
14. Private external files (2)
La radice di locazione dei file esterni privati si ottiene
chiamando
Android.Content.Context.GetExternalFilesDir(string type)
Questo metodo restituisce un oggetto di tipo Java.IO.File che
rappresenta una directory su external storage
Se type 竪 null viene restituita la directory radice altrimenti
usando una costante Android.OS.Environment viene
restituita una determinata directory
16. Public external files
I file pubblici su external storage non verranno eliminati quando l'app viene disinstallata.
Le app Android devono essere autorizzate prima che possano leggere o scrivere su public external storage.
Android.OS.Environment.ExternalStorageDirectory 竪 un property che restituisce un Java.IO.File che rappresenta la directory esterna
principale es /storage/emulated/0/
Le stesse directory che esistono per la memoria privata sono presenti anche per quella pubblica e si ottengono tramite
Android.OS.Environment.GetExternalStoragePublicDirectory(string directoryType)
queste sono dedicate e accessibili da tutte le applicazioni
17. External Storage Android Check
(1)
Prima di accedere ad uno dei file presenti su external
storage 竪 necessario
Verificare lo stato dellexternal storage: la memoria potrebbe
non essere montata o accessibile
Verificare il permesso di accedervi a runtime: le app android
devono richiedere il permesso per potere accedere alla external
storage
18. External Storage Android Check
(2)
Android.OS.Environment.ExternalStorageState propriet contiene una stringa che identifica lo stato della memoria esterna
La maggior parte delle app Android dovr solo verificare se 竪 installata memoria esterna.
Il seguente codice mostra come verificare che l'archiviazione esterna sia montata per l'accesso in sola lettura o l'accesso in
lettura-scrittura
bool isReadonly = Environment.MediaMountedReadOnly.Equals(Environment.ExternalStorageState);
bool isWriteable = Environment.MediaMounted.Equals(Environment.ExternalStorageState);
19. External Storage Android Check
(3)
Tutte le app Android devono dichiarare una delle due
autorizzazioni per l'archiviazione esterna nel file
AndrroidManifest.xml
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>
20. Richiesta dei permessi
Le app che hanno come target Android 6.0 devono
eseguire la richiesta dei permessi runtime
Le app che hanno target Android 5.1 o inferiori non
necessitano di eseguire la richiesta runtime ma 竪
sufficiente utilizzare il file AndroidManifest.xml
21. Runtime Permission Checks in
Android 6.0
Normal Permissions queste sono autorizzazioni cui mettere a rischio di sicurezza poco la sicurezza o
privacy dell'utente. Android 6.0 conceder autorizzazioni normale automaticamente al momento
dell'installazione. Vedere la documentazione di Android per un elenco completo delle autorizzazioni normali.
Dangerous Permission a differenza dei normali autorizzazioni, autorizzazioni pericolose sono quelli che
proteggono sicurezza o privacy dell'utente. Questi permessi devono essere concessi esplicitamente
dall'utente tramige popup. Inviare o ricevere un messaggio SMS 竪 un esempio di un'azione che richiede
un'autorizzazione pericolosa.
22. Runtime Permission Checks in
Android 6.0 (1)
Il metodo ContextCompat.CheckSelfPermission serve per
verificare che una determinato permesso sia stato convalidato
Questo metodo restituisce un enum di tipo
Android.Content.PM.Permission che contiene due valori
Permission.Granted lo speficifico permesso 竪 stato convalidato
Permission.Denied lo specificao permesso non 竪 stato convalidato
23. Runtime Permission Checks in
Android 6.0 (2)
ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int
requestCode)
Questo metodo serve per attivare il popup di richiesta permessi
Activity 竪 listanza dellactivity che richiede il permesso
Permissions 竪 la lista dei permessi richiesti
RequestCode 竪 un intero utilizzato per convalidare la richiesta del permesso nel
metodo OnRequestPermissionsResult che intercetta la risposta
dellutente(dovrebbe essere maggiore di zero)
24. Es. Richiesta permessi Android
6.0 (1)
Requisiti
Device con Android 6.0 o superiore installato
Android target 6.0 o superiore nel manifest
25. Es. Riechiesta permessi Android
6.0 (2)
Nella MainActvitiy.cs del progetto Xamarin.Android
vado ad inserire il seguente override per ottenere il
permesso di scrittura su External storage
int REQUEST_STORAGE = 1;
protected override void OnStart()
{
base.OnStart();
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.WriteExternalStorage }, REQUEST_STORAGE);
}
}
26. Es. Riechiesta permessi Android
6.0 (3)
Nella MainActvitiy.cs del progetto Xamarin.Android
vado ad inserire il seguente override per ricevere la
conferma che il permesso sia stato concessopublic override void OnRequestPermissionsResult(
int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
if (requestCode == REQUEST_STORAGE)
{
if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
Log.Info("My AP", "My storage permission accepted");
}
else
{
.Info("My AP", "My storage permission denied");
}
Log.Info("My AP", "My storage received");
}
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
28. Xamarin.Forms Local Database
Xamarin.Forms supporta applicazioni basate su database
che utilizzano il motore di database SQLite, che consente di
caricare e salvare oggetti utilizzando lo shared code.
Le applicazioni Xamarin.Forms possono usare il pacchetto
nuget sqlite-net-pcl
Di seguito un esempio di come creare una ToDo list
memorizzandola in un database
29. Es. Sqlite
Creo una directory Model nel progetto PCL e includo la
mia classe di model
using SQLite;
namespace AppDatabase.Model
{
public class TodoItem
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public bool Done { get; set; }
}
}
30. Es. Sqlite (2.1)
Creo una classe crud TodoItemDatabase mettendola in
una cartella Data
public class TodoItemDatabase
{
readonly SQLiteAsyncConnection database;
public TodoItemDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
//Executes a "create table if not exists" on the database.
database.CreateTableAsync<TodoItem>().Wait();
}
public Task<List<TodoItem>> GetItemsAsync()
{
return database.Table<TodoItem>().ToListAsync();
}
public Task<List<TodoItem>> GetItemsNotDoneAsync()
{
return database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
}
32. Es. Sqlite (3)
Nel file App.xaml.cs aggiungere linizializzazione statica del database aggiungendo il
seguente codice nella classe App
static TodoItemDatabase database;
public static TodoItemDatabase Database
{
get
{
if (database == null)
{
database = new
TodoItemDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TodoSQLite.db3"));
}
return database;
}
}
33. Es. Sqlite (4)
Nel file di MainPage.xaml inserire una ListView che mostra i dati
Salvare licona check.png in Resources/drawable nel progetto Android
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AppDatabase"
x:Class="AppDatabase.MainPage">
<ListView x:Name="listView" Margin="20" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="20,0,0,0" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" />
<Image Source="check.png" HorizontalOptions="End" IsVisible="{Binding Done}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
34. Es. Sqlite (5)
Nella file MainPage.xaml.cs aggiungere qualche elemento al
database ed esegue il bind dei dati con il seguente codice
protected override async void OnAppearing()
{
base.OnAppearing();
TodoItem todoItem = new TodoItem();
todoItem.Name = "Todo1";
todoItem.Notes = "Take the rabbish out";
todoItem.Done = true;
await App.Database.SaveItemAsync(todoItem);
TodoItem todoItem2 = new TodoItem();
todoItem2.Name = "Todo2";
todoItem2.Notes = "do homework";
todoItem2.Done = false;
await App.Database.SaveItemAsync(todoItem2);
listView.ItemsSource = await App.Database.GetItemsAsync();
}