Skip to content

Commit

Permalink
Merge pull request #63 from OpenIPC/merge-android-fixes
Browse files Browse the repository at this point in the history
Merge android fixes
  • Loading branch information
mikecarr authored Jan 10, 2025
2 parents ac052a7 + e61aabd commit deab5e0
Show file tree
Hide file tree
Showing 17 changed files with 353 additions and 22 deletions.
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

0 comments on commit deab5e0

Please sign in to comment.