bitwarden-android/src/Android/MainActivity.cs

407 lines
16 KiB
C#
Raw Normal View History

using System;
2019-05-11 06:43:35 +03:00
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Android.App;
2019-05-11 06:43:35 +03:00
using Android.Content;
using Android.Content.PM;
2019-05-17 19:03:35 +03:00
using Android.Nfc;
using Android.OS;
using Android.Runtime;
using AndroidX.Core.Content;
using Bit.App.Abstractions;
using Bit.App.Models;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Utilities;
using Bit.Droid.Receivers;
using Bit.Droid.Utilities;
using ZXing.Net.Mobile.Android;
2019-03-28 03:12:44 +03:00
namespace Bit.Droid
{
// Activity and IntentFilter declarations have been moved to Properties/AndroidManifest.xml
// They have been hardcoded so we can use the default LaunchMode on Android 11+
// LaunchMode defined in values/manifest.xml for Android 10- and values-v30/manifest.xml for Android 11+
// See https://github.com/bitwarden/mobile/pull/1673 for details
2019-03-28 03:12:44 +03:00
[Register("com.x8bit.bitwarden.MainActivity")]
2019-03-28 06:44:54 +03:00
public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
2019-03-28 03:12:44 +03:00
{
2019-05-11 06:43:35 +03:00
private IDeviceActionService _deviceActionService;
private IMessagingService _messagingService;
2019-05-16 19:30:20 +03:00
private IBroadcasterService _broadcasterService;
Account Switching (#1807) * Account Switching (#1720) * Account switching * WIP * wip * wip * updates to send test logic * fixed Send tests * fixes for theme handling on account switching and re-adding existing account * switch fixes * fixes * fixes * cleanup * vault timeout fixes * account list status enhancements * logout fixes and token handling improvements * merge latest (#1727) * remove duplicate dependency * fix for initial login token storage paradox (#1730) * Fix avatar color update toolbar item issue on iOS for account switching (#1735) * Updated account switching menu UI (#1733) * updated account switching menu UI * additional changes * add key suffix to constant * GetFirstLetters method tweaks * Fix crash on account switching when logging out when having more than user at a time (#1740) * single account migration to multi-account on app update (#1741) * Account Switching Tap to dismiss (#1743) * Added tap to dismiss on the Account switching overlay and improved a bit the code * Fix account switching overlay background transparent on the proper place * Fixed transparent background and the shadow on the account switching overlay * Fix iOS top space on Account switching list overlay after modal (#1746) * Fix top space added to Account switching list overlay after closing modal * Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well * Usability: dismiss account list on certain events (#1748) * dismiss account list on certain events * use new FireAndForget method for back button logic * Create and use Account Switching overlay control (#1753) * Added Account switching overlay control and its own ViewModel and refactored accordingly * Fix account switching Accounts list binding update * Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755) * Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756) * Usability improvements for logout on vault timeout (#1781) * accountswitching fixes (#1784) * Fix for invalid PIN lock state when switching accounts (#1792) * fix for pin lock flow * named tuple values and updated async * clear send service cache on account switch (#1796) * Global theme and account removal (#1793) * Global theme and account removal * remove redundant call to hide account list overlay * cleanup and additional tweaks * add try/catch to remove account dialog flow Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2022-02-23 20:40:17 +03:00
private IStateService _stateService;
2019-05-29 06:14:02 +03:00
private IAppIdService _appIdService;
2019-07-13 00:29:40 +03:00
private IEventService _eventService;
private PendingIntent _eventUploadPendingIntent;
2019-05-17 19:03:35 +03:00
private AppOptions _appOptions;
private string _activityKey = $"{nameof(MainActivity)}_{Java.Lang.JavaSystem.CurrentTimeMillis().ToString()}";
2019-05-28 16:54:08 +03:00
private Java.Util.Regex.Pattern _otpPattern =
Java.Util.Regex.Pattern.Compile("^.*?([cbdefghijklnrtuv]{32,64})$");
2019-05-11 06:43:35 +03:00
2019-03-28 03:12:44 +03:00
protected override void OnCreate(Bundle savedInstanceState)
{
2019-07-13 00:29:40 +03:00
var eventUploadIntent = new Intent(this, typeof(EventUploadReceiver));
_eventUploadPendingIntent = PendingIntent.GetBroadcast(this, 0, eventUploadIntent,
PendingIntentFlags.UpdateCurrent);
2019-05-16 19:30:20 +03:00
2019-05-29 06:03:03 +03:00
var policy = new StrictMode.ThreadPolicy.Builder().PermitAll().Build();
StrictMode.SetThreadPolicy(policy);
2019-05-11 06:43:35 +03:00
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
2019-05-16 19:30:20 +03:00
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
Account Switching (#1807) * Account Switching (#1720) * Account switching * WIP * wip * wip * updates to send test logic * fixed Send tests * fixes for theme handling on account switching and re-adding existing account * switch fixes * fixes * fixes * cleanup * vault timeout fixes * account list status enhancements * logout fixes and token handling improvements * merge latest (#1727) * remove duplicate dependency * fix for initial login token storage paradox (#1730) * Fix avatar color update toolbar item issue on iOS for account switching (#1735) * Updated account switching menu UI (#1733) * updated account switching menu UI * additional changes * add key suffix to constant * GetFirstLetters method tweaks * Fix crash on account switching when logging out when having more than user at a time (#1740) * single account migration to multi-account on app update (#1741) * Account Switching Tap to dismiss (#1743) * Added tap to dismiss on the Account switching overlay and improved a bit the code * Fix account switching overlay background transparent on the proper place * Fixed transparent background and the shadow on the account switching overlay * Fix iOS top space on Account switching list overlay after modal (#1746) * Fix top space added to Account switching list overlay after closing modal * Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well * Usability: dismiss account list on certain events (#1748) * dismiss account list on certain events * use new FireAndForget method for back button logic * Create and use Account Switching overlay control (#1753) * Added Account switching overlay control and its own ViewModel and refactored accordingly * Fix account switching Accounts list binding update * Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755) * Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756) * Usability improvements for logout on vault timeout (#1781) * accountswitching fixes (#1784) * Fix for invalid PIN lock state when switching accounts (#1792) * fix for pin lock flow * named tuple values and updated async * clear send service cache on account switch (#1796) * Global theme and account removal (#1793) * Global theme and account removal * remove redundant call to hide account list overlay * cleanup and additional tweaks * add try/catch to remove account dialog flow Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2022-02-23 20:40:17 +03:00
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
2019-05-29 06:14:02 +03:00
_appIdService = ServiceContainer.Resolve<IAppIdService>("appIdService");
2019-07-13 00:29:40 +03:00
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
2019-05-11 06:43:35 +03:00
2019-03-28 03:12:44 +03:00
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
// this needs to be called here before base.OnCreate(...)
Intent?.Validate();
2019-03-28 03:12:44 +03:00
base.OnCreate(savedInstanceState);
if (!CoreHelpers.InDebugMode())
2019-05-29 06:04:01 +03:00
{
Window.AddFlags(Android.Views.WindowManagerFlags.Secure);
}
#if !DEBUG && !FDROID
Account Switching (#1807) * Account Switching (#1720) * Account switching * WIP * wip * wip * updates to send test logic * fixed Send tests * fixes for theme handling on account switching and re-adding existing account * switch fixes * fixes * fixes * cleanup * vault timeout fixes * account list status enhancements * logout fixes and token handling improvements * merge latest (#1727) * remove duplicate dependency * fix for initial login token storage paradox (#1730) * Fix avatar color update toolbar item issue on iOS for account switching (#1735) * Updated account switching menu UI (#1733) * updated account switching menu UI * additional changes * add key suffix to constant * GetFirstLetters method tweaks * Fix crash on account switching when logging out when having more than user at a time (#1740) * single account migration to multi-account on app update (#1741) * Account Switching Tap to dismiss (#1743) * Added tap to dismiss on the Account switching overlay and improved a bit the code * Fix account switching overlay background transparent on the proper place * Fixed transparent background and the shadow on the account switching overlay * Fix iOS top space on Account switching list overlay after modal (#1746) * Fix top space added to Account switching list overlay after closing modal * Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well * Usability: dismiss account list on certain events (#1748) * dismiss account list on certain events * use new FireAndForget method for back button logic * Create and use Account Switching overlay control (#1753) * Added Account switching overlay control and its own ViewModel and refactored accordingly * Fix account switching Accounts list binding update * Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755) * Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756) * Usability improvements for logout on vault timeout (#1781) * accountswitching fixes (#1784) * Fix for invalid PIN lock state when switching accounts (#1792) * fix for pin lock flow * named tuple values and updated async * clear send service cache on account switch (#1796) * Global theme and account removal (#1793) * Global theme and account removal * remove redundant call to hide account list overlay * cleanup and additional tweaks * add try/catch to remove account dialog flow Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2022-02-23 20:40:17 +03:00
var appCenterHelper = new AppCenterHelper(_appIdService, _stateService);
var appCenterTask = appCenterHelper.InitAsync();
2019-05-29 06:14:02 +03:00
#endif
var toplayout = Window?.DecorView?.RootView;
if (toplayout != null)
{
toplayout.FilterTouchesWhenObscured = true;
}
2019-03-28 06:44:54 +03:00
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
Xamarin.Forms.Forms.Init(this, savedInstanceState);
2019-05-17 19:03:35 +03:00
_appOptions = GetOptions();
LoadApplication(new App.App(_appOptions));
2019-05-16 19:30:20 +03:00
_broadcasterService.Subscribe(_activityKey, (message) =>
2019-05-16 19:30:20 +03:00
{
if (message.Command == "startEventTimer")
2019-07-13 00:29:40 +03:00
{
StartEventAlarm();
}
else if (message.Command == "stopEventTimer")
2019-07-13 00:29:40 +03:00
{
var task = StopEventAlarmAsync();
}
else if (message.Command == "finishMainActivity")
2019-05-17 21:46:31 +03:00
{
2019-05-31 03:40:50 +03:00
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => Finish());
2019-05-17 21:46:31 +03:00
}
else if (message.Command == "listenYubiKeyOTP")
2019-05-28 16:54:08 +03:00
{
ListenYubiKey((bool)message.Data);
}
else if (message.Command == "updatedTheme")
2019-05-29 22:50:20 +03:00
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => AppearanceAdjustments());
2019-05-29 22:50:20 +03:00
}
else if (message.Command == "exit")
2019-05-30 07:29:00 +03:00
{
ExitApp();
}
2019-05-16 19:30:20 +03:00
});
2019-03-28 03:12:44 +03:00
}
2019-03-28 06:44:54 +03:00
2019-05-28 16:54:08 +03:00
protected override void OnPause()
{
base.OnPause();
ListenYubiKey(false);
}
protected override void OnResume()
{
base.OnResume();
Xamarin.Essentials.Platform.OnResume();
AppearanceAdjustments();
ThemeManager.UpdateThemeOnPagesAsync();
if (_deviceActionService.SupportsNfc())
2019-05-28 16:54:08 +03:00
{
try
{
_messagingService.Send("resumeYubiKey");
}
catch { }
}
AndroidHelpers.SetPreconfiguredRestrictionSettingsAsync(this)
.GetAwaiter()
.GetResult();
2019-05-28 16:54:08 +03:00
}
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
try
{
if (intent?.GetStringExtra("uri") is string uri)
{
_messagingService.Send("popAllAndGoToAutofillCiphers");
if (_appOptions != null)
{
_appOptions.Uri = uri;
}
}
else if (intent.GetBooleanExtra("generatorTile", false))
2019-06-07 03:34:59 +03:00
{
_messagingService.Send("popAllAndGoToTabGenerator");
if (_appOptions != null)
{
_appOptions.GeneratorTile = true;
}
2019-06-07 03:34:59 +03:00
}
else if (intent.GetBooleanExtra("myVaultTile", false))
2019-06-07 03:34:59 +03:00
{
_messagingService.Send("popAllAndGoToTabMyVault");
if (_appOptions != null)
{
_appOptions.MyVaultTile = true;
}
2019-06-07 03:34:59 +03:00
}
else if (intent.Action == Intent.ActionSend && intent.Type != null)
{
if (_appOptions != null)
{
_appOptions.CreateSend = GetCreateSendRequest(intent);
}
_messagingService.Send("popAllAndGoToTabSend");
}
else
{
ParseYubiKey(intent.DataString);
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", e.GetType(), e.StackTrace);
}
2019-05-28 16:54:08 +03:00
}
2019-05-11 06:43:35 +03:00
public async override void OnRequestPermissionsResult(int requestCode, string[] permissions,
2019-03-28 06:44:54 +03:00
[GeneratedEnum] Permission[] grantResults)
{
if (requestCode == Constants.SelectFilePermissionRequestCode)
2019-05-11 06:43:35 +03:00
{
if (grantResults.Any(r => r != Permission.Granted))
2019-05-11 06:43:35 +03:00
{
_messagingService.Send("selectFileCameraPermissionDenied");
}
await _deviceActionService.SelectFileAsync();
}
else
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
2019-05-11 06:43:35 +03:00
}
2019-03-28 06:44:54 +03:00
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
2019-05-11 06:43:35 +03:00
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (resultCode == Result.Ok &&
(requestCode == Constants.SelectFileRequestCode || requestCode == Constants.SaveFileRequestCode))
2019-05-11 06:43:35 +03:00
{
Android.Net.Uri uri = null;
string fileName = null;
if (data != null && data.Data != null)
2019-05-11 06:43:35 +03:00
{
uri = data.Data;
fileName = AndroidHelpers.GetFileName(ApplicationContext, uri);
}
else
{
// camera
2019-06-25 18:54:31 +03:00
var file = new Java.IO.File(FilesDir, "temp_camera_photo.jpg");
uri = FileProvider.GetUriForFile(this, "com.x8bit.bitwarden.fileprovider", file);
2019-05-11 06:43:35 +03:00
fileName = $"photo_{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.jpg";
}
if (uri == null)
2019-05-11 06:43:35 +03:00
{
return;
}
if (requestCode == Constants.SaveFileRequestCode)
{
_messagingService.Send("selectSaveFileResult",
new Tuple<string, string>(uri.ToString(), fileName));
return;
}
2019-05-11 06:43:35 +03:00
try
{
using (var stream = ContentResolver.OpenInputStream(uri))
using (var memoryStream = new MemoryStream())
2019-05-11 06:43:35 +03:00
{
stream.CopyTo(memoryStream);
_messagingService.Send("selectFileResult",
new Tuple<byte[], string>(memoryStream.ToArray(), fileName ?? "unknown_file_name"));
}
}
catch (Java.IO.FileNotFoundException)
2019-05-11 06:43:35 +03:00
{
return;
}
}
}
2019-05-17 19:03:35 +03:00
protected override void OnDestroy()
{
base.OnDestroy();
_broadcasterService.Unsubscribe(_activityKey);
}
2019-05-17 19:03:35 +03:00
private void ListenYubiKey(bool listen)
{
if (!_deviceActionService.SupportsNfc())
2019-05-17 19:03:35 +03:00
{
return;
}
var adapter = NfcAdapter.GetDefaultAdapter(this);
if (listen)
2019-05-17 19:03:35 +03:00
{
var intent = new Intent(this, Class);
intent.AddFlags(ActivityFlags.SingleTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
// register for all NDEF tags starting with http och https
var ndef = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
ndef.AddDataScheme("http");
ndef.AddDataScheme("https");
var filters = new IntentFilter[] { ndef };
try
{
// register for foreground dispatch so we'll receive tags according to our intent filters
adapter.EnableForegroundDispatch(this, pendingIntent, filters, null);
}
catch { }
}
else
{
2019-06-06 15:59:54 +03:00
try
{
adapter.DisableForegroundDispatch(this);
}
catch { }
2019-05-17 19:03:35 +03:00
}
}
private AppOptions GetOptions()
{
var options = new AppOptions
{
Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra("autofillFrameworkUri"),
MyVaultTile = Intent.GetBooleanExtra("myVaultTile", false),
GeneratorTile = Intent.GetBooleanExtra("generatorTile", false),
FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false),
CreateSend = GetCreateSendRequest(Intent)
2019-05-17 19:03:35 +03:00
};
var fillType = Intent.GetIntExtra("autofillFrameworkFillType", 0);
if (fillType > 0)
2019-05-17 19:03:35 +03:00
{
options.FillType = (CipherType)fillType;
}
if (Intent.GetBooleanExtra("autofillFrameworkSave", false))
2019-05-17 19:03:35 +03:00
{
options.SaveType = (CipherType)Intent.GetIntExtra("autofillFrameworkType", 0);
options.SaveName = Intent.GetStringExtra("autofillFrameworkName");
options.SaveUsername = Intent.GetStringExtra("autofillFrameworkUsername");
options.SavePassword = Intent.GetStringExtra("autofillFrameworkPassword");
options.SaveCardName = Intent.GetStringExtra("autofillFrameworkCardName");
options.SaveCardNumber = Intent.GetStringExtra("autofillFrameworkCardNumber");
options.SaveCardExpMonth = Intent.GetStringExtra("autofillFrameworkCardExpMonth");
options.SaveCardExpYear = Intent.GetStringExtra("autofillFrameworkCardExpYear");
options.SaveCardCode = Intent.GetStringExtra("autofillFrameworkCardCode");
}
return options;
}
2019-05-28 16:54:08 +03:00
private Tuple<SendType, string, byte[], string> GetCreateSendRequest(Intent intent)
{
if (intent.Action == Intent.ActionSend && intent.Type != null)
{
if ((intent.Flags & ActivityFlags.LaunchedFromHistory) == ActivityFlags.LaunchedFromHistory)
{
// don't re-deliver intent if resuming from app switcher
return null;
}
var type = intent.Type;
if (type.Contains("text/"))
{
var subject = intent.GetStringExtra(Intent.ExtraSubject);
var text = intent.GetStringExtra(Intent.ExtraText);
return new Tuple<SendType, string, byte[], string>(SendType.Text, subject, null, text);
}
else
{
var data = intent.ClipData?.GetItemAt(0);
var uri = data?.Uri;
var filename = AndroidHelpers.GetFileName(ApplicationContext, uri);
try
{
using (var stream = ContentResolver.OpenInputStream(uri))
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return new Tuple<SendType, string, byte[], string>(SendType.File, filename, memoryStream.ToArray(), null);
}
}
catch (Java.IO.FileNotFoundException) { }
}
}
return null;
}
2019-05-28 16:54:08 +03:00
private void ParseYubiKey(string data)
{
if (data == null)
2019-05-28 16:54:08 +03:00
{
return;
}
var otpMatch = _otpPattern.Matcher(data);
if (otpMatch.Matches())
2019-05-28 16:54:08 +03:00
{
var otp = otpMatch.Group(1);
_messagingService.Send("gotYubiKeyOTP", otp);
}
}
2019-05-29 22:50:20 +03:00
private void AppearanceAdjustments()
2019-05-30 06:02:30 +03:00
{
Window?.SetStatusBarColor(ThemeHelpers.NavBarBackgroundColor);
Window?.DecorView.SetBackgroundColor(ThemeHelpers.BackgroundColor);
Account Switching (#1807) * Account Switching (#1720) * Account switching * WIP * wip * wip * updates to send test logic * fixed Send tests * fixes for theme handling on account switching and re-adding existing account * switch fixes * fixes * fixes * cleanup * vault timeout fixes * account list status enhancements * logout fixes and token handling improvements * merge latest (#1727) * remove duplicate dependency * fix for initial login token storage paradox (#1730) * Fix avatar color update toolbar item issue on iOS for account switching (#1735) * Updated account switching menu UI (#1733) * updated account switching menu UI * additional changes * add key suffix to constant * GetFirstLetters method tweaks * Fix crash on account switching when logging out when having more than user at a time (#1740) * single account migration to multi-account on app update (#1741) * Account Switching Tap to dismiss (#1743) * Added tap to dismiss on the Account switching overlay and improved a bit the code * Fix account switching overlay background transparent on the proper place * Fixed transparent background and the shadow on the account switching overlay * Fix iOS top space on Account switching list overlay after modal (#1746) * Fix top space added to Account switching list overlay after closing modal * Fix top space added to Account switching list overlay after closing modal on lock, login and home views just in case we add modals in the future there as well * Usability: dismiss account list on certain events (#1748) * dismiss account list on certain events * use new FireAndForget method for back button logic * Create and use Account Switching overlay control (#1753) * Added Account switching overlay control and its own ViewModel and refactored accordingly * Fix account switching Accounts list binding update * Implemented dismiss account switching overlay when changing tabs and when selecting the same tab. Also updated the deprecated listener on CustomTabbedRenderer on Android (#1755) * Overriden Equals on AvatarImageSource so it doesn't get set multiple times when it's the same image thus producing blinking on tab chaged (#1756) * Usability improvements for logout on vault timeout (#1781) * accountswitching fixes (#1784) * Fix for invalid PIN lock state when switching accounts (#1792) * fix for pin lock flow * named tuple values and updated async * clear send service cache on account switch (#1796) * Global theme and account removal (#1793) * Global theme and account removal * remove redundant call to hide account list overlay * cleanup and additional tweaks * add try/catch to remove account dialog flow Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2022-02-23 20:40:17 +03:00
ThemeHelpers.SetAppearance(ThemeManager.GetTheme(), ThemeManager.OsDarkModeEnabled());
2019-05-30 06:02:30 +03:00
}
2019-05-30 07:29:00 +03:00
private void ExitApp()
{
FinishAffinity();
Java.Lang.JavaSystem.Exit(0);
}
2019-05-30 18:22:35 +03:00
2019-07-13 00:29:40 +03:00
private void StartEventAlarm()
{
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtime, 120000, 300000, _eventUploadPendingIntent);
}
private async Task StopEventAlarmAsync()
{
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.Cancel(_eventUploadPendingIntent);
await _eventService.UploadEventsAsync();
}
2019-03-28 03:12:44 +03:00
}
2019-03-28 06:44:54 +03:00
}