public async Task ExecuteAsync() { var latestAssetUrl = await UpdateHelper.GetLatestApkAssetUrlAsync(); var decision = await RequestUpdateDecisionAsync(latestAssetUrl); if (!decision) { if (_featureContext.UserInitiated) { ToastHelper.Display("Update aborted", ToastLength.Long); } return; } var downloadFilePath = Path.Combine(FileSystem.CacheDirectory, "latest.apk"); var downloadSuccess = await UpdateHelper.DownloadApkAsync(latestAssetUrl, downloadFilePath, _featureContext.DownloadProgressHandler); if (downloadSuccess) { var providerPath = FileProvider.GetUriForFile(_context, "amusoft.pcr.mobile.droid.provider", new Java.IO.File(downloadFilePath)); var upgradeIntent = new Intent(Intent.ActionView); upgradeIntent.SetDataAndType(providerPath, "application/vnd.android.package-archive"); upgradeIntent.AddFlags(ActivityFlags.GrantReadUriPermission); _context.StartActivity(upgradeIntent); } }
private async void InstanceOnItemClicked(object sender, HostSelectionDataSource.ServerDataItem e) { var endpointAddress = new HostEndpointAddress(e.EndPoint.Address.ToString(), e.HttpsPorts[0]); try { var portOpen = await SocketHelper.IsPortOpenAsync(endpointAddress.IpAddress, endpointAddress.Port, TimeSpan.FromSeconds(1)); if (!portOpen) { ToastHelper.Display($"Failed to connect to {endpointAddress.FullAddress}", ToastLength.Long); return; } using (var agent = GrpcApplicationAgentFactory.Create(GrpcChannelHub.GetChannelFor(endpointAddress))) { var authenticated = await CheckIsAuthenticatedAsync(agent); if (!authenticated) { if (!await TryUpdateAuthenticationAsync(agent, endpointAddress)) { return; } } NavigateToHost(e); } } catch (Exception exception) { ToastHelper.Display($"Failed to connect to {endpointAddress.FullAddress}", ToastLength.Long); Log.Error(exception); } }
private async void DataSourceOnUpdateRequired(object sender, AudioFeedResponseItem e) { try { var result = await _agent.FullDesktopClient.UpdateAudioFeedAsync(new UpdateAudioFeedRequest() { Item = e }); ToastHelper.DisplaySuccess(result.Success, ToastLength.Short); if (result.Success) { var feeds = await _agent.FullDesktopClient.GetAudioFeedsAsync(new AudioFeedRequest()); if (_recyclerView.GetAdapter() is AudioApplicationDataSource audioDataSource) { var match = feeds.Items.FirstOrDefault(d => d.Id == e.Id); if (match != null) { audioDataSource.UpdateSingle(match); } } } } catch (Exception exception) { Log.Error(exception); ToastHelper.Display("Update failed", ToastLength.Short); } }
private Task TellClipboard() { if (TryGetClipboardContent(out var content)) { ToastHelper.Display(content, ToastLength.Long); } return(Task.CompletedTask); }
private async Task <bool> IsAuthorizedAsync() { var result = await _agent.DesktopClient.AuthenticateAsync(); if (!result) { ToastHelper.Display("Authentication required.", ToastLength.Long); } return(result); }
private async Task ButtonAction(MacPackage package) { Log.Info("Waking up host {Name} with {Count} last known addresses", package.HostName, package.Addresses.Length); foreach (var address in package.Addresses) { Log.Debug("Waking up physical address {Id}", address); await Amusoft.Toolkit.Networking.WakeOnLan.UsingAddressAsync(address); } ToastHelper.Display($"Wake On LAN for {package.HostName} sent", ToastLength.Long); }
private void HolderItemOnItemClicked(object sender, EventArgs e) { if (sender is SelectServerFragmentDataSourceItem holder) { if (holder.AbsoluteAdapterPosition < 0) { ToastHelper.Display("Error - Restart application", ToastLength.Short); Log.Debug("holder.AbsoluteAdapterPosition < 0"); return; } ItemClicked?.Invoke(null, _dataItems[holder.AbsoluteAdapterPosition]); } }
private void DeleteLogsClicked() { try { var root = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var path = Path.Combine(root, "logs", "nlog.csv"); if (File.Exists(path)) { File.Delete(path); } ToastHelper.Display("Logs deleted", ToastLength.Short); } catch (Exception e) { ToastHelper.Display("Failed to clear logs", ToastLength.Short); Log.Error(e); } }
private async Task SetHostClipboard() { if (!TryGetClipboardContent(out var content)) { ToastHelper.Display($"Clipboard cannot be sent", ToastLength.Long); return; } try { var result = await this.GetAgent().DesktopClient.SetClipboardAsync(TimeSpan.FromMinutes(1), GetRemoteName(), content); ToastHelper.Display(result ? "Host clipboard updated" : "error", ToastLength.Short); } catch (RpcException e) when(e.StatusCode == StatusCode.PermissionDenied) { ToastHelper.Display(e.Message, ToastLength.Long); } }
private void SeekBarOnProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e) { const int step = 5; var progress = e.Progress; progress = progress / step; progress = progress * step; _textView.Text = $"Master volume: {progress}"; _seekBar.SetProgress(progress, true); Log.Info("Setting master volume to {Value} FromUser: {FromUser}", progress, e.FromUser); if (e.FromUser) { Debouncer.Debounce(nameof(AudioFragment) + nameof(SeekBarOnProgressChanged), async() => { await _agent.DesktopClient.SetMasterVolumeAsync(TimeSpan.FromSeconds(5), progress); ToastHelper.Display("Volume updated", ToastLength.Short); }, TimeSpan.FromSeconds(2)); } }
private async void ToggleMuteClicked(object sender, EventArgs e) { var result = await _agent.DesktopClient.ToggleMuteAsync(TimeSpan.FromSeconds(5)); switch (result) { case null: ToastHelper.Display("Error", ToastLength.Short); break; case true: ToastHelper.Display("Muted", ToastLength.Short); _imageViewMasterToggle.SetImageResource(Resource.Drawable.outline_volume_off_24); break; case false: ToastHelper.Display("Unmuted", ToastLength.Short); _imageViewMasterToggle.SetImageResource(Resource.Drawable.outline_volume_up_24); break; } }
private async Task GetHostClipboard() { var cm = Context.GetSystemService(Context.ClipboardService) as ClipboardManager; if (cm == null) { return; } try { var content = await this.GetAgent().DesktopClient.GetClipboardAsync(TimeSpan.FromMinutes(1), GetRemoteName()); cm.PrimaryClip = ClipData.NewPlainText("Host clipboard", content); ToastHelper.Display("Clipboard updated", ToastLength.Short); } catch (RpcException e) when(e.StatusCode == StatusCode.PermissionDenied) { ToastHelper.Display(e.Message, ToastLength.Long); } }
private static async Task <bool> CheckIsAuthenticatedAsync(GrpcApplicationAgent agent) { var authenticated = true; CheckIsAuthenticatedResponse response = null; try { response = await agent.FullDesktopClient.CheckIsAuthenticatedAsync(new CheckIsAuthenticatedRequest()).ResponseAsync; } catch (RpcException exception) when(exception.Status.StatusCode == StatusCode.Unauthenticated) { authenticated = false; } catch (RpcException exception) { Log.Error(exception); ToastHelper.Display("Failed to check authentication state", ToastLength.Long); authenticated = false; } return(authenticated && response.Result); }
private async Task <bool> TryUpdateAuthenticationAsync(GrpcApplicationAgent agent, HostEndpointAddress endpointAddress) { var input = await LoginDialog.GetInputAsync("Authentication required"); if (input == null) { ToastHelper.Display("Authentication required", ToastLength.Long); return(false); } var loginResponse = await GetLoginResponseAsync(agent, input); if (loginResponse.InvalidCredentials) { ToastHelper.Display("Invalid credentials", ToastLength.Long); return(false); } var authenticationStorage = new AuthenticationStorage(endpointAddress); await authenticationStorage.UpdateAsync(loginResponse.AccessToken, loginResponse.RefreshToken).ConfigureAwait(false); return(true); }
private async Task<TResult> SecuredCallAsync<TResult>(Func<DesktopIntegrationService.DesktopIntegrationServiceClient, Task<TResult>> functionCall, TResult defaultValue, [CallerMemberName] string methodName = default) { try { GrpcRequestObserver.NotifyCallRunning(); return await functionCall(_client); } catch (RpcException e) when (e.StatusCode == StatusCode.PermissionDenied) { ToastHelper.Display("Permission denied", ToastLength.Long); return defaultValue; } catch (Exception e) { Log.Error(e, methodName + " failed."); GrpcRequestObserver.NotifyCallFailed(e); return defaultValue; } finally { GrpcRequestObserver.NotifyCallFinished(); } }
private void ClearStorageClicked() { SecureStorage.RemoveAll(); ToastHelper.Display("Secure storage cleared", ToastLength.Short); }
protected override async Task <Data> DoWorkAsync(CancellationToken cancellationToken) { var notificationId = (GetStateKind() + "+" + _agentAddress).GetHashCode(); Log.Debug("Spawned notification with Id {Id}", notificationId); try { var scheduled = await SystemStateManager.GetScheduledTimeAsync(_agentAddress, GetStateKind()); if (scheduled == null || DateTime.Now > scheduled.Value) { Log.Info("A system state event passed while the device was not working."); return(Data.Empty); } var progressDataBuilder = new Data.Builder(); UpdateProgress(progressDataBuilder, 0, false); if (!HostEndpointAddress.TryParse(_agentAddress, out var address)) { Log.Warn("Address {Address} could not be parsed - aborting process", _agentAddress); return(Data.Empty); } using (var agent = GrpcApplicationAgentFactory.Create(GrpcChannelHub.GetChannelFor(address))) { var hostName = await agent.DesktopClient.GetHostNameAsync(TimeSpan.FromSeconds(5)); var notification = NotificationHelper.DisplayNotification(notificationId, builder => { builder.SetCategory(NotificationCompat.CategoryProgress); builder.SetContentTitle(GetNotificationTitle(hostName)); builder.SetOnlyAlertOnce(true); builder.SetSmallIcon(GetNotificationIcon()); var intent = new Intent(); intent.SetAction(GetAbortAction()); intent.PutExtra(AbortBroadcastReceiver.NotificationIdTag, notificationId); intent.PutExtra(AbortBroadcastReceiver.WorkIdTag, Id.ToString()); intent.PutExtra(AbortBroadcastReceiver.HostAddressTag, _agentAddress); var pendingIntent = PendingIntent.GetBroadcast(Application.Context, notificationId, intent, PendingIntentFlags.OneShot); builder.AddAction(Android.Resource.Drawable.ButtonPlus, "Abort", pendingIntent); }, GetNotificationChannel()); SetForegroundAsync(new ForegroundInfo(notificationId, notification.Build())); var startDifference = scheduled.Value - DateTime.Now; while (scheduled > DateTime.Now) { var currentDifference = scheduled.Value - DateTime.Now; var progress = (100f / startDifference.TotalSeconds) * currentDifference.TotalSeconds; notification.SetProgress(100, (int)progress, false); UpdateProgress(progressDataBuilder, progress, true); notification.SetContentText(currentDifference.ToString("hh\\:mm\\:ss")); NotificationHelper.UpdateNotification(ApplicationContext, notificationId, notification); await Task.Delay(1000, cancellationToken); } UpdateProgress(progressDataBuilder, 0, false); NotificationHelper.DestroyNotification(notificationId); SystemStateManager.Clear(_agentAddress, GetStateKind()); var result = await ExecuteFinalizerAsync(agent); Xamarin.Essentials.MainThread.BeginInvokeOnMainThread(() => { if (result) { ToastHelper.Display(GetSuccessToastMessage(hostName), ToastLength.Long); } else { ToastHelper.Display("Error", ToastLength.Short); } }); } } catch (RpcException e) { Log.Debug(e, "Cancelling work because of an RPC exception"); WorkManager.GetInstance(ApplicationContext).CancelWorkById(Id); } return(Data.Empty); }