Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge android fixes #63

Merged
merged 5 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions OpenIPC_Config.Android/Helpers/AndroidFileHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.IO;
using Android.Content;
using Android.Content.Res;
using Android.Util;

namespace OpenIPC_Config.Android.Helpers;

public class AndroidFileHelper
{
public static string ReadAssetFile(string relativePath)
{
// var assets = Android.App.Application.Context.Assets;
var assets = global::Android.App.Application.Context.Assets;

using (var stream = assets.Open(relativePath))
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}

public static string[] ListAssetFiles(string folderPath)
{
var assets = global::Android.App.Application.Context.Assets;
return assets.List(folderPath); // Lists all files in the folder
}

public static void CopyAssetsToInternalStorage(Context context)
{
AssetManager assets = context.Assets;
string internalStoragePath = context.FilesDir.AbsolutePath; // Internal storage path

// Start recursive copy from the root "binaries" folder
CopyFolder(assets, "binaries", internalStoragePath);
}

private static void CopyFolder(AssetManager assets, string sourceFolder, string destinationFolder)
{
try
{
// Ensure the destination folder exists
Directory.CreateDirectory(destinationFolder);

// List all items (files and folders) in the source folder
string[] items = assets.List(sourceFolder);

foreach (string item in items)
{
string sourcePath = string.IsNullOrEmpty(sourceFolder) ? item : $"{sourceFolder}/{item}";
string destinationPath = Path.Combine(destinationFolder, item);

// Check if the item is a directory or file
if (assets.List(sourcePath).Length > 0)
{
// If it's a folder, recursively copy its contents
CopyFolder(assets, sourcePath, destinationPath);
}
else
{
// If it's a file, copy it
using (Stream input = assets.Open(sourcePath))
using (FileStream output = new FileStream(destinationPath, FileMode.Create))
{
input.CopyTo(output);
}

Log.Debug("FileHelper", $"Copied file: {sourcePath} to {destinationPath}");
}
}
}
catch (Exception ex)
{
Log.Error("FileHelper", $"Error copying assets: {ex.Message}");
}
}
}
23 changes: 22 additions & 1 deletion OpenIPC_Config.Android/MainActivity.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using Android.App;
using System;
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Views;
using Avalonia;
using Avalonia.Android;
using Java.Lang;
using OpenIPC_Config.Android.Helpers;

namespace OpenIPC_Config.Android;

Expand All @@ -13,8 +18,24 @@ namespace OpenIPC_Config.Android;
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App>
{

// Adjust the layout when the keyboard is shown
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);

// Hide the soft keyboard initially
Window.SetSoftInputMode(SoftInput.StateHidden);

// Optionally, adjust the layout when the keyboard is shown
Window.SetSoftInputMode(SoftInput.AdjustResize);
}

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{

AndroidFileHelper.CopyAssetsToInternalStorage(global::Android.App.Application.Context);

return base.CustomizeAppBuilder(builder)
.WithInterFont();
}
Expand Down
11 changes: 11 additions & 0 deletions OpenIPC_Config.Android/OpenIPC_Config.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,23 @@
<RootNamespace>OpenIPC_Config.Android</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
<DefineConstants>$(DefineConstants);ANDROID</DefineConstants>
</PropertyGroup>

<ItemGroup>
<AndroidResource Include="Icon.png">
<Link>Resources\drawable\Icon.png</Link>
</AndroidResource>
</ItemGroup>

<ItemGroup>
<AndroidAsset Include="..\OpenIPC_Config\binaries\**\*">
<Link>assets\binaries\%(RecursiveDir)%(Filename)%(Extension)</Link>
</AndroidAsset>
</ItemGroup>


<ItemGroup>
<PackageReference Include="Avalonia.Android" Version="$(AvaloniaVersion)"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
Expand Down
104 changes: 94 additions & 10 deletions OpenIPC_Config/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,107 @@ namespace OpenIPC_Config;
public class App : Application
{
public static IServiceProvider ServiceProvider { get; private set; }

public static string OSType { get; private set; }

private void DetectOsType()
{
// Detect OS Type
if (OperatingSystem.IsAndroid() || OperatingSystem.IsIOS())
{
OSType = "Mobile";
}
else if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
OSType = "Desktop";
}
else
{
OSType = "Unknown";
}
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);

DetectOsType();

}

private IConfigurationRoot LoadConfiguration()
{
var configPath = GetConfigPath();

// Create default settings if not present
if (!File.Exists(configPath))
{
var defaultSettings = createDefaultAppSettings();
File.WriteAllText(configPath, defaultSettings.ToString());
Log.Information($"Default appsettings.json created at {configPath}");
}

// Build configuration
var configuration = new ConfigurationBuilder()
.AddJsonFile(configPath, optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();

return configuration;
}

private void InitializeBasicLogger()
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();

Log.Information("Basic logger initialized for early startup.");
}

private void ReconfigureLogger(IConfiguration configuration)
{
var eventAggregator = ServiceProvider.GetRequiredService<IEventAggregator>();

Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console() // Keep console logging
.WriteTo.Sink(new EventAggregatorSink(eventAggregator)) // Add EventAggregatorSink
.CreateLogger();

Log.Information(
"**********************************************************************************************");
Log.Information($"Starting up log for OpenIPC Configurator v{VersionHelper.GetAppVersion()}");
Log.Information("Logger initialized successfully.");
}

// private void InitializeLogger(IConfiguration configuration)
// {
// Log.Logger = new LoggerConfiguration()
// .ReadFrom.Configuration(configuration)
// .WriteTo.Sink(new EventAggregatorSink(ServiceProvider?.GetService<IEventAggregator>()))
// .CreateLogger();
//
// Log.Information(
// "**********************************************************************************************");
// Log.Information($"Starting up log for OpenIPC Configurator v{VersionHelper.GetAppVersion()}");
// Log.Information("Logger initialized successfully.");
// }

public override void OnFrameworkInitializationCompleted()
{
// Configure and build the DI container
// Step 1: Initialize basic logger
InitializeBasicLogger();

// Step 2: Load configuration
var configuration = LoadConfiguration();

// Configure DI container
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
ConfigureServices(serviceCollection, configuration);
ServiceProvider = serviceCollection.BuildServiceProvider();

CreateAppSettings();

// Step 4: Reconfigure logger with DI services
ReconfigureLogger(configuration);

// check for updates
CheckForUpdatesAsync();
Expand Down Expand Up @@ -207,7 +294,7 @@ private async Task CheckForUpdatesAsync()
}
}

private void ConfigureServices(IServiceCollection services)
private void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
// Register IEventAggregator as a singleton
services.AddSingleton<IEventAggregator, EventAggregator>();
Expand All @@ -218,11 +305,8 @@ private void ConfigureServices(IServiceCollection services)
services.AddSingleton<IYamlConfigService, YamlConfigService>();
services.AddSingleton<ILogger>(sp => Log.Logger);

// Load the configuration
var configPath = GetConfigPath();
var configuration = new ConfigurationBuilder()
.AddJsonFile(configPath, optional: false, reloadOnChange: true)
.Build();
// Register configuration
services.AddSingleton<IConfiguration>(configuration);

// Register IConfiguration
services.AddSingleton<IConfiguration>(configuration);
Expand Down
5 changes: 5 additions & 0 deletions OpenIPC_Config/Assets/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions OpenIPC_Config/Assets/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,7 @@ Adjust the transmission power for the 2.4GHz frequency. Lower power conserves en
</value>
</data>

<data name="LocalIpToolTip" xml:space="preserve">
<value>IP of the device running the App</value>
</data>
</root>
Loading
Loading