diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index 4cb6d50ce..c6aad805e 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -327,6 +327,7 @@ + diff --git a/src/Android/AutofillService.cs b/src/Android/AutofillService.cs index b7473839f..62d6202df 100644 --- a/src/Android/AutofillService.cs +++ b/src/Android/AutofillService.cs @@ -153,7 +153,7 @@ namespace Bit.Android private string ExtractUri(string uri, AccessibilityNodeInfo addressNode) { - if(addressNode != null) + if(addressNode?.Text != null) { uri = addressNode.Text; if(!uri.Contains("://")) diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index 20facc7a2..bdf0388e8 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -135,6 +135,7 @@ namespace Bit.Android Parent.SetResult(Result.Ok, data); } + MessagingCenter.Send(Xamarin.Forms.Application.Current, "SetMainPage"); Finish(); } diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs index 4eb52160e..cf8925a55 100644 --- a/src/Android/MainApplication.cs +++ b/src/Android/MainApplication.cs @@ -212,6 +212,7 @@ namespace Bit.Android .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) + .RegisterType(new ContainerControlledLifetimeManager()) // Repositories .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) diff --git a/src/Android/Services/MemoryService.cs b/src/Android/Services/MemoryService.cs new file mode 100644 index 000000000..37f9ccc48 --- /dev/null +++ b/src/Android/Services/MemoryService.cs @@ -0,0 +1,44 @@ +using System; +using Android.Content; +using Bit.App.Abstractions; +using Xamarin.Forms; + +namespace Bit.Android.Services +{ + public class MemoryService : IMemoryService + { + public MemoryInfo GetInfo() + { + return MemoryHelper.GetMemoryInfo(Forms.Context); + } + + public void Check() + { + MemoryHelper.MemoryCheck(Forms.Context); + } + + public static class MemoryHelper + { + public static void MemoryCheck(Context context) + { + Console.WriteLine("MemoryHelper.MemoryCheck.{0} - {1}", "Start", context.ToString()); + var maxMemory = Java.Lang.Runtime.GetRuntime().MaxMemory(); + var freeMemory = Java.Lang.Runtime.GetRuntime().FreeMemory(); + var percentUsed = (maxMemory - freeMemory) / (double)maxMemory; + Console.WriteLine("Free memory: {0:N}", freeMemory); + Console.WriteLine("Max memory: {0:N}", maxMemory); + Console.WriteLine("% used: {0:P}", percentUsed); + Console.WriteLine("MemoryHelper.MemoryCheck.{0} {3:P} {1} out of {2}", "End", freeMemory, maxMemory, percentUsed); + } + + public static MemoryInfo GetMemoryInfo(Context context) + { + var retVal = new MemoryInfo(); + retVal.MaxMemory = Java.Lang.Runtime.GetRuntime().MaxMemory(); + retVal.FreeMemory = Java.Lang.Runtime.GetRuntime().FreeMemory(); + retVal.TotalMemory = Java.Lang.Runtime.GetRuntime().TotalMemory(); + return retVal; + } + } + } +} diff --git a/src/App/Abstractions/Services/IMemoryService.cs b/src/App/Abstractions/Services/IMemoryService.cs new file mode 100644 index 000000000..5f5c939e9 --- /dev/null +++ b/src/App/Abstractions/Services/IMemoryService.cs @@ -0,0 +1,26 @@ +namespace Bit.App.Abstractions +{ + public interface IMemoryService + { + MemoryInfo GetInfo(); + void Check(); + } + + public class MemoryInfo + { + public long FreeMemory { get; set; } + public long MaxMemory { get; set; } + public long TotalMemory { get; set; } + public long UsedMemory => TotalMemory - FreeMemory; + + public double HeapUsage() + { + return UsedMemory / (double)TotalMemory; + } + + public double Usage() + { + return UsedMemory / (double)MaxMemory; + } + } +} diff --git a/src/App/App.cs b/src/App/App.cs index 1e1b5d275..56070914c 100644 --- a/src/App/App.cs +++ b/src/App/App.cs @@ -14,7 +14,6 @@ using Acr.UserDialogs; using XLabs.Ioc; using System.Reflection; using Bit.App.Resources; -using System.Threading; namespace Bit.App { @@ -23,6 +22,7 @@ namespace Bit.App private const string LastBuildKey = "LastBuild"; private string _uri; + private DateTime _lastMainPageSet = DateTime.MinValue; private readonly IDatabaseService _databaseService; private readonly IConnectivity _connectivity; private readonly IUserDialogs _userDialogs; @@ -80,7 +80,7 @@ namespace Bit.App MessagingCenter.Subscribe(Current, "Resumed", async (sender, args) => { - await CheckLockAsync(args); + Device.BeginInvokeOnMainThread(async () => await CheckLockAsync(args)); await Task.Run(() => FullSyncAsync()).ConfigureAwait(false); }); @@ -91,7 +91,12 @@ namespace Bit.App MessagingCenter.Subscribe(Current, "Logout", (sender, args) => { - Device.BeginInvokeOnMainThread(() => Logout(args)); + Logout(args); + }); + + MessagingCenter.Subscribe(Current, "SetMainPage", (sender) => + { + SetMainPageFromAutofill(); }); } @@ -120,12 +125,8 @@ namespace Bit.App // Handle when your app sleeps Debug.WriteLine("OnSleep"); - if(Device.OS == TargetPlatform.Android && !string.IsNullOrWhiteSpace(_uri)) - { - MainPage = new MainPage(); - _uri = null; - } - + SetMainPageFromAutofill(); + if(Device.OS == TargetPlatform.Android && !TopPageIsLock()) { _settings.AddOrUpdateValue(Constants.LastActivityDate, DateTime.UtcNow); @@ -160,6 +161,22 @@ namespace Bit.App } } + private void SetMainPageFromAutofill() + { + if(Device.OS == TargetPlatform.Android && !string.IsNullOrWhiteSpace(_uri)) + { + var now = DateTime.UtcNow; + if((now - _lastMainPageSet).Seconds <= 1) + { + return; + } + + _lastMainPageSet = now; + Device.BeginInvokeOnMainThread(() => MainPage = new MainPage()); + _uri = null; + } + } + private bool InDebugMode() { #if DEBUG @@ -214,7 +231,8 @@ namespace Bit.App _googleAnalyticsService.TrackAppEvent("LoggedOut"); _googleAnalyticsService.RefreshUserId(); - Current.MainPage = new ExtendedNavigationPage(new HomePage()); + + Device.BeginInvokeOnMainThread(() => Current.MainPage = new ExtendedNavigationPage(new HomePage())); if(!string.IsNullOrWhiteSpace(logoutMessage)) { _userDialogs.Toast(logoutMessage); @@ -235,7 +253,6 @@ namespace Bit.App } var lockType = _lockService.GetLockType(forceLock); - var currentPage = Current.MainPage.Navigation.ModalStack.LastOrDefault() as ExtendedNavigationPage; switch(lockType) { case Enums.LockType.Fingerprint: diff --git a/src/App/App.csproj b/src/App/App.csproj index 28d73e6f9..03b24fe92 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -39,6 +39,7 @@ + @@ -62,6 +63,7 @@ + diff --git a/src/App/Controls/MemoryContentView.cs b/src/App/Controls/MemoryContentView.cs new file mode 100644 index 000000000..b6d34e25d --- /dev/null +++ b/src/App/Controls/MemoryContentView.cs @@ -0,0 +1,108 @@ +using Bit.App.Abstractions; +using System; +using Xamarin.Forms; +using XLabs.Ioc; + +namespace Bit.App.Controls +{ + public class MemoryContentView : ContentView + { + private readonly IMemoryService _memoryService; + + public MemoryContentView() + { + _memoryService = Resolver.Resolve(); + + var grid = new Grid + { + Padding = 5, + BackgroundColor = Color.White, + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto } + }, + ColumnDefinitions = new ColumnDefinitionCollection + { + new ColumnDefinition { Width = GridLength.Star }, + new ColumnDefinition { Width = GridLength.Star } + } + }; + + grid.Children.Add(new Label { Text = "Used Memory:" }, 0, 0); + grid.Children.Add(new Label { Text = "Free Memory:" }, 0, 1); + grid.Children.Add(new Label { Text = "Heap Memory:" }, 0, 2); + grid.Children.Add(new Label { Text = "Max Memory:" }, 0, 3); + grid.Children.Add(new Label { Text = "% Used Heap:" }, 0, 4); + grid.Children.Add(new Label { Text = "% Used Max:" }, 0, 5); + + UsedMemory = new Label { Text = "Used Memory:", HorizontalTextAlignment = TextAlignment.End }; + FreeMemory = new Label { Text = "Free Memory:", HorizontalTextAlignment = TextAlignment.End }; + HeapMemory = new Label { Text = "Heap Memory:", HorizontalTextAlignment = TextAlignment.End }; + MaxMemory = new Label { Text = "Max Memory:", HorizontalTextAlignment = TextAlignment.End }; + HeapUsage = new Label { Text = "% Used Heap:", HorizontalTextAlignment = TextAlignment.End }; + TotalUsage = new Label { Text = "% Used Max:", HorizontalTextAlignment = TextAlignment.End }; + + grid.Children.Add(UsedMemory, 1, 0); + grid.Children.Add(FreeMemory, 1, 1); + grid.Children.Add(HeapMemory, 1, 2); + grid.Children.Add(MaxMemory, 1, 3); + grid.Children.Add(HeapUsage, 1, 4); + grid.Children.Add(TotalUsage, 1, 5); + + var button = new ExtendedButton { Text = "Refresh", BackgroundColor = Color.Transparent }; + button.Clicked += Button_Clicked; + grid.Children.Add(button, 0, 6); + Grid.SetColumnSpan(button, 2); + + Content = grid; + + RefreshScreen(); + } + + private void Button_Clicked(object sender, EventArgs e) + { + RefreshScreen(); + } + + public Label UsedMemory { get; set; } + public Label FreeMemory { get; set; } + public Label HeapMemory { get; set; } + public Label MaxMemory { get; set; } + public Label HeapUsage { get; set; } + public Label TotalUsage { get; set; } + + void RefreshScreen() + { + UsedMemory.Text = FreeMemory.Text = HeapMemory.Text = MaxMemory.Text = + HeapUsage.Text = TotalUsage.Text = string.Empty; + + UsedMemory.TextColor = FreeMemory.TextColor = HeapMemory.TextColor = + MaxMemory.TextColor = HeapUsage.TextColor = TotalUsage.TextColor = Color.Black; + + if(_memoryService != null) + { + var info = _memoryService.GetInfo(); + if(info != null) + { + UsedMemory.Text = string.Format("{0:N} mb", Math.Round(info.UsedMemory / 1024 / 1024D, 2)); + FreeMemory.Text = string.Format("{0:N} mb", Math.Round(info.FreeMemory / 1024 / 1024D, 2)); + HeapMemory.Text = string.Format("{0:N} mb", Math.Round(info.TotalMemory / 1024 / 1024D, 2)); + MaxMemory.Text = string.Format("{0:N} mb", Math.Round(info.MaxMemory / 1024 / 1024D, 2)); + HeapUsage.Text = string.Format("{0:P}", info.HeapUsage()); + TotalUsage.Text = string.Format("{0:P}", info.Usage()); + + if(info.Usage() > 0.8) + { + FreeMemory.TextColor = UsedMemory.TextColor = TotalUsage.TextColor = Color.Red; + } + } + } + } + } +} diff --git a/src/App/Pages/Vault/VaultListLoginsPage.cs b/src/App/Pages/Vault/VaultListLoginsPage.cs index 3907cab1b..d84866f6a 100644 --- a/src/App/Pages/Vault/VaultListLoginsPage.cs +++ b/src/App/Pages/Vault/VaultListLoginsPage.cs @@ -117,7 +117,7 @@ namespace Bit.App.Pages ResultsStackLayout = new StackLayout { - Children = { Search, ListView }, + Children = { new MemoryContentView(), Search, ListView }, Spacing = 0 };