*/
using System;
+using System.Collections.Concurrent;
+using System.ComponentModel;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
using System.Timers;
using Tizen.Applications.CoreBackend;
public class CoreApplication : Application
{
private readonly ICoreBackend _backend;
+ private readonly ICoreTask _task;
private bool _disposedValue = false;
- private static Timer sTimer;
-
/// <summary>
/// Initializes the CoreApplication class.
/// </summary>
public CoreApplication(ICoreBackend backend)
{
_backend = backend;
+ _task = null;
+ }
+
+ /// <summary>
+ /// Initializes the CoreApplication class.
+ /// </summary>
+ /// <param name="backend">The backend instance implementing ICoreBackend interface.</param>
+ /// <param name="task">The backend instance implmenting ICoreTask interface.</param>
+ /// <since_tizen> 10 </since_tizen>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public CoreApplication(ICoreBackend backend, ICoreTask task)
+ {
+ _backend = backend;
+ _task = task;
}
/// <summary>
/// The backend instance.
/// </summary>
/// <since_tizen> 3 </since_tizen>
- protected ICoreBackend Backend { get { return _backend; } }
+ protected ICoreBackend Backend { get { return _backend; } }
/// <summary>
/// Runs the application's main loop.
_backend.AddEventHandler<RegionFormatChangedEventArgs>(EventType.RegionFormatChanged, OnRegionFormatChanged);
_backend.AddEventHandler<DeviceOrientationEventArgs>(EventType.DeviceOrientationChanged, OnDeviceOrientationChanged);
- string[] argsClone = new string[args.Length + 1];
- if (args.Length > 1)
+ string[] argsClone = new string[args == null ? 1 : args.Length + 1];
+ if (args != null && args.Length > 1)
{
args.CopyTo(argsClone, 1);
}
argsClone[0] = string.Empty;
- _backend.Run(argsClone);
+ if (_task != null)
+ {
+ ICoreTaskBackend backend = (ICoreTaskBackend)_backend;
+ backend.SetCoreTask(_task);
+ backend.Run(argsClone);
+ }
+ else
+ {
+ _backend.Run(argsClone);
+ }
}
/// <summary>
/// <since_tizen> 3 </since_tizen>
protected virtual void OnCreate()
{
- string locale = ULocale.GetDefaultLocale();
- ChangeCurrentUICultureInfo(locale);
- ChangeCurrentCultureInfo(locale);
+ if (_task != null)
+ {
+ TizenUISynchronizationContext.Initialize();
+ }
+
+ if (!GlobalizationMode.Invariant)
+ {
+ string locale = ULocale.GetDefaultLocale();
+ ChangeCurrentUICultureInfo(locale);
+ ChangeCurrentCultureInfo(locale);
+ }
+ else
+ {
+ Log.Warn(LogTag, "Run in invariant mode");
+ }
Created?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnLowMemory(LowMemoryEventArgs e)
{
LowMemory?.Invoke(this, e);
- double interval = new Random().Next(10 * 1000);
- if (interval <= 0)
- interval = 10 * 1000;
-
- sTimer = new Timer(interval);
- sTimer.Elapsed += OnTimedEvent;
- sTimer.AutoReset = false;
- sTimer.Enabled = true;
- }
-
- private static void OnTimedEvent(Object source, ElapsedEventArgs e)
- {
- System.GC.Collect();
+ if (e.LowMemoryStatus == LowMemoryStatus.SoftWarning || e.LowMemoryStatus == LowMemoryStatus.HardWarning)
+ {
+ System.GC.Collect();
+ }
}
/// <summary>
/// <since_tizen> 3 </since_tizen>
protected virtual void OnLocaleChanged(LocaleChangedEventArgs e)
{
- ChangeCurrentUICultureInfo(e.Locale);
+ if (!GlobalizationMode.Invariant)
+ {
+ ChangeCurrentUICultureInfo(e.Locale);
+ }
+
LocaleChanged?.Invoke(this, e);
}
/// <since_tizen> 3 </since_tizen>
protected virtual void OnRegionFormatChanged(RegionFormatChangedEventArgs e)
{
- ChangeCurrentCultureInfo(e.Region);
+ if (!GlobalizationMode.Invariant)
+ {
+ ChangeCurrentCultureInfo(e.Region);
+ }
+
RegionFormatChanged?.Invoke(this, e);
}
}
/// <summary>
+ /// Dispatches an asynchronous message to a main loop of the CoreApplication.
+ /// </summary>
+ /// <remarks>
+ /// If an application uses UI thread App Model, the asynchronous message will be delivered to the UI thread.
+ /// If not, the asynchronous message will be delivered to the main thread.
+ /// </remarks>
+ /// <param name="runner">The runner callaback.</param>
+ /// <exception cref="ArgumentNullException">Thrown when the runner is null.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void Post(Action runner)
+ {
+ if (runner == null)
+ {
+ throw new ArgumentNullException(nameof(runner));
+ }
+
+ GSourceManager.Post(runner, true);
+ }
+
+ /// <summary>
+ /// Dispatches an asynchronous message to a main loop of the CoreApplication.
+ /// </summary>
+ /// <remarks>
+ /// If an application uses UI thread App Model, the asynchronous message will be delivered to the UI thread.
+ /// If not, the asynchronous message will be delivered to the main thread.
+ /// </remarks>
+ /// <typeparam name="T">The type of the result.</typeparam>
+ /// <param name="runner">The runner callback.</param>
+ /// <exception cref="ArgumentNullException">Thrown when the runner is null.</exception>
+ /// <returns>A task with the result.</returns>
+ /// <since_tizen> 10 </since_tizen>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static async Task<T> Post<T>(Func<T> runner)
+ {
+ if (runner == null)
+ {
+ throw new ArgumentNullException(nameof(runner));
+ }
+
+ var task = new TaskCompletionSource<T>();
+ GSourceManager.Post(() => { task.SetResult(runner()); }, true);
+ return await task.Task.ConfigureAwait(false);
+ }
+
+ /// <summary>
/// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
/// </summary>
/// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
private CultureInfo ConvertCultureInfo(string locale)
{
ULocale pLocale = new ULocale(locale);
+ string cultureName = CultureInfoHelper.GetCultureName(pLocale.Locale.Replace("_", "-"));
+
+ if (!string.IsNullOrEmpty(cultureName))
+ {
+ try
+ {
+ return new CultureInfo(cultureName);
+ }
+ catch (CultureNotFoundException)
+ {
+ Log.Error(LogTag, "CultureNotFoundException occurs. CultureName: " + cultureName);
+ }
+ }
try
{
private void ChangeCurrentCultureInfo(string locale)
{
- CultureInfo.CurrentCulture = ConvertCultureInfo(locale);
+ CultureInfo cultureInfo = ConvertCultureInfo(locale);
+ if (cultureInfo != null)
+ {
+ CultureInfo.CurrentCulture = cultureInfo;
+ }
+ else
+ {
+ Log.Error(LogTag, "CultureInfo is null. locale: " + locale);
+ }
}
private void ChangeCurrentUICultureInfo(string locale)
{
- CultureInfo.CurrentUICulture = ConvertCultureInfo(locale);
+ CultureInfo cultureInfo = ConvertCultureInfo(locale);
+ if (cultureInfo != null)
+ {
+ CultureInfo.CurrentUICulture = cultureInfo;
+ }
+ else
+ {
+ Log.Error(LogTag, "CultureInfo is null. locale: " + locale);
+ }
}
private bool ExistCultureInfo(string locale)
if (fallbackCultureInfo == null)
{
- locale = "en";
- fallbackCultureInfo = GetCultureInfo(locale);
+ try
+ {
+ fallbackCultureInfo = new CultureInfo("en");
+ }
+ catch (CultureNotFoundException e)
+ {
+ Log.Error(LogTag, "Failed to create CultureInfo. err = " + e.Message);
+ }
}
return fallbackCultureInfo;
}
}
+ internal static class GlobalizationMode
+ {
+ private static int _invariant = -1;
+
+ internal static bool Invariant
+ {
+ get
+ {
+ if (_invariant == -1)
+ {
+ string value = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
+ _invariant = value != null ? (value.Equals("1") ? 1 : 0) : 0;
+ }
+
+ return _invariant != 0;
+ }
+ }
+ }
+
internal class ULocale
{
private const int ULOC_FULLNAME_CAPACITY = 157;