Reputation: 925
We have a Xamarin Forms app that has a tab view. From one of the tabs, we open a new Content Page, which needs to have an option to select files and upload the attachment. Using Xamarin.Essentials FilePicker, we are able to pick the file and read the file contents, but after the file is read, the app auto-navigates to the home screen - the same as an app restart.
We have observed that when the filepicker is opened, OnSleep in the App.xaml.cs is called and when the file is read and the picker is dismissed, onresume in App.xaml.cs is called. It seems like this could cause the XForms App to be restarted completely.
All permissions are in place - we are targeting Android 9.0, using XForms version 4.8, X.Essentials v1.6.
Can you please help?
Relevant code:
try
{
var file = await FilePicker.PickAsync();
if (file != null)
{
var stream = await file.OpenReadAsync();
byte[] FileData = new byte[stream.Length];
await stream.ReadAsync(FileData, 0, (int)(stream.Length - 1));
fileData = Convert.ToBase64String(FileData);
fileStream = new MemoryStream(FileData);
FileNameVisibility = true;
FileName = file.FileName;
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
Upvotes: 2
Views: 700
Reputation: 21213
Tested code snippet in doc.
This code works for me:
FilePickerPage.xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XFSOAnswers.FilePickerPage">
<ContentPage.Content>
<StackLayout>
<Button Text="Pick File" Clicked="PickFileButton_Clicked" />
<Label x:Name="FileName" />
<Image x:Name="FileImage" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
FilePickerPage.xaml.cs:
using System;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XFSOAnswers
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class FilePickerPage : ContentPage
{
public FilePickerPage()
{
InitializeComponent();
}
private void PickFileButton_Clicked(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(async () =>
{
await PickAndShow(PickOptions.Images);
});
}
async Task<FileResult> PickAndShow(PickOptions options)
{
try
{
var result = await FilePicker.PickAsync(options);
if (result != null)
{
FileName.Text = $"File Name: {result.FileName}";
if (result.FileName.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ||
result.FileName.EndsWith("png", StringComparison.OrdinalIgnoreCase))
{
var stream = await result.OpenReadAsync();
FileImage.Source = ImageSource.FromStream(() => stream);
}
}
return result;
}
catch (Exception ex)
{
// The user canceled or something went wrong
_ = ex;
}
return null;
}
}
}
App.xaml.cs:
...
MainPage = new StartPage();
StartPage:
... had a button to go to FilePickerPage.
Therefore StartPage was on the stack, then FilePickerPage.
After FilePicker was done, FilePickerPage was still showing - with file name and image:
MainActivity.cs:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
...
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
NOTE: The above MainActivity code should automatically be there in any new Xamarin Forms project; it would only be missing if this was an old project, before Essentials was automatically added by project template.
So, how to debug your code.
if (file != null) { ... }
When commented out, crash or not?
Device.BeginInvokeOnMainThread( async () => {
... YOUR CODE ...
});
Perhaps your navigation stack is empty? When the FilePicker closes, there might be nowhere to go back to.
Upvotes: 1