diff --git a/src/Android/Accessibility/AccessibilityService.cs b/src/Android/Accessibility/AccessibilityService.cs
index 326653aff0..7f6aad01ba 100644
--- a/src/Android/Accessibility/AccessibilityService.cs
+++ b/src/Android/Accessibility/AccessibilityService.cs
@@ -255,13 +255,13 @@ namespace Bit.Droid.Accessibility
if (!AccessibilityHelpers.OverlayPermitted())
{
- if (!AccessibilityHelpers.IsAutofillTileAdded)
+ if (Build.VERSION.SdkInt <= BuildVersionCodes.M)
{
// The user has the option of only using the autofill tile and leaving the overlay permission
- // disabled, so only show this toast if they're using accessibility without overlay permission and
- // have _not_ added the autofill tile
+ // disabled, so only show this toast if they're using accessibility without overlay permission on
+ // a version of Android without quick-action tile support
System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted");
- Toast.MakeText(this, AppResources.AccessibilityOverlayPermissionAlert, ToastLength.Long).Show();
+ Toast.MakeText(this, AppResources.AccessibilityDrawOverPermissionAlert, ToastLength.Long).Show();
}
return;
}
diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj
index 076e761fad..abad97bb6e 100644
--- a/src/Android/Android.csproj
+++ b/src/Android/Android.csproj
@@ -161,28 +161,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Android/Autofill/AutofillHelpers.cs b/src/Android/Autofill/AutofillHelpers.cs
index 742fd302bd..8bce4672ee 100644
--- a/src/Android/Autofill/AutofillHelpers.cs
+++ b/src/Android/Autofill/AutofillHelpers.cs
@@ -143,13 +143,13 @@ namespace Bit.Droid.Autofill
}
public static FillResponse BuildFillResponse(Parser parser, List items, bool locked,
- FillRequest fillRequest = null)
+ bool inlineAutofillEnabled, FillRequest fillRequest = null)
{
// Acquire inline presentation specs on Android 11+
IList inlinePresentationSpecs = null;
var inlinePresentationSpecsCount = 0;
var inlineMaxSuggestedCount = 0;
- if (fillRequest != null && (int)Build.VERSION.SdkInt >= 30)
+ if (inlineAutofillEnabled && fillRequest != null && (int)Build.VERSION.SdkInt >= 30)
{
var inlineSuggestionsRequest = fillRequest.InlineSuggestionsRequest;
inlineMaxSuggestedCount = inlineSuggestionsRequest?.MaxSuggestionCount ?? 0;
diff --git a/src/Android/Autofill/AutofillService.cs b/src/Android/Autofill/AutofillService.cs
index 4c36fb223d..32a73d2cf0 100644
--- a/src/Android/Autofill/AutofillService.cs
+++ b/src/Android/Autofill/AutofillService.cs
@@ -46,6 +46,8 @@ namespace Bit.Droid.Autofill
{
return;
}
+
+ var inlineAutofillEnabled = await _storageService.GetAsync(Constants.InlineAutofillEnabledKey) ?? true;
if (_vaultTimeoutService == null)
{
@@ -64,7 +66,7 @@ namespace Bit.Droid.Autofill
}
// build response
- var response = AutofillHelpers.BuildFillResponse(parser, items, locked, request);
+ var response = AutofillHelpers.BuildFillResponse(parser, items, locked, inlineAutofillEnabled, request);
callback.OnSuccess(response);
}
diff --git a/src/Android/Resources/drawable-hdpi/accessibility_overlay.png b/src/Android/Resources/drawable-hdpi/accessibility_overlay.png
deleted file mode 100644
index 3ee6b41ea4..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/accessibility_overlay.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-hdpi/accessibility_permission.png b/src/Android/Resources/drawable-hdpi/accessibility_permission.png
deleted file mode 100644
index 4ea9736d72..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/accessibility_permission.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-hdpi/accessibility_step1.png b/src/Android/Resources/drawable-hdpi/accessibility_step1.png
deleted file mode 100644
index 0e248a7211..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/accessibility_step1.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-hdpi/accessibility_step2.png b/src/Android/Resources/drawable-hdpi/accessibility_step2.png
deleted file mode 100644
index 9ed205409b..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/accessibility_step2.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-hdpi/autofill_enable.png b/src/Android/Resources/drawable-hdpi/autofill_enable.png
deleted file mode 100644
index 61c5f81cc9..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/autofill_enable.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-hdpi/autofill_use.png b/src/Android/Resources/drawable-hdpi/autofill_use.png
deleted file mode 100644
index fb79c6a670..0000000000
Binary files a/src/Android/Resources/drawable-hdpi/autofill_use.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/accessibility_overlay.png b/src/Android/Resources/drawable-xhdpi/accessibility_overlay.png
deleted file mode 100644
index b55bf956b3..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/accessibility_overlay.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/accessibility_permission.png b/src/Android/Resources/drawable-xhdpi/accessibility_permission.png
deleted file mode 100644
index 942fa729ce..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/accessibility_permission.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/accessibility_step1.png b/src/Android/Resources/drawable-xhdpi/accessibility_step1.png
deleted file mode 100644
index 994b5c72c9..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/accessibility_step1.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/accessibility_step2.png b/src/Android/Resources/drawable-xhdpi/accessibility_step2.png
deleted file mode 100644
index 4d8d92d08c..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/accessibility_step2.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/autofill_enable.png b/src/Android/Resources/drawable-xhdpi/autofill_enable.png
deleted file mode 100644
index f3fd1dd03a..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/autofill_enable.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xhdpi/autofill_use.png b/src/Android/Resources/drawable-xhdpi/autofill_use.png
deleted file mode 100644
index d3ff23feb2..0000000000
Binary files a/src/Android/Resources/drawable-xhdpi/autofill_use.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/accessibility_overlay.png b/src/Android/Resources/drawable-xxhdpi/accessibility_overlay.png
deleted file mode 100644
index eaf993ff01..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/accessibility_overlay.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/accessibility_permission.png b/src/Android/Resources/drawable-xxhdpi/accessibility_permission.png
deleted file mode 100644
index 7d91c5d4c4..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/accessibility_permission.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/accessibility_step1.png b/src/Android/Resources/drawable-xxhdpi/accessibility_step1.png
deleted file mode 100644
index e6c1196891..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/accessibility_step1.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/accessibility_step2.png b/src/Android/Resources/drawable-xxhdpi/accessibility_step2.png
deleted file mode 100644
index b774085a64..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/accessibility_step2.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/autofill_enable.png b/src/Android/Resources/drawable-xxhdpi/autofill_enable.png
deleted file mode 100644
index 24636a2ee1..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/autofill_enable.png and /dev/null differ
diff --git a/src/Android/Resources/drawable-xxhdpi/autofill_use.png b/src/Android/Resources/drawable-xxhdpi/autofill_use.png
deleted file mode 100644
index 538ff52ae5..0000000000
Binary files a/src/Android/Resources/drawable-xxhdpi/autofill_use.png and /dev/null differ
diff --git a/src/Android/Services/DeviceActionService.cs b/src/Android/Services/DeviceActionService.cs
index 8e0a445558..898be8c408 100644
--- a/src/Android/Services/DeviceActionService.cs
+++ b/src/Android/Services/DeviceActionService.cs
@@ -378,6 +378,34 @@ namespace Bit.Droid.Services
}
}
+ public void DisableAutofillService()
+ {
+ try
+ {
+ var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
+ var type = Java.Lang.Class.FromType(typeof(AutofillManager));
+ var manager = activity.GetSystemService(type) as AutofillManager;
+ manager.DisableAutofillServices();
+ }
+ catch { }
+ }
+
+ public bool AutofillServicesEnabled()
+ {
+ if (Build.VERSION.SdkInt <= BuildVersionCodes.M)
+ {
+ // Android 5-6: Both accessibility & overlay are required or nothing happens
+ return AutofillAccessibilityServiceRunning() && AutofillAccessibilityOverlayPermitted();
+ }
+ if (Build.VERSION.SdkInt == BuildVersionCodes.N)
+ {
+ // Android 7: Only accessibility is required (overlay is optional when using quick-action tile)
+ return AutofillAccessibilityServiceRunning();
+ }
+ // Android 8+: Either autofill or accessibility is required
+ return AutofillServiceEnabled() || AutofillAccessibilityServiceRunning();
+ }
+
public string GetBuildNumber()
{
return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(
diff --git a/src/App/Abstractions/IDeviceActionService.cs b/src/App/Abstractions/IDeviceActionService.cs
index 9c55f2fba7..2d1d200671 100644
--- a/src/App/Abstractions/IDeviceActionService.cs
+++ b/src/App/Abstractions/IDeviceActionService.cs
@@ -36,6 +36,8 @@ namespace Bit.App.Abstractions
bool AutofillAccessibilityServiceRunning();
bool AutofillAccessibilityOverlayPermitted();
bool AutofillServiceEnabled();
+ void DisableAutofillService();
+ bool AutofillServicesEnabled();
string GetBuildNumber();
void OpenAccessibilitySettings();
void OpenAccessibilityOverlayPermissionSettings();
diff --git a/src/App/App.csproj b/src/App/App.csproj
index 3d1d938fe1..c5eb2326ab 100644
--- a/src/App/App.csproj
+++ b/src/App/App.csproj
@@ -57,8 +57,8 @@
ExtensionPage.xaml
-
- AutofillServicePage.xaml
+
+ AutofillServicesPage.xaml
FolderAddEditPage.xaml
@@ -72,9 +72,6 @@
OptionsPage.xaml
-
- AccessibilityServicePage.xaml
-
SyncPage.xaml
diff --git a/src/App/Pages/Settings/AccessibilityServicePage.xaml b/src/App/Pages/Settings/AccessibilityServicePage.xaml
deleted file mode 100644
index b3555a690d..0000000000
--- a/src/App/Pages/Settings/AccessibilityServicePage.xaml
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/App/Pages/Settings/AccessibilityServicePageViewModel.cs b/src/App/Pages/Settings/AccessibilityServicePageViewModel.cs
deleted file mode 100644
index 0d91c75fe0..0000000000
--- a/src/App/Pages/Settings/AccessibilityServicePageViewModel.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using Bit.App.Abstractions;
-using Bit.App.Resources;
-using Bit.Core.Utilities;
-
-namespace Bit.App.Pages
-{
- public class AccessibilityServicePageViewModel : BaseViewModel
- {
- private readonly IDeviceActionService _deviceActionService;
-
- private bool _enabled;
- private bool _permitted;
-
- public AccessibilityServicePageViewModel()
- {
- _deviceActionService = ServiceContainer.Resolve("deviceActionService");
- PageTitle = AppResources.AutofillAccessibilityService;
- }
-
- public bool Enabled
- {
- get => _enabled;
- set => SetProperty(ref _enabled, value,
- additionalPropertyNames: new string[]
- {
- nameof(EnabledWithoutPermission),
- nameof(EnabledAndPermitted)
- });
- }
-
- public bool Permitted
- {
- get => _permitted;
- set => SetProperty(ref _permitted, value,
- additionalPropertyNames: new string[]
- {
- nameof(EnabledWithoutPermission),
- nameof(EnabledAndPermitted)
- });
- }
-
- public bool EnabledWithoutPermission => Enabled && !Permitted;
-
- public bool EnabledAndPermitted => Enabled && Permitted;
-
- public void OpenSettings()
- {
- _deviceActionService.OpenAccessibilitySettings();
- }
-
- public void OpenOverlayPermissionSettings()
- {
- _deviceActionService.OpenAccessibilityOverlayPermissionSettings();
- }
-
- public void UpdateEnabled()
- {
- Enabled = _deviceActionService.AutofillAccessibilityServiceRunning();
- }
-
- public void UpdatePermitted()
- {
- Permitted = _deviceActionService.AutofillAccessibilityOverlayPermitted();
- }
- }
-}
diff --git a/src/App/Pages/Settings/AutofillServicePage.xaml b/src/App/Pages/Settings/AutofillServicePage.xaml
deleted file mode 100644
index b703f9436f..0000000000
--- a/src/App/Pages/Settings/AutofillServicePage.xaml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/App/Pages/Settings/AutofillServicePage.xaml.cs b/src/App/Pages/Settings/AutofillServicePage.xaml.cs
deleted file mode 100644
index 14f3ad54fc..0000000000
--- a/src/App/Pages/Settings/AutofillServicePage.xaml.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using Xamarin.Forms;
-
-namespace Bit.App.Pages
-{
- public partial class AutofillServicePage : BaseContentPage
- {
- private readonly AutofillServicePageViewModel _vm;
- private readonly SettingsPage _settingsPage;
- private DateTime? _timerStarted = null;
- private TimeSpan _timerMaxLength = TimeSpan.FromMinutes(5);
-
- public AutofillServicePage(SettingsPage settingsPage)
- {
- InitializeComponent();
- _vm = BindingContext as AutofillServicePageViewModel;
- _vm.Page = this;
- _settingsPage = settingsPage;
- }
-
- protected override void OnAppearing()
- {
- _vm.UpdateEnabled();
- _timerStarted = DateTime.UtcNow;
- Device.StartTimer(new TimeSpan(0, 0, 2), () =>
- {
- if (_timerStarted == null || (DateTime.UtcNow - _timerStarted) > _timerMaxLength)
- {
- return false;
- }
- _vm.UpdateEnabled();
- return true;
- });
- base.OnAppearing();
- }
-
- protected override void OnDisappearing()
- {
- _timerStarted = null;
- _settingsPage.BuildList();
- base.OnDisappearing();
- }
-
- private void Settings_Clicked(object sender, EventArgs e)
- {
- if (DoOnce())
- {
- _vm.OpenSettings();
- }
- }
- }
-}
diff --git a/src/App/Pages/Settings/AutofillServicePageViewModel.cs b/src/App/Pages/Settings/AutofillServicePageViewModel.cs
deleted file mode 100644
index a37e53f241..0000000000
--- a/src/App/Pages/Settings/AutofillServicePageViewModel.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Bit.App.Abstractions;
-using Bit.App.Resources;
-using Bit.Core.Utilities;
-
-namespace Bit.App.Pages
-{
- public class AutofillServicePageViewModel : BaseViewModel
- {
- private readonly IDeviceActionService _deviceActionService;
-
- private bool _enabled;
-
- public AutofillServicePageViewModel()
- {
- _deviceActionService = ServiceContainer.Resolve("deviceActionService");
- PageTitle = AppResources.AutofillService;
- }
-
- public bool Enabled
- {
- get => _enabled;
- set => SetProperty(ref _enabled, value);
- }
-
- public void OpenSettings()
- {
- _deviceActionService.OpenAutofillSettings();
- }
-
- public void UpdateEnabled()
- {
- Enabled = _deviceActionService.AutofillServiceEnabled();
- }
- }
-}
diff --git a/src/App/Pages/Settings/AutofillServicesPage.xaml b/src/App/Pages/Settings/AutofillServicesPage.xaml
new file mode 100644
index 0000000000..8f823c2953
--- /dev/null
+++ b/src/App/Pages/Settings/AutofillServicesPage.xaml
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/App/Pages/Settings/AccessibilityServicePage.xaml.cs b/src/App/Pages/Settings/AutofillServicesPage.xaml.cs
similarity index 53%
rename from src/App/Pages/Settings/AccessibilityServicePage.xaml.cs
rename to src/App/Pages/Settings/AutofillServicesPage.xaml.cs
index 93dc5ed32b..72719b7840 100644
--- a/src/App/Pages/Settings/AccessibilityServicePage.xaml.cs
+++ b/src/App/Pages/Settings/AutofillServicesPage.xaml.cs
@@ -3,34 +3,33 @@ using Xamarin.Forms;
namespace Bit.App.Pages
{
- public partial class AccessibilityServicePage : BaseContentPage
+ public partial class AutofillServicesPage : BaseContentPage
{
- private readonly AccessibilityServicePageViewModel _vm;
+ private readonly AutofillServicesPageViewModel _vm;
private readonly SettingsPage _settingsPage;
private DateTime? _timerStarted = null;
private TimeSpan _timerMaxLength = TimeSpan.FromMinutes(5);
- public AccessibilityServicePage(SettingsPage settingsPage)
+ public AutofillServicesPage(SettingsPage settingsPage)
{
InitializeComponent();
- _vm = BindingContext as AccessibilityServicePageViewModel;
+ _vm = BindingContext as AutofillServicesPageViewModel;
_vm.Page = this;
_settingsPage = settingsPage;
}
- protected override void OnAppearing()
+ protected async override void OnAppearing()
{
+ await _vm.InitAsync();
_vm.UpdateEnabled();
- _vm.UpdatePermitted();
_timerStarted = DateTime.UtcNow;
- Device.StartTimer(new TimeSpan(0, 0, 3), () =>
+ Device.StartTimer(new TimeSpan(0, 0, 0, 0, 500), () =>
{
if (_timerStarted == null || (DateTime.UtcNow - _timerStarted) > _timerMaxLength)
{
return false;
}
_vm.UpdateEnabled();
- _vm.UpdatePermitted();
return true;
});
base.OnAppearing();
@@ -43,19 +42,32 @@ namespace Bit.App.Pages
base.OnDisappearing();
}
- private void Settings_Clicked(object sender, EventArgs e)
+ private void ToggleAutofillService(object sender, EventArgs e)
{
if (DoOnce())
{
- _vm.OpenSettings();
+ _vm.ToggleAutofillService();
}
}
-
- private void OverlayPermissionSettings_Clicked(object sender, EventArgs e)
+
+ private void ToggleInlineAutofill(object sender, EventArgs e)
+ {
+ _vm.ToggleInlineAutofill();
+ }
+
+ private void ToggleAccessibility(object sender, EventArgs e)
{
if (DoOnce())
{
- _vm.OpenOverlayPermissionSettings();
+ _vm.ToggleAccessibility();
+ }
+ }
+
+ private void ToggleDrawOver(object sender, EventArgs e)
+ {
+ if (DoOnce())
+ {
+ _vm.ToggleDrawOver();
}
}
}
diff --git a/src/App/Pages/Settings/AutofillServicesPageViewModel.cs b/src/App/Pages/Settings/AutofillServicesPageViewModel.cs
new file mode 100644
index 0000000000..1fad4cc534
--- /dev/null
+++ b/src/App/Pages/Settings/AutofillServicesPageViewModel.cs
@@ -0,0 +1,201 @@
+using System.Threading.Tasks;
+using Bit.App.Abstractions;
+using Bit.App.Resources;
+using Bit.App.Services;
+using Bit.Core;
+using Bit.Core.Abstractions;
+using Bit.Core.Utilities;
+
+namespace Bit.App.Pages
+{
+ public class AutofillServicesPageViewModel : BaseViewModel
+ {
+ private readonly IDeviceActionService _deviceActionService;
+ private readonly IStorageService _storageService;
+ private readonly MobileI18nService _i18nService;
+
+ private bool _autofillServiceToggled;
+ private bool _inlineAutofillToggled;
+ private bool _accessibilityToggled;
+ private bool _drawOverToggled;
+ private bool _inited;
+
+ public AutofillServicesPageViewModel()
+ {
+ _deviceActionService = ServiceContainer.Resolve("deviceActionService");
+ _storageService = ServiceContainer.Resolve("storageService");
+ _i18nService = ServiceContainer.Resolve("i18nService") as MobileI18nService;
+ PageTitle = AppResources.AutofillServices;
+ }
+
+ #region Autofill Service
+
+ public bool AutofillServiceVisible
+ {
+ get => _deviceActionService.SystemMajorVersion() >= 26;
+ }
+
+ public bool AutofillServiceToggled
+ {
+ get => _autofillServiceToggled;
+ set => SetProperty(ref _autofillServiceToggled, value,
+ additionalPropertyNames: new string[]
+ {
+ nameof(InlineAutofillEnabled)
+ });
+ }
+
+ #endregion
+
+ #region Inline Autofill
+
+ public bool InlineAutofillVisible
+ {
+ get => _deviceActionService.SystemMajorVersion() >= 30;
+ }
+
+ public bool InlineAutofillEnabled
+ {
+ get => AutofillServiceToggled;
+ }
+
+ public bool InlineAutofillToggled
+ {
+ get => _inlineAutofillToggled;
+ set
+ {
+ if (SetProperty(ref _inlineAutofillToggled, value))
+ {
+ var task = UpdateInlineAutofillToggledAsync();
+ }
+ }
+ }
+
+ #endregion
+
+ #region Accessibility
+
+ public string AccessibilityDescriptionLabel
+ {
+ get
+ {
+ if (_deviceActionService.SystemMajorVersion() <= 22)
+ {
+ // Android 5
+ return _i18nService.T("AccessibilityDescription");
+ }
+ if (_deviceActionService.SystemMajorVersion() == 23)
+ {
+ // Android 6
+ return _i18nService.T("AccessibilityDescription2");
+ }
+ if (_deviceActionService.SystemMajorVersion() == 24 || _deviceActionService.SystemMajorVersion() == 25)
+ {
+ // Android 7
+ return _i18nService.T("AccessibilityDescription3");
+ }
+ // Android 8+
+ return _i18nService.T("AccessibilityDescription4");
+ }
+ }
+
+ public bool AccessibilityToggled
+ {
+ get => _accessibilityToggled;
+ set => SetProperty(ref _accessibilityToggled, value,
+ additionalPropertyNames: new string[]
+ {
+ nameof(DrawOverEnabled)
+ });
+ }
+
+ #endregion
+
+ #region Draw-Over
+
+ public bool DrawOverVisible
+ {
+ get => _deviceActionService.SystemMajorVersion() >= 23;
+ }
+
+ public string DrawOverDescriptionLabel
+ {
+ get
+ {
+ if (_deviceActionService.SystemMajorVersion() <= 23)
+ {
+ // Android 6
+ return _i18nService.T("DrawOverDescription");
+ }
+ if (_deviceActionService.SystemMajorVersion() == 24 || _deviceActionService.SystemMajorVersion() == 25)
+ {
+ // Android 7
+ return _i18nService.T("DrawOverDescription2");
+ }
+ // Android 8+
+ return _i18nService.T("DrawOverDescription3");
+ }
+ }
+
+ public bool DrawOverEnabled
+ {
+ get => AccessibilityToggled;
+ }
+
+ public bool DrawOverToggled
+ {
+ get => _drawOverToggled;
+ set => SetProperty(ref _drawOverToggled, value);
+ }
+
+ #endregion
+
+ public async Task InitAsync()
+ {
+ InlineAutofillToggled = await _storageService.GetAsync(Constants.InlineAutofillEnabledKey) ?? true;
+ _inited = true;
+ }
+
+ public void ToggleAutofillService()
+ {
+ if (!AutofillServiceToggled)
+ {
+ _deviceActionService.OpenAutofillSettings();
+ }
+ else
+ {
+ _deviceActionService.DisableAutofillService();
+ }
+ }
+
+ public void ToggleInlineAutofill()
+ {
+ InlineAutofillToggled = !InlineAutofillToggled;
+ }
+
+ public void ToggleAccessibility()
+ {
+ _deviceActionService.OpenAccessibilitySettings();
+ }
+
+ public void ToggleDrawOver()
+ {
+ _deviceActionService.OpenAccessibilityOverlayPermissionSettings();
+ }
+
+ public void UpdateEnabled()
+ {
+ AutofillServiceToggled = _deviceActionService.AutofillServiceEnabled();
+ AccessibilityToggled = _deviceActionService.AutofillAccessibilityServiceRunning();
+ DrawOverToggled = _deviceActionService.AutofillAccessibilityOverlayPermitted();
+ }
+
+ private async Task UpdateInlineAutofillToggledAsync()
+ {
+ if (_inited)
+ {
+ await _storageService.SaveAsync(Constants.InlineAutofillEnabledKey, InlineAutofillToggled);
+ }
+ }
+ }
+}
diff --git a/src/App/Pages/Settings/SettingsPage/SettingsPage.xaml.cs b/src/App/Pages/Settings/SettingsPage/SettingsPage.xaml.cs
index ff1d3e16b9..a6dc34c41c 100644
--- a/src/App/Pages/Settings/SettingsPage/SettingsPage.xaml.cs
+++ b/src/App/Pages/Settings/SettingsPage/SettingsPage.xaml.cs
@@ -57,13 +57,9 @@ namespace Bit.App.Pages
{
await Navigation.PushModalAsync(new NavigationPage(new SyncPage()));
}
- else if (item.Name == AppResources.AutofillAccessibilityService)
+ else if (item.Name == AppResources.AutofillServices)
{
- await Navigation.PushModalAsync(new NavigationPage(new AccessibilityServicePage(this)));
- }
- else if (item.Name == AppResources.AutofillService)
- {
- await Navigation.PushModalAsync(new NavigationPage(new AutofillServicePage(this)));
+ await Navigation.PushModalAsync(new NavigationPage(new AutofillServicesPage(this)));
}
else if (item.Name == AppResources.PasswordAutofill)
{
diff --git a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs
index 3656b54650..958e2bd915 100644
--- a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs
+++ b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs
@@ -326,22 +326,10 @@ namespace Bit.App.Pages
var autofillItems = new List();
if (Device.RuntimePlatform == Device.Android)
{
- if (_deviceActionService.SupportsAutofillService())
- {
- autofillItems.Add(new SettingsPageListItem
- {
- Name = AppResources.AutofillService,
- SubLabel = _deviceActionService.AutofillServiceEnabled() ?
- AppResources.Enabled : AppResources.Disabled
- });
- }
-
- var accessibilityEnabled = _deviceActionService.AutofillAccessibilityServiceRunning() &&
- _deviceActionService.AutofillAccessibilityOverlayPermitted();
autofillItems.Add(new SettingsPageListItem
{
- Name = AppResources.AutofillAccessibilityService,
- SubLabel = accessibilityEnabled ?
+ Name = AppResources.AutofillServices,
+ SubLabel = _deviceActionService.AutofillServicesEnabled() ?
AppResources.Enabled : AppResources.Disabled
});
}
diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs
index 9a496acf90..12695127bc 100644
--- a/src/App/Resources/AppResources.Designer.cs
+++ b/src/App/Resources/AppResources.Designer.cs
@@ -3074,5 +3074,83 @@ namespace Bit.App.Resources {
return ResourceManager.GetString("PrivacyPolicy", resourceCulture);
}
}
+
+ public static string AccessibilityDrawOverPermissionAlert {
+ get {
+ return ResourceManager.GetString("AccessibilityDrawOverPermissionAlert", resourceCulture);
+ }
+ }
+
+ public static string AutofillServices {
+ get {
+ return ResourceManager.GetString("AutofillServices", resourceCulture);
+ }
+ }
+
+ public static string InlineAutofill {
+ get {
+ return ResourceManager.GetString("InlineAutofill", resourceCulture);
+ }
+ }
+
+ public static string InlineAutofillDescription {
+ get {
+ return ResourceManager.GetString("InlineAutofillDescription", resourceCulture);
+ }
+ }
+
+ public static string Accessibility {
+ get {
+ return ResourceManager.GetString("Accessibility", resourceCulture);
+ }
+ }
+
+ public static string AccessibilityDescription {
+ get {
+ return ResourceManager.GetString("AccessibilityDescription", resourceCulture);
+ }
+ }
+
+ public static string AccessibilityDescription2 {
+ get {
+ return ResourceManager.GetString("AccessibilityDescription2", resourceCulture);
+ }
+ }
+
+ public static string AccessibilityDescription3 {
+ get {
+ return ResourceManager.GetString("AccessibilityDescription3", resourceCulture);
+ }
+ }
+
+ public static string AccessibilityDescription4 {
+ get {
+ return ResourceManager.GetString("AccessibilityDescription4", resourceCulture);
+ }
+ }
+
+ public static string DrawOver {
+ get {
+ return ResourceManager.GetString("DrawOver", resourceCulture);
+ }
+ }
+
+ public static string DrawOverDescription {
+ get {
+ return ResourceManager.GetString("DrawOverDescription", resourceCulture);
+ }
+ }
+
+ public static string DrawOverDescription2 {
+ get {
+ return ResourceManager.GetString("DrawOverDescription2", resourceCulture);
+ }
+ }
+
+ public static string DrawOverDescription3 {
+ get {
+ return ResourceManager.GetString("DrawOverDescription3", resourceCulture);
+ }
+ }
}
}
diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx
index 450fefafba..9ae1aae895 100644
--- a/src/App/Resources/AppResources.resx
+++ b/src/App/Resources/AppResources.resx
@@ -1744,4 +1744,43 @@
Privacy Policy
+
+ Bitwarden needs attention - Enable "Draw-Over" in "Auto-fill Services" from Bitwarden Settings
+
+
+ Auto-fill Services
+
+
+ Use Inline Autofill
+
+
+ Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is disabled), the default Autofill overlay will be used.
+
+
+ Use Accessibility
+
+
+ Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When enabled, we'll display a popup when login fields are selected.
+
+
+ Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be enabled as well)
+
+
+ Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if enabled).
+
+
+ Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if enabled).
+
+
+ Use Draw-Over
+
+
+ When enabled, allows the Bitwarden Accessibility Service to display a popup when login fields are selected.
+
+
+ If enabled, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins.
+
+
+ If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.
+
\ No newline at end of file
diff --git a/src/App/Services/MobileStorageService.cs b/src/App/Services/MobileStorageService.cs
index 3762220934..ba262dde90 100644
--- a/src/App/Services/MobileStorageService.cs
+++ b/src/App/Services/MobileStorageService.cs
@@ -35,6 +35,7 @@ namespace Bit.App.Services
Constants.iOSAutoFillClearCiphersCacheKey,
Constants.iOSExtensionClearCiphersCacheKey,
Constants.EnvironmentUrlsKey,
+ Constants.InlineAutofillEnabledKey,
};
private readonly HashSet _migrateToPreferences = new HashSet
diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs
index 031bf042ee..b2b6164eac 100644
--- a/src/Core/Constants.cs
+++ b/src/Core/Constants.cs
@@ -36,6 +36,7 @@
public static string TriedV1Resync = "triedV1Resync";
public static string EventCollectionKey = "eventCollection";
public static string PreviousPageKey = "previousPage";
+ public static string InlineAutofillEnabledKey = "inlineAutofillEnabled";
public const int SelectFileRequestCode = 42;
public const int SelectFilePermissionRequestCode = 43;
public const int SaveFileRequestCode = 44;
diff --git a/src/iOS.Core/Services/DeviceActionService.cs b/src/iOS.Core/Services/DeviceActionService.cs
index e1b0132ce1..a1ed3bcb9e 100644
--- a/src/iOS.Core/Services/DeviceActionService.cs
+++ b/src/iOS.Core/Services/DeviceActionService.cs
@@ -392,6 +392,16 @@ namespace Bit.iOS.Core.Services
throw new NotImplementedException();
}
+ public void DisableAutofillService()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool AutofillServicesEnabled()
+ {
+ throw new NotImplementedException();
+ }
+
public string GetBuildNumber()
{
return NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString();