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
};