Olá pessoal! Tudo bem? Agora que já entendemos todo o conceito fundamental de como usar manualmente funcionalidades nativas de cada plataforma com o DependencyService do Xamarin.Forms, vamos aprender como usar plug-ins para usar funcionalidades nativas sem precisar de todo o trabalho do DependencyService – que nós usamos de fato em situações particulares dos app.
Hoje, plug-ins do Xamarin.Forms podem ser encontrados diretamente no Nuget, e normalmente devem ser instalados em todas as plataformas, já que abrem funcionalidades de cada uma – o raciocínio neste caso é igual ao DependencyService mesmo.
Não é fácil saber quantos e quais plug-ins existem para Xamarin.Forms, então felizmente a própria equipe de desenvolvimento do Xamarin criou uma lista com os plug-ins open-source mais populares, que dão acesso à diferentes funcionalidades.
O problema desta lista é que ela não está atualizada e alguns plug-ins nem são mais suportados. Para entender de forma bem simples como conseguimos usar um plug-in, vamos aprender como criar arquivos em cada plataforma usando o plug-in PCLExt.FIleStorage. Desta forma, podemos comparar facilmente como o plug-in pode facilitar o trabalho em relação à leitura e escrita de arquivos que fizemos apenas usando o DependencyService.
Como sempre, fique à vontade para baixar o código fonte deste artigo para estudos.
Para instalar um plug-in do Xamarin.Forms, clique com o botão direito do mouse na solução, e escolha Manage NuGet Packages for Solution.

Encontre o plug-in PCLExt.FIleStorage e o instale em todos os projetos. Como estamos falando sobre persistência de arquivos, e já sabemos que cada sistema implementa o acesso a dados de forma particular, precisamos instalar o plug-in em todos os projetos.
A interface é bem simples, com um Entry
para o nome do arquivo, um Editor
para o conteúdo do arquivo e três botões para salvar, carregar e apagar arquivos. Cada botão, obviamente, terá o evento Click
atrelado a um método, que fará a ação correspondente.

<Grid Padding="0,20,0,0"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Entry x:Name="Entry" Placeholder="Digite o nome do arquivo" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" /> <Editor x:Name="Editor" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" /> <Button Text="Carregar" Grid.Row="2" Grid.Column="0" Clicked="ButtonLoad_OnClicked" FontSize="10" /> <Button Text="Salvar" Grid.Row="2" Grid.Column="1" Clicked="ButtonSave_OnClicked" FontSize="10"/> <Button Text="Apagar" Grid.Row="2" Grid.Column="2" Clicked="ButtonErase_OnClicked" FontSize="10"/> </Grid>
Mas antes mesmo de programarmos cada método, veja o construtor da página, onde instanciamos um objeto do tipo IFolder
, que é do PCLExt.FIleStorage. A interface IFolder
representa uma pasta, e instanciamos usando o construtor de LocalRootFolder
, que representa a pasta pessoal de cada aplicativo.
private IFolder PastaRaiz { get; } public MainPage() { InitializeComponent(); PastaRaiz = new LocalRootFolder(); }
Agora vamos aos métodos. O primeiro é ButtonLoad_OnClicked
, usado quando quisermos carregar um arquivo. Com base na pasta inicial do app, usamos o método CheckExistsAsync
, que verifica se existe o arquivo na pasta.
Se o resultado for do tipo ExistenceCheckResult.NotFound
, então não existe nada com o mesmo nome e não conseguiremos carregar o arquivo. Caso contrário, usamos o método GetFileAsync
para carregar o arquivo e o método ReadAllTextAsync
para carregar seu conteúdo. Se o resultado for do tipo ExistenceCheckResult.NotFound
, então não existe nada com o mesmo nome e não conseguimos carregar o arquivo. Caso contrário, usamos o método GetFileAsync
para carregar o arquivo e o método ReadAllTextAsync
para carregar seu conteúdo.
private async void ButtonLoad_OnClicked(object sender, EventArgs e) { var nome = Entry.Text; if (string.IsNullOrEmpty(nome)) { await DisplayAlert("Atenção", "Digite um nome para o arquivo!", "Ok"); return; } var arquivoExiste = await PastaRaiz.CheckExistsAsync(nome); if (arquivoExiste == ExistenceCheckResult.NotFound) { await DisplayAlert("Atenção", "Arquivo não existe!", "Ok"); Entry.Text = string.Empty; return; } var arquivo = await PastaRaiz.GetFileAsync(nome); Editor.Text = await arquivo.ReadAllTextAsync(); }
Já o método ButtonSave_OnClicked
, usando para salvar arquivos, também faz a checagem se o arquivo existe (e se existe, o método CheckExistsAsync
retorna ExistenceCheckResult.FileExists
).
Se quisermos sobrescrever o arquivo que já existe, precisamos usar o método CreateFileAsync
passando o nome do arquivo como primeiro parâmetro e a opção CreationCollisionOption.ReplaceExisting
como segundo parâmetro. Ao final, usamos o método WriteAllTextAsync
para escrever o conteúdo do arquivo recém criado.
private async void ButtonSave_OnClicked(object sender, EventArgs e) { var nome = Entry.Text; var conteudo = Editor.Text; if (string.IsNullOrEmpty(nome)) { await DisplayAlert("Atenção", "Digite um nome para o arquivo!", "Ok"); return; } var arquivoExiste = await PastaRaiz.CheckExistsAsync(nome); var substituirArquivo = true; if (arquivoExiste == ExistenceCheckResult.FileExists) substituirArquivo = await DisplayAlert("Atenção", "Deseja substituir arquivo já existente?", "Sim", "Não"); if (!substituirArquivo) return; var arquivo = await PastaRaiz.CreateFileAsync(nome, CreationCollisionOption.ReplaceExisting); await arquivo.WriteAllTextAsync(conteudo); Entry.Text = string.Empty; Editor.Text = string.Empty; await DisplayAlert("Atenção", "Arquivo criado com sucesso!", "Ok"); }
Finalmente, o método ButtonErase_OnClicked
, usado para apagar um arquivo, faz a mesma checagem se o arquivo existe. Se a resposta for afirmativa e o usuário confirmar a remoção, carregamos a referência ao arquivo usando GetFileAsync
e apagamos o arquivo usando o método DeleteAsync
.
private async void ButtonErase_OnClicked(object sender, EventArgs e) { var nome = Entry.Text; if (string.IsNullOrEmpty(nome)) { await DisplayAlert("Atenção", "Digite um nome para o arquivo!", "Ok"); return; } var arquivoExiste = await PastaRaiz.CheckExistsAsync(nome); if (arquivoExiste == ExistenceCheckResult.NotFound) { await DisplayAlert("Atenção", "Arquivo não existe!", "Ok"); Entry.Text = string.Empty; return; } var apagar = await DisplayAlert("Atenção", "Deseja apagar este arquivo?", "Sim", "Não"); if (!apagar) return; var arquivo = await PastaRaiz.GetFileAsync(nome); await arquivo.DeleteAsync(); Entry.Text = string.Empty; Editor.Text = string.Empty; }
Veja o resultado:


Reparou que não precisamos nos preocupar com injetar dependências manualmente e nem mexemos nos projetos de cada plataforma – tirando a instalação do PCLExt.FIleStorage? Esta é a grande vantagem de se usar plug-ins, toda a parte difícil de abstração e injeção de dependência é feita por eles, e podemos nos concentrar no que realmente interessa – criar apps. Até a próxima!
[]’s
Paulo Roberto