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)