diff --git a/src/Android/Properties/AndroidManifest.xml b/src/Android/Properties/AndroidManifest.xml index 1c9f45819..8fd7e6da3 100644 --- a/src/Android/Properties/AndroidManifest.xml +++ b/src/Android/Properties/AndroidManifest.xml @@ -13,6 +13,9 @@ + + + (Application.Current, "SelectFileCameraPermissionDenied"); var hasStorageWritePermission = !_cameraPermissionsDenied && HasPermission(Manifest.Permission.WriteExternalStorage); - var hasCameraPermission = !_cameraPermissionsDenied && HasPermission(Manifest.Permission.Camera); - - if(!_cameraPermissionsDenied && !hasStorageWritePermission) - { - AskCameraPermission(Manifest.Permission.WriteExternalStorage); - return Task.FromResult(0); - } - - if(!_cameraPermissionsDenied && !hasCameraPermission) - { - AskCameraPermission(Manifest.Permission.Camera); - return Task.FromResult(0); - } var additionalIntents = new List(); + if(Forms.Context.PackageManager.HasSystemFeature(PackageManager.FeatureCamera)) + { + var hasCameraPermission = !_cameraPermissionsDenied && HasPermission(Manifest.Permission.Camera); + + if(!_cameraPermissionsDenied && !hasStorageWritePermission) + { + AskCameraPermission(Manifest.Permission.WriteExternalStorage); + return Task.FromResult(0); + } + + if(!_cameraPermissionsDenied && !hasCameraPermission) + { + AskCameraPermission(Manifest.Permission.Camera); + return Task.FromResult(0); + } + + if(!_cameraPermissionsDenied && hasCameraPermission && hasStorageWritePermission) + { + try + { + var root = new Java.IO.File(global::Android.OS.Environment.ExternalStorageDirectory, "bitwarden"); + var file = new Java.IO.File(root, "temp_camera_photo.jpg"); + if(!file.Exists()) + { + file.ParentFile.Mkdirs(); + file.CreateNewFile(); + } + var outputFileUri = global::Android.Net.Uri.FromFile(file); + additionalIntents.AddRange(GetCameraIntents(outputFileUri)); + } + catch(Java.IO.IOException) { } + } + } var docIntent = new Intent(Intent.ActionOpenDocument); docIntent.AddCategory(Intent.CategoryOpenable); docIntent.SetType("*/*"); var chooserIntent = Intent.CreateChooser(docIntent, AppResources.FileSource); - - if(!_cameraPermissionsDenied && hasCameraPermission && hasStorageWritePermission) - { - try - { - var root = new Java.IO.File(global::Android.OS.Environment.ExternalStorageDirectory, "bitwarden"); - var file = new Java.IO.File(root, "temp_camera_photo.jpg"); - if(!file.Exists()) - { - file.ParentFile.Mkdirs(); - file.CreateNewFile(); - } - var outputFileUri = global::Android.Net.Uri.FromFile(file); - additionalIntents.AddRange(GetCameraIntents(outputFileUri)); - } - catch(Java.IO.IOException) { } - } - if(additionalIntents.Count > 0) { chooserIntent.PutExtra(Intent.ExtraInitialIntents, additionalIntents.ToArray()); diff --git a/src/Android/Services/DeviceInfoService.cs b/src/Android/Services/DeviceInfoService.cs index e6514a8b6..222df7b2c 100644 --- a/src/Android/Services/DeviceInfoService.cs +++ b/src/Android/Services/DeviceInfoService.cs @@ -1,4 +1,5 @@ using Android.App; +using Android.Content.PM; using Android.OS; using Bit.App.Abstractions; @@ -42,5 +43,6 @@ namespace Bit.Android.Services } } public bool NfcEnabled => Utilities.NfcEnabled(); + public bool HasCamera => Xamarin.Forms.Forms.Context.PackageManager.HasSystemFeature(PackageManager.FeatureCamera); } } diff --git a/src/App/Abstractions/Services/IDeviceInfoService.cs b/src/App/Abstractions/Services/IDeviceInfoService.cs index 4e87274b6..706a4cda1 100644 --- a/src/App/Abstractions/Services/IDeviceInfoService.cs +++ b/src/App/Abstractions/Services/IDeviceInfoService.cs @@ -6,5 +6,6 @@ int Version { get; } float Scale { get; } bool NfcEnabled { get; } + bool HasCamera { get; } } } diff --git a/src/App/Pages/Vault/VaultAddLoginPage.cs b/src/App/Pages/Vault/VaultAddLoginPage.cs index be92cf2a2..3b51c5ccc 100644 --- a/src/App/Pages/Vault/VaultAddLoginPage.cs +++ b/src/App/Pages/Vault/VaultAddLoginPage.cs @@ -25,6 +25,7 @@ namespace Bit.App.Pages private readonly IGoogleAnalyticsService _googleAnalyticsService; private readonly ISettings _settings; private readonly IAppInfoService _appInfoService; + private readonly IDeviceInfoService _deviceInfo; private readonly string _defaultUri; private readonly string _defaultName; private readonly bool _fromAutofill; @@ -43,6 +44,7 @@ namespace Bit.App.Pages _googleAnalyticsService = Resolver.Resolve(); _settings = Resolver.Resolve(); _appInfoService = Resolver.Resolve(); + _deviceInfo = Resolver.Resolve(); Init(); } @@ -61,8 +63,11 @@ namespace Bit.App.Pages NotesCell = new FormEditorCell(height: 180); TotpCell = new FormEntryCell(AppResources.AuthenticatorKey, nextElement: NotesCell.Editor, - useButton: true); - TotpCell.Button.Image = "camera"; + useButton: _deviceInfo.HasCamera); + if(_deviceInfo.HasCamera) + { + TotpCell.Button.Image = "camera"; + } TotpCell.Entry.DisableAutocapitalize = true; TotpCell.Entry.Autocorrect = false; TotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Courier", Android: "monospace", WinPhone: "Courier"); @@ -142,7 +147,12 @@ namespace Bit.App.Pages } else if(Device.RuntimePlatform == Device.Android) { - PasswordCell.Button.WidthRequest = TotpCell.Button.WidthRequest = 40; + PasswordCell.Button.WidthRequest = 40; + + if(TotpCell.Button != null) + { + TotpCell.Button.WidthRequest = 40; + } } var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () => @@ -234,7 +244,10 @@ namespace Bit.App.Pages TotpCell.InitEvents(); FolderCell.InitEvents(); PasswordCell.Button.Clicked += PasswordButton_Clicked; - TotpCell.Button.Clicked += TotpButton_Clicked; + if(TotpCell?.Button != null) + { + TotpCell.Button.Clicked += TotpButton_Clicked; + } GenerateCell.Tapped += GenerateCell_Tapped; if(!_fromAutofill && !_settings.GetValueOrDefault(AddedLoginAlertKey, false)) @@ -266,7 +279,10 @@ namespace Bit.App.Pages TotpCell.Dispose(); FolderCell.Dispose(); PasswordCell.Button.Clicked -= PasswordButton_Clicked; - TotpCell.Button.Clicked -= TotpButton_Clicked; + if(TotpCell?.Button != null) + { + TotpCell.Button.Clicked -= TotpButton_Clicked; + } GenerateCell.Tapped -= GenerateCell_Tapped; } diff --git a/src/App/Pages/Vault/VaultEditLoginPage.cs b/src/App/Pages/Vault/VaultEditLoginPage.cs index f70dc3891..aa7a0f30f 100644 --- a/src/App/Pages/Vault/VaultEditLoginPage.cs +++ b/src/App/Pages/Vault/VaultEditLoginPage.cs @@ -19,6 +19,7 @@ namespace Bit.App.Pages private readonly IFolderService _folderService; private readonly IUserDialogs _userDialogs; private readonly IConnectivity _connectivity; + private readonly IDeviceInfoService _deviceInfo; private readonly IGoogleAnalyticsService _googleAnalyticsService; private DateTime? _lastAction; @@ -29,6 +30,7 @@ namespace Bit.App.Pages _folderService = Resolver.Resolve(); _userDialogs = Resolver.Resolve(); _connectivity = Resolver.Resolve(); + _deviceInfo = Resolver.Resolve(); _googleAnalyticsService = Resolver.Resolve(); Init(); @@ -58,9 +60,12 @@ namespace Bit.App.Pages NotesCell.Editor.Text = login.Notes?.Decrypt(login.OrganizationId); TotpCell = new FormEntryCell(AppResources.AuthenticatorKey, nextElement: NotesCell.Editor, - useButton: true); + useButton: _deviceInfo.HasCamera); + if(_deviceInfo.HasCamera) + { + TotpCell.Button.Image = "camera"; + } TotpCell.Entry.Text = login.Totp?.Decrypt(login.OrganizationId); - TotpCell.Button.Image = "camera"; TotpCell.Entry.DisableAutocapitalize = true; TotpCell.Entry.Autocorrect = false; TotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Courier", Android: "monospace", WinPhone: "Courier"); @@ -161,7 +166,12 @@ namespace Bit.App.Pages } else if(Device.RuntimePlatform == Device.Android) { - PasswordCell.Button.WidthRequest = TotpCell.Button.WidthRequest = 40; + PasswordCell.Button.WidthRequest = 40; + + if(TotpCell.Button != null) + { + TotpCell.Button.WidthRequest = 40; + } } var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () => diff --git a/src/iOS.Core/Services/DeviceInfoService.cs b/src/iOS.Core/Services/DeviceInfoService.cs index 60b0cafa4..e6dc774bc 100644 --- a/src/iOS.Core/Services/DeviceInfoService.cs +++ b/src/iOS.Core/Services/DeviceInfoService.cs @@ -23,5 +23,6 @@ namespace Bit.iOS.Core.Services } public float Scale => (float)UIScreen.MainScreen.Scale; public bool NfcEnabled => false; + public bool HasCamera => true; } }