From 243224a720069e939533b8894187d39ac6a315a1 Mon Sep 17 00:00:00 2001 From: shept Date: Mon, 15 Sep 2025 00:38:30 +0500 Subject: [PATCH] now with animations lol --- .../MetaforceInstaller.Cli.csproj | 4 + MetaforceInstaller.Cli/Program.cs | 79 +++++++----- .../Intefaces/IAdbService.cs | 14 ++- .../MetaforceInstaller.Core.csproj | 6 + .../Models/ProgressInfo.cs | 19 +++ .../Services/AdbService.cs | 113 ++++++++++++++++-- 6 files changed, 192 insertions(+), 43 deletions(-) create mode 100644 MetaforceInstaller.Core/Models/ProgressInfo.cs diff --git a/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj b/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj index 0f2fdaa..dee32c2 100644 --- a/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj +++ b/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj @@ -7,6 +7,10 @@ enable + + + + diff --git a/MetaforceInstaller.Cli/Program.cs b/MetaforceInstaller.Cli/Program.cs index ec19c2a..88b7a88 100644 --- a/MetaforceInstaller.Cli/Program.cs +++ b/MetaforceInstaller.Cli/Program.cs @@ -5,7 +5,7 @@ namespace MetaforceInstaller.Cli; static class Program { - static void Main(string[] args) + static async Task Main(string[] args) { try { @@ -22,32 +22,29 @@ static class Program var adbService = new AdbService(); - adbService.InstallApk(installationRequest.ApkPath); - adbService.CopyFile(installationRequest.ZipPath, installationRequest.OutputPath); + // Подписка на события прогресса + adbService.ProgressChanged += OnProgressChanged; + adbService.StatusChanged += OnStatusChanged; - // var adbPath = ExtractAdbFiles(); - // - // var server = new AdbServer(); - // var result = server.StartServer(adbPath, restartServerIfNewer: false); - // Console.WriteLine($"ADB сервер запущен: {result}"); - // - // adbClient = new AdbClient(); - // - // var devices = adbClient.GetDevices(); - // - // if (!devices.Any()) - // { - // Console.WriteLine("Устройства не найдены. Подключите Android-устройство и включите отладку по USB."); - // return; - // } - // - // deviceData = devices.FirstOrDefault(); - // Console.WriteLine($"Найдено устройство: {deviceData.Serial}"); - // Console.WriteLine($"Состояние: {deviceData.State}"); - // Console.WriteLine($"Имя устройства: {deviceData.Name} - {deviceData.Model}"); - // - // InstallApk(installationRequest.ApkPath); - // CopyFileToDevice(installationRequest.ZipPath, installationRequest.OutputPath); + // Получение информации об устройстве + var deviceInfo = adbService.GetDeviceInfo(); + Console.WriteLine($"Найдено устройство: {deviceInfo.SerialNumber}"); + Console.WriteLine($"Состояние: {deviceInfo.State}"); + Console.WriteLine($"Модель: {deviceInfo.Model} - {deviceInfo.Name}"); + Console.WriteLine(); + + // Создание объекта для отслеживания прогресса + var progress = new Progress(OnProgressReport); + + // Установка APK + await adbService.InstallApkAsync(installationRequest.ApkPath, progress); + Console.WriteLine(); + + // Копирование файла + await adbService.CopyFileAsync(installationRequest.ZipPath, installationRequest.OutputPath, progress); + Console.WriteLine(); + + Console.WriteLine("Операция завершена успешно!"); } catch (Exception ex) { @@ -55,6 +52,29 @@ static class Program } } + private static void OnProgressChanged(object? sender, MetaforceInstaller.Core.Models.ProgressInfo e) + { + DrawProgressBar(e.PercentageComplete, e.BytesTransferred, e.TotalBytes); + } + + private static void OnStatusChanged(object? sender, string e) + { + Console.WriteLine(e); + } + + private static void OnProgressReport(MetaforceInstaller.Core.Models.ProgressInfo progressInfo) + { + if (progressInfo.TotalBytes > 0) + { + DrawProgressBar(progressInfo.PercentageComplete, progressInfo.BytesTransferred, progressInfo.TotalBytes); + } + else + { + // Для случаев без информации о байтах (например, установка APK) + DrawProgressBar(progressInfo.PercentageComplete, 0, 100); + } + } + static void ShowUsage() { Console.WriteLine("Использование:"); @@ -82,7 +102,12 @@ static class Program var filledLength = (int)(barLength * progress / 100.0); var bar = "[" + new string('█', filledLength) + new string('░', barLength - filledLength) + "]"; - var bytesText = $" {FormatBytes(receivedBytes)} / {FormatBytes(totalBytes)}"; + + string bytesText = ""; + if (totalBytes > 0) + { + bytesText = $" {FormatBytes(receivedBytes)} / {FormatBytes(totalBytes)}"; + } Console.Write($"\r{bar} {progress}%{bytesText}"); } diff --git a/MetaforceInstaller.Core/Intefaces/IAdbService.cs b/MetaforceInstaller.Core/Intefaces/IAdbService.cs index c520ed6..444c237 100644 --- a/MetaforceInstaller.Core/Intefaces/IAdbService.cs +++ b/MetaforceInstaller.Core/Intefaces/IAdbService.cs @@ -1,10 +1,18 @@ using MetaforceInstaller.Core.Models; +using MetaforceInstaller.Core.Models; namespace MetaforceInstaller.Core.Intefaces; public interface IAdbService { - public void InstallApk(string apkPath); - public void CopyFile(string localPath, string remotePath); - public DeviceInfo GetDeviceInfo(); + event EventHandler? ProgressChanged; + event EventHandler? StatusChanged; + + Task InstallApkAsync(string apkPath, IProgress? progress = null, CancellationToken cancellationToken = default); + Task CopyFileAsync(string localPath, string remotePath, IProgress? progress = null, CancellationToken cancellationToken = default); + DeviceInfo GetDeviceInfo(); + + // Синхронные версии для обратной совместимости + void InstallApk(string apkPath); + void CopyFile(string localPath, string remotePath); } \ No newline at end of file diff --git a/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj b/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj index 9b6a6fd..7542437 100644 --- a/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj +++ b/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj @@ -12,8 +12,14 @@ + + + + + + diff --git a/MetaforceInstaller.Core/Models/ProgressInfo.cs b/MetaforceInstaller.Core/Models/ProgressInfo.cs new file mode 100644 index 0000000..cc09a74 --- /dev/null +++ b/MetaforceInstaller.Core/Models/ProgressInfo.cs @@ -0,0 +1,19 @@ +namespace MetaforceInstaller.Core.Models; + +public class ProgressInfo +{ + public int PercentageComplete { get; set; } + public long BytesTransferred { get; set; } + public long TotalBytes { get; set; } + public string? Message { get; set; } + public string? CurrentFile { get; set; } + public ProgressType Type { get; set; } +} + +public enum ProgressType +{ + Installation, + FileCopy, + Extraction, + General +} diff --git a/MetaforceInstaller.Core/Services/AdbService.cs b/MetaforceInstaller.Core/Services/AdbService.cs index b646012..8a55bd0 100644 --- a/MetaforceInstaller.Core/Services/AdbService.cs +++ b/MetaforceInstaller.Core/Services/AdbService.cs @@ -1,33 +1,42 @@ using System.Reflection; using AdvancedSharpAdbClient; using AdvancedSharpAdbClient.DeviceCommands; -using AdvancedSharpAdbClient.Logs; using AdvancedSharpAdbClient.Models; using MetaforceInstaller.Core.Intefaces; using MetaforceInstaller.Core.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace MetaforceInstaller.Core.Services; public class AdbService : IAdbService { - private ILogger _logger; + private readonly ILogger _logger; private readonly AdbClient _adbClient; private DeviceData _deviceData; - public AdbService() + public event EventHandler? ProgressChanged; + public event EventHandler? StatusChanged; + + public AdbService(ILogger? logger = null) { + _logger = logger ?? new NullLogger(); var adbPath = GetAdbPath(); var server = new AdbServer(); var serverStatus = server.StartServer(adbPath, restartServerIfNewer: false); _adbClient = new AdbClient(); var devices = _adbClient.GetDevices(); + foreach (var device in devices) + { + Console.WriteLine(device.Model); + } _deviceData = devices.FirstOrDefault(); } private void ExtractResource(string resourceName, string outputPath) { _logger.LogInformation($"Extracting resource: {resourceName} to {outputPath}"); - using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); + using var stream = Assembly.GetAssembly(typeof(AdbService)).GetManifestResourceStream(resourceName); using var fileStream = File.Create(outputPath); stream.CopyTo(fileStream); _logger.LogInformation($"Resource extracted: {resourceName} to {outputPath}"); @@ -41,14 +50,30 @@ public class AdbService : IAdbService var adbPath = Path.Combine(tempDir, "adb.exe"); if (File.Exists(adbPath)) return adbPath; - ExtractResource("MetaforceInstaller.Cli.adb.adb.exe", adbPath); - ExtractResource("MetaforceInstaller.Cli.adb.AdbWinApi.dll", Path.Combine(tempDir, "AdbWinApi.dll")); - ExtractResource("MetaforceInstaller.Cli.adb.AdbWinUsbApi.dll", Path.Combine(tempDir, "AdbWinUsbApi.dll")); + ExtractResource("MetaforceInstaller.Core.adb.adb.exe", adbPath); + ExtractResource("MetaforceInstaller.Core.adb.AdbWinApi.dll", Path.Combine(tempDir, "AdbWinApi.dll")); + ExtractResource("MetaforceInstaller.Core.adb.AdbWinUsbApi.dll", Path.Combine(tempDir, "AdbWinUsbApi.dll")); return adbPath; } + private void OnProgressChanged(ProgressInfo progressInfo) + { + ProgressChanged?.Invoke(this, progressInfo); + } + + private void OnStatusChanged(string status) + { + StatusChanged?.Invoke(this, status); + } + public void InstallApk(string apkPath) + { + InstallApkAsync(apkPath).Wait(); + } + + public async Task InstallApkAsync(string apkPath, IProgress? progress = null, + CancellationToken cancellationToken = default) { try { @@ -58,11 +83,37 @@ public class AdbService : IAdbService return; } + OnStatusChanged("Начинаем установку APK..."); _logger.LogInformation($"Installing APK: {apkPath}"); - var packageManager = new PackageManager(_adbClient, _deviceData); - packageManager.InstallPackage(apkPath, o => { }); + progress?.Report(new ProgressInfo + { + PercentageComplete = 0, + Message = "Подготовка к установке APK...", + Type = ProgressType.Installation, + CurrentFile = Path.GetFileName(apkPath) + }); + var packageManager = new PackageManager(_adbClient, _deviceData); + + await Task.Run(() => + { + packageManager.InstallPackage(apkPath, installProgress => + { + var progressInfo = new ProgressInfo + { + PercentageComplete = (int)installProgress.UploadProgress, + Message = $"Установка APK: {installProgress.UploadProgress:F1}%", + Type = ProgressType.Installation, + CurrentFile = Path.GetFileName(apkPath) + }; + + progress?.Report(progressInfo); + OnProgressChanged(progressInfo); + }); + }, cancellationToken); + + OnStatusChanged("APK успешно установлен!"); _logger.LogInformation("APK successfully installed!"); } catch (Exception ex) @@ -73,6 +124,12 @@ public class AdbService : IAdbService } public void CopyFile(string localPath, string remotePath) + { + CopyFileAsync(localPath, remotePath).Wait(); + } + + public async Task CopyFileAsync(string localPath, string remotePath, IProgress? progress = null, + CancellationToken cancellationToken = default) { try { @@ -82,14 +139,44 @@ public class AdbService : IAdbService return; } + OnStatusChanged("Начинаем копирование файла..."); _logger.LogInformation($"Copying file: {localPath} to {remotePath}"); - using var fileStream = File.OpenRead(localPath); - var syncService = new SyncService(_adbClient, _deviceData); + var fileInfo = new FileInfo(localPath); - syncService.Push(fileStream, remotePath, UnixFileStatus.DefaultFileMode, DateTime.Now, - new Action(progress => { })); + progress?.Report(new ProgressInfo + { + PercentageComplete = 0, + Message = "Подготовка к копированию файла...", + Type = ProgressType.FileCopy, + CurrentFile = Path.GetFileName(localPath), + TotalBytes = fileInfo.Length + }); + await Task.Run(() => + { + using var fileStream = File.OpenRead(localPath); + var syncService = new SyncService(_adbClient, _deviceData); + + syncService.Push(fileStream, remotePath, UnixFileStatus.DefaultFileMode, DateTime.Now, + copyProgress => + { + var progressInfo = new ProgressInfo + { + PercentageComplete = (int)copyProgress.ProgressPercentage, + BytesTransferred = copyProgress.ReceivedBytesSize, + TotalBytes = copyProgress.TotalBytesToReceive, + Message = $"Копирование: {copyProgress.ProgressPercentage:F1}%", + Type = ProgressType.FileCopy, + CurrentFile = Path.GetFileName(localPath) + }; + + progress?.Report(progressInfo); + OnProgressChanged(progressInfo); + }); + }, cancellationToken); + + OnStatusChanged("Файл успешно скопирован!"); _logger.LogInformation("File successfully copied!"); } catch (Exception ex)