mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 18:08:26 +03:00
Fix Progress dialog crash on tombstoning (#1682)
* Changed ProgressDialog because deprecated and improved the dismissal of the dialog in order for it not to crash the app on certain situations * Removed android version check given that our minimum is greater that the check
This commit is contained in:
parent
137c762e40
commit
5a6aec51f3
5 changed files with 146 additions and 15 deletions
|
@ -191,6 +191,7 @@
|
|||
<AndroidResource Include="Resources\drawable-v23\splash_screen.xml" />
|
||||
<AndroidResource Include="Resources\drawable-v23\splash_screen_dark.xml" />
|
||||
<AndroidResource Include="Resources\drawable\switch_thumb.xml" />
|
||||
<AndroidResource Include="Resources\layout\progress_dialog_layout.xml" />
|
||||
<AndroidResource Include="Resources\layout\Tabbar.axml" />
|
||||
<AndroidResource Include="Resources\layout\Toolbar.axml" />
|
||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
||||
|
|
27
src/Android/Resources/layout/progress_dialog_layout.xml
Normal file
27
src/Android/Resources/layout/progress_dialog_layout.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="10dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLoading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:gravity="center|left"
|
||||
android:textSize="18sp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
|
@ -13,6 +13,7 @@ using Android.OS;
|
|||
using Android.Provider;
|
||||
using Android.Text;
|
||||
using Android.Text.Method;
|
||||
using Android.Views;
|
||||
using Android.Views.Autofill;
|
||||
using Android.Views.InputMethods;
|
||||
using Android.Webkit;
|
||||
|
@ -27,6 +28,7 @@ using Bit.Core.Enums;
|
|||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Droid.Autofill;
|
||||
using Bit.Droid.Utilities;
|
||||
using Plugin.CurrentActivity;
|
||||
|
||||
namespace Bit.Droid.Services
|
||||
|
@ -37,7 +39,9 @@ namespace Bit.Droid.Services
|
|||
private readonly IMessagingService _messagingService;
|
||||
private readonly IBroadcasterService _broadcasterService;
|
||||
private readonly Func<IEventService> _eventServiceFunc;
|
||||
private ProgressDialog _progressDialog;
|
||||
private AlertDialog _progressDialog;
|
||||
object _progressDialogLock = new object();
|
||||
|
||||
private bool _cameraPermissionsDenied;
|
||||
private Toast _toast;
|
||||
private string _userAgent;
|
||||
|
@ -108,22 +112,101 @@ namespace Bit.Droid.Services
|
|||
{
|
||||
await HideLoadingAsync();
|
||||
}
|
||||
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
|
||||
_progressDialog = new ProgressDialog(activity);
|
||||
_progressDialog.SetMessage(text);
|
||||
_progressDialog.SetCancelable(false);
|
||||
|
||||
var activity = CrossCurrentActivity.Current.Activity;
|
||||
var inflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService);
|
||||
var dialogView = inflater.Inflate(Resource.Layout.progress_dialog_layout, null);
|
||||
|
||||
var txtLoading = dialogView.FindViewById<TextView>(Resource.Id.txtLoading);
|
||||
txtLoading.Text = text;
|
||||
txtLoading.SetTextColor(ThemeHelpers.TextColor);
|
||||
|
||||
_progressDialog = new AlertDialog.Builder(activity)
|
||||
.SetView(dialogView)
|
||||
.SetCancelable(false)
|
||||
.Create();
|
||||
_progressDialog.Show();
|
||||
}
|
||||
|
||||
public Task HideLoadingAsync()
|
||||
{
|
||||
if (_progressDialog != null)
|
||||
// Based on https://github.com/redth-org/AndHUD/blob/master/AndHUD/AndHUD.cs
|
||||
lock (_progressDialogLock)
|
||||
{
|
||||
_progressDialog.Dismiss();
|
||||
_progressDialog.Dispose();
|
||||
_progressDialog = null;
|
||||
if (_progressDialog is null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
void actionDismiss()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsAlive(_progressDialog) && IsAlive(_progressDialog.Window))
|
||||
{
|
||||
_progressDialog.Hide();
|
||||
_progressDialog.Dismiss();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
_progressDialog = null;
|
||||
}
|
||||
|
||||
// First try the SynchronizationContext
|
||||
if (Application.SynchronizationContext != null)
|
||||
{
|
||||
Application.SynchronizationContext.Send(state => actionDismiss(), null);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Otherwise try OwnerActivity on dialog
|
||||
var ownerActivity = _progressDialog?.OwnerActivity;
|
||||
if (IsAlive(ownerActivity))
|
||||
{
|
||||
ownerActivity.RunOnUiThread(actionDismiss);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Otherwise try get it from the Window Context
|
||||
if (_progressDialog?.Window?.Context is Activity windowActivity && IsAlive(windowActivity))
|
||||
{
|
||||
windowActivity.RunOnUiThread(actionDismiss);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Finally if all else fails, let's see if current activity is MainActivity
|
||||
if (CrossCurrentActivity.Current.Activity is MainActivity activity && IsAlive(activity))
|
||||
{
|
||||
activity.RunOnUiThread(actionDismiss);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
bool IsAlive(Java.Lang.Object @object)
|
||||
{
|
||||
if (@object == null)
|
||||
return false;
|
||||
|
||||
if (@object.Handle == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
if (@object is Activity activity)
|
||||
{
|
||||
if (activity.IsFinishing)
|
||||
return false;
|
||||
|
||||
if (activity.IsDestroyed)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenFile(byte[] fileData, string id, string fileName)
|
||||
|
|
|
@ -36,6 +36,10 @@ namespace Bit.Droid.Utilities
|
|||
{
|
||||
get => ThemeManager.GetResourceColor("SwitchThumbColor").ToAndroid();
|
||||
}
|
||||
public static Color TextColor
|
||||
{
|
||||
get => ThemeManager.GetResourceColor("TextColor").ToAndroid();
|
||||
}
|
||||
|
||||
public static void SetAppearance(string theme, bool osDarkModeEnabled)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,9 @@ using System.Threading.Tasks;
|
|||
using Bit.App.Controls;
|
||||
using Bit.Core;
|
||||
using Xamarin.Forms;
|
||||
using View = Xamarin.Forms.View;
|
||||
#if !FDROID
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
#endif
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
@ -494,9 +496,12 @@ namespace Bit.App.Pages
|
|||
try
|
||||
{
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||
|
||||
await _cipherService.SaveWithServerAsync(cipher);
|
||||
Cipher.Id = cipher.Id;
|
||||
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
|
||||
_platformUtilsService.ShowToast("success", null,
|
||||
EditMode && !CloneMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
|
||||
_messagingService.Send(EditMode && !CloneMode ? "editedCipher" : "addedCipher", Cipher.Id);
|
||||
|
@ -512,19 +517,30 @@ namespace Bit.App.Pages
|
|||
{
|
||||
ViewPage?.UpdateCipherId(this.Cipher.Id);
|
||||
}
|
||||
await Page.Navigation.PopModalAsync();
|
||||
// if the app is tombstoned then PopModalAsync would throw index out of bounds
|
||||
if (Page.Navigation?.ModalStack?.Count > 0)
|
||||
{
|
||||
await Page.Navigation.PopModalAsync();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (ApiException e)
|
||||
catch (ApiException apiEx)
|
||||
{
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
if (e?.Error != null)
|
||||
if (apiEx?.Error != null)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(e.Error.GetSingleMessage(),
|
||||
await _platformUtilsService.ShowDialogAsync(apiEx.Error.GetSingleMessage(),
|
||||
AppResources.AnErrorHasOccurred);
|
||||
}
|
||||
}
|
||||
catch(Exception genex)
|
||||
{
|
||||
#if !FDROID
|
||||
Crashes.TrackError(genex);
|
||||
#endif
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue