You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by fr...@apache.org on 2025/04/29 11:05:10 UTC
(logging-log4net) 01/01: #239 detect Android and use environment variables instead of AppSettings
This is an automated email from the ASF dual-hosted git repository.
freeandnil pushed a commit to branch Feature/239-Android-Support
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git
commit 418062c39ad9c9945af7eeac100ef2ef65a72fe7
Author: Jan Friedrich <fr...@apache.org>
AuthorDate: Tue Apr 29 13:04:28 2025 +0200
#239 detect Android and use environment variables instead of AppSettings
---
src/log4net.Tests/Util/SystemInfoTest.cs | 7 +++-
src/log4net/Appender/AdoNetAppender.cs | 5 +--
src/log4net/Core/DefaultRepositorySelector.cs | 6 +--
src/log4net/Util/SystemInfo.cs | 47 ++++++++++++++++++----
.../modules/ROOT/pages/manual/configuration.adoc | 10 ++++-
5 files changed, 57 insertions(+), 18 deletions(-)
diff --git a/src/log4net.Tests/Util/SystemInfoTest.cs b/src/log4net.Tests/Util/SystemInfoTest.cs
index 8cd3fd75..9b9067c9 100644
--- a/src/log4net.Tests/Util/SystemInfoTest.cs
+++ b/src/log4net.Tests/Util/SystemInfoTest.cs
@@ -166,4 +166,9 @@ public void EqualsIgnoringCase_SameStringsDifferentCase_true()
[Test]
public void EqualsIgnoringCase_DifferentStrings_false()
=> Assert.That(SystemInfo.EqualsIgnoringCase("foo", "foobar"), Is.False);
-}
+
+ [Test]
+ [Platform(Include = "Win,Linux,MacOsX")]
+ public void IsAndoid()
+ => Assert.That(typeof(SystemInfo).GetProperty("IsAndroid", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null), Is.False);
+}
\ No newline at end of file
diff --git a/src/log4net/Appender/AdoNetAppender.cs b/src/log4net/Appender/AdoNetAppender.cs
index 4453e39e..f720dfdf 100644
--- a/src/log4net/Appender/AdoNetAppender.cs
+++ b/src/log4net/Appender/AdoNetAppender.cs
@@ -449,10 +449,7 @@ protected override void SendBuffer(LoggingEvent[] events)
/// Adds a parameter to the ordered list of command parameters.
/// </para>
/// </remarks>
- public void AddParameter(AdoNetAppenderParameter parameter)
- {
- m_parameters.Add(parameter);
- }
+ public void AddParameter(AdoNetAppenderParameter parameter) => m_parameters.Add(parameter);
/// <summary>
/// Writes the events to the database using the transaction specified.
diff --git a/src/log4net/Core/DefaultRepositorySelector.cs b/src/log4net/Core/DefaultRepositorySelector.cs
index f960a6e4..4cc14c88 100644
--- a/src/log4net/Core/DefaultRepositorySelector.cs
+++ b/src/log4net/Core/DefaultRepositorySelector.cs
@@ -469,10 +469,8 @@ public void AliasRepository(string repositoryAlias, ILoggerRepository repository
/// Raises the <see cref="LoggerRepositoryCreatedEvent"/> event.
/// </para>
/// </remarks>
- protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository)
- {
- LoggerRepositoryCreatedEvent?.Invoke(this, new LoggerRepositoryCreationEventArgs(repository));
- }
+ protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository)
+ => LoggerRepositoryCreatedEvent?.Invoke(this, new(repository));
/// <summary>
/// Gets the repository name and repository type for the specified assembly.
diff --git a/src/log4net/Util/SystemInfo.cs b/src/log4net/Util/SystemInfo.cs
index 6c0f05b7..30b23fdc 100644
--- a/src/log4net/Util/SystemInfo.cs
+++ b/src/log4net/Util/SystemInfo.cs
@@ -36,6 +36,11 @@ public static class SystemInfo
private const string DefaultNullText = "(null)";
private const string DefaultNotAvailableText = "NOT AVAILABLE";
+ /// <summary>
+ /// Is OperatingSystem Android
+ /// </summary>
+ internal static bool IsAndroid { get; } = IsAndroidCore();
+
/// <summary>
/// Initialize default values for private static fields.
/// </summary>
@@ -68,6 +73,34 @@ static SystemInfo()
NullText = nullText;
}
+ private static bool IsAndroidCore() // https://stackoverflow.com/questions/47521008/how-can-i-distinguish-between-unix-and-android-on-netstandard-2-0
+ {
+ if (Environment.OSVersion.Platform != PlatformID.Unix)
+ return false;
+ using System.Diagnostics.Process process = new()
+ {
+ StartInfo = new()
+ {
+ FileName = "getprop",
+ Arguments = "ro.build.user",
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+
+ try
+ {
+ process.Start();
+ string output = process.StandardOutput.ReadToEnd();
+ return !string.IsNullOrEmpty(output);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ return false;
+ }
+ }
+
/// <summary>
/// Gets the system dependent line terminator.
/// </summary>
@@ -414,10 +447,8 @@ public static string AssemblyFileName(Assembly myAssembly)
/// then all the loaded assemblies will be searched for the type.
/// </para>
/// </remarks>
- public static Type? GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase)
- {
- return GetTypeFromString(relativeType.EnsureNotNull().Assembly, typeName, throwOnError, ignoreCase);
- }
+ public static Type? GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase)
+ => GetTypeFromString(relativeType.EnsureNotNull().Assembly, typeName, throwOnError, ignoreCase);
/// <summary>
/// Loads the type specified in the type string.
@@ -438,10 +469,8 @@ public static string AssemblyFileName(Assembly myAssembly)
/// in the assembly then all the loaded assemblies will be searched for the type.
/// </para>
/// </remarks>
- public static Type? GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase)
- {
- return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase);
- }
+ public static Type? GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase)
+ => GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase);
/// <summary>
/// Loads the type specified in the type string.
@@ -646,6 +675,8 @@ public static bool TryParse(string s, out short val)
/// <returns>the value for the key, or <c>null</c></returns>
public static string? GetAppSetting(string key)
{
+ if (IsAndroid)
+ return Environment.GetEnvironmentVariable(key); // Android does not support config files
try
{
return ConfigurationManager.AppSettings[key];
diff --git a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
index ccb1c9bc..fff7d2db 100644
--- a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
@@ -349,7 +349,6 @@ The section must specify the `log4net.Config.Log4NetConfigurationSectionHandler,
The following is a simple example configuration file that specifies the correct section handler to use for the `log4net` section.
-
[source,xml]
----
<configuration>
@@ -427,6 +426,15 @@ The example shows how to embed configuration data in a .config file while allowi
Since the .NET config parser throws errors for unregistered elements, the `log4net` section is registered using `System.Configuration.IgnoreSectionHandler`.
This tells .NET to ignore the section, as it will be processed by log4net instead.
+[#android]
+== Android
+
+Android does not support `.config` files.
+
+Instead, you can set `AppSettings` values as environment variables for your process — this works only on Android.
+
+You must also load the `log4net` configuration manually, for example by reading it from an XML file at runtime.
+
[#configuration-syntax]
== Configuration Syntax