MonoDroid and TimeZoneInfo.ConvertTime - xamarin.android

I'm trying to convert the current time to Central Standard Time. With Mono and .NET, these both work.
TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
TimeZoneInfo.ConvertTime(DateTime.UtcNow, cst);
TimeZoneInfo.ConvertTime(DateTime.Now, cst);
With MonoDroid 3.0.4, the first one give this error:
Unhandled Exception:
System.ArgumentException: Kind propery of dateTime is Utc but the sourceTimeZone does not equal TimeZoneInfo.Utc
at System.TimeZoneInfo.ConvertTime (DateTime dateTime, System.TimeZoneInfo sourceTimeZone, System.TimeZoneInfo destinationTimeZone) [0x00000] in <filename unknown>:0
at System.TimeZoneInfo.ConvertTime (DateTime dateTime, System.TimeZoneInfo destinationTimeZone) [0x00000] in <filename unknown>:0
and the second gives this error:
Unhandled Exception:
System.ArgumentNullException: Argument cannot be null.
Parameter name: destinationTimeZone
at System.TimeZoneInfo.ConvertTime (DateTime dateTime, System.TimeZoneInfo sourceTimeZone, System.TimeZoneInfo destinationTimeZone) [0x00000] in <filename unknown>:0
at System.TimeZoneInfo.ConvertTime (DateTime dateTime, System.TimeZoneInfo destinationTimeZone) [0x00000] in <filename unknown>:0
Same problems with TimeZoneInfo.ConvertTimeBySystemTimeZoneId.
Anyway to get the current time in different timezones with MonoDroid?

One possible workaround is to call the three-parameter version yourself:
var zoned = TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, cst);
EDIT: FindSystemTimeZoneById should throw a TimeZoneNotFoundException if it doesn't find the zone you're interested in, but I wonder whether in this case it's just returning null.
It's possible that the time zone IDs on MonoDroid are the TZDB ones, in which case you could try using:
TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById("America/Chicago");

Related

How I can get correct stack trace at Unity3d (iOS)

My code:
try
{
throw new System.ArgumentException("Parameter cannot be null", "original");
}
catch (Exception ex)
{
string exception = ex.ToString();
}
But correct stack trace getting only in Unity's editor.
System.ArgumentException: Parameter cannot be null
Parameter name: original
at MyClassName (System.String message) [0x00026] in /Users/xxx/Documents/xxx/myPackageName/xxx/xxx/xxx/myClassName.cs:104
At the device stack trace is such:
System.ArgumentException: Parameter cannot be null
Parameter name: original
at MyClassName(System.String message) [0x00000] in <filename unknown>:0
at UnityEngine.Events.UnityAction.Invoke () [0x00000] in <filename unknown>:0
at UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0
at UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0
at UnityEngine.Events.UnityEvent.Invoke () [0x00000] in <filename unknown>:0
at UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1].Invoke (.T1 handler, UnityEngine.EventSystems.BaseEventData eventData) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.StandaloneInputModule.ProcessTouchPress (UnityEngine.EventSystems.PointerEventData pointerEvent, Boolean pressed, Boolean released) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.EventSystem.Update () [0x00000] in <filename unknown>:0
Why in Unity's editor I have file name and line number at stacktrace, but at this iOS device I haven't this?
It's a development build
When making an ios build in Unity, Check Development Build in the build dialog. Also, in the drop down, choose Run in Xcode as Debug. In build settings, turn off the strip symbols checkbox.
This will include the symbols in the build, and will allow filename and line numbers to be reported.
You can have line numbers on C# Exceptions with IL2CPP builds when using Sentry. Works on iOS, Android, Windows, macOS and Linux players.
Works on 2020.3 and newer.
https://docs.sentry.io/platforms/unity/configuration/il2cpp/

iOS UIFont.ByName Exception (Value cannot be null. Parameter name: value)

In a custom Xamarin Forms iOS renderer I am loading fonts from files and when I get to UIFont.FromName it thorws the exception shown below. The font var is a valid CGFont instance and fontsize is a valid nfloat. Any ideas?
var font = CGFont.CreateFromProvider(fontDataProvider);
Control.Font = UIFont.FromName(font.FullName, (nfloat)e.NewElement.FontSize);
stacktrace:
System.ArgumentNullException: Value cannot be null.
Parameter name: value
at UIKit.UILabel.set_Font (UIKit.UIFont value) [0x00011] in /Users/builder/data/lanes/1381/3afb4af5/source/maccore/src/build/ios/native/UIKit/UILabel.g.cs:337
at DecryptRenderFont.iOS.DecryptRenderControlRenderer.OnElementChanged (Xamarin.Forms.Platform.iOS.ElementChangedEventArgs`1[TElement] e) [0x00215]
at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x00118] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.iOS.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00000] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001b] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementPackager.OnChildAdded (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementPackager.Load () [0x00023] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x000cc] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.iOS.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00000] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001b] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementPackager.OnChildAdded (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.VisualElementPackager.Load () [0x00023] in <filename unknown>:0
at Xamarin.Forms.Platform.iOS.PageRenderer.ViewDidLoad () [0x0007d] in <filename unknown>:0
at (wrapper managed-to-native) ObjCRuntime.Messaging:IntPtr_objc_msgSendSuper (intptr,intptr)
at UIKit.UIViewController.get_View () [0x00030] in /Users/builder/data/lanes/1381/3afb4af5/source/maccore/src/build/ios/native/UIKit/UIViewController.g.cs:2667
1 ) I am going to assume the exception stack you are seeing is not showing the actual underlaying error as it is coming from the Xamarin.iOS generated UILabel.g.cs file (that is a auto-generated wrapper within https://github.com/xamarin/xamarin-macios) and I personally have had a few issues tracing certain low-level OS exceptions/throws and thus the shown exception is a little (a lot?) misleading.
2) Again I am going to assume since you said you are "loading fonts from files" that these fonts are not registered. Assuming you are loading these fonts via a CGFont.CreateFromProvider from files in your app bundle (or dynimically downloaded) and since they do not exist in the info.plist under the UIAppFonts key, they are not auto-registered to iOS. You need to do that step yourself:
NSError error;
if (!CTFontManager.RegisterGraphicsFont(customFont, out error))
{
// error occurred, checkout the contents of the NSError var
}
After registering the CGFont with the iOS font manager (CTFontManager) you can actually use them within UIKit, otherwise internally there is an exception within iOS code... Would need to write some ObjC/Swift to check it out in Xcode to see what the actual error being thrown is...
Are your fonts registered or not:
Somewhere before the exception but after your CreateFromProvider, you can do the following:
foreach (var familyNames in UIFont.FamilyNames.OrderBy(c => c).ToList())
{
D.WriteLine(" * " + familyNames);
foreach (var familyName in UIFont.FontNamesForFamilyName(familyNames).OrderBy(c => c).ToList())
{
D.WriteLine(" *-- " + familyName);
}
}
Note: D is just using D = System.Diagnostics.Debug;
I would bet that your font is not in the list, but after a call to CTFontManager.RegisterGraphicsFont it will be in that list and valid to be consumed by UIKit.
Update:
Interesting note in that using a Swift-based app and not registering the font does not cause a app crash. The font is not shown of course, but referencing it via UIFont(name: "XXXXX", size: 35) is just a silent failure.
So I'd just recommend some defensive try{} catch{} around any use of your custom font to be safe.
Xamarin.iOS - Custom Fonts
iOS only supports .TTF and .OTF font types.
Add the fonts to the 'Resources/Fonts/' folder (any folder would do but lets keep it organized).
Right click on the added font, 'Properties', change ‘Copy to output directory’ to ‘Always copy’.
Open the Info.plist file and select ‘Source’ at the bottom of the view.
‘Add new entry’, select ‘Fonts provided by application’.
Input the location of the font ‘Fonts/FontName.ttf’.
Use it: lab1.Font = UIFont.FromName("FontName", 20f);
All credit goes to Mike James - custom-fonts-in-ios.
To add to Eyal/Mike James answer. Its important that you use the right FontName. If you open your font files info, you may see that the file name is different from your Full Name.
In the image below you can see the File name is FranklinGothicMedium.otf but the full name is FranklinGothicURW-Med. You must use the full name when using UIFont.FromName([YourFontFullName], 20f);.

Crash on iPhone camera start, few but vague errors

I should note that this is an augmented reality project. Application works perfect with Mono2x. Changed to IL2CPP because app store requires 64-bit. Splash screen still plays, but now when the camera tries to start, the app crashes.
I am instantiating objects which represent the player's score. This works perfectly with Mono2X.
I also have a very simple collision which worked fine before too.
I get very vague errors like this:
ArgumentException: The thing you want to instantiate is null.
at UnityEngine.AssetBundle.LoadAsset_Internal (System.String name,
System.Type type) [0x00000] in <filename unknown>:0
at UnityEngine.Object.Instantiate (UnityEngine.Object original)
[0x00000] in <filename unknown>:0
at UnityEngine.Object.Instantiate (UnityEngine.Object original)
[0x00000] in <filename unknown>:0
at ScoreHandler.OnCollisionEnter (UnityEngine.Collision col) [0x00000]
in <filename unknown>:0
(Filename: currently not available on il2cpp Line: -1)
Unhandled Exception: System.ArgumentException: The thing you want to
instantiate is null.
at UnityEngine.AssetBundle.LoadAsset_Internal (System.String name,
System.Type type) [0x00000] in <filename unknown>:0
at UnityEngine.Object.Instantiate (UnityEngine.Object original)
[0x00000] in <filename unknown>:0
at UnityEngine.Object.Instantiate (UnityEngine.Object original)
[0x00000] in <filename unknown>:0
at ScoreHandler.OnCollisionEnter (UnityEngine.Collision col) [0x00000]
in <filename unknown>:0
I also get an error on loading the ARMarker. The marker successfully loads anyways though.
ARController (native): [error]Loading single AR marker from buffer,
width 55.000000.
ARController (native): [error]ARController::addMarker(): called
ARController (native): ARController::addMarker(): Added marker (UID=0),
total markers loaded: 1, exiting, returning true
ARController: Starting AR.
I'm more concerned with the ArgumentException which is causing the program to crash.

Using Protobuf-net, I get an exception about an unknown wire-type with List<Subclassable>

I've started to convert our Unity/iOS game to save state with Protobuf-net. It looked like things were working OK, until I added this instance variable to GameState
[ProtoMember(10)]
public List<Unit> fUnits;
Unit is
[ProtoContract]
[ProtoInclude(21, typeof(ArtilleryUnit))]
[ProtoInclude(22, typeof(CavalryArtilleryUnit))]
[ProtoInclude(23, typeof(CavalryUnit))]
[ProtoInclude(24, typeof(InfantryUnit))]
[Serializable]
public class Unit : IActionHandler
This is the first subclass I've serialized. I'm testing my code by deserializing right after writing
using (Stream memoryStream = new MemoryStream()) {
byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
memoryStream.Write(data, 0, data.Length);
memoryStream.Position = 0;
WBTSSerializer deserializer = new WBTSSerializer();
testState = new GameState();
deserializer.Deserialize(memoryStream, testState, typeof(GameState));
}
and I get
ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354
at ProtoBuf.ProtoReader.SkipField () [0x00000] in <filename unknown>:0
at WBTSSerializer.Read (wbts.Unit , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
at WBTSSerializer.Read (wbts.GameState , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
at WBTSSerializer.Deserialize (Int32 , System.Object , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader reader, System.Type type, System.Object value, Boolean noAutoCreate) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type, ProtoBuf.SerializationContext context) [0x00000] in <filename unknown>:0
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type) [0x00000] in <filename unknown>:0
at wbts.Game.SaveGame (System.String filename) [0x000c1] in /Users/david/Shenandoah/WBTS/wbts/wbts/Game.cs:620
Needless to say, I've checked for overwriting (it's a brand new file). And, if I take out the ProtoMember(10), it won't throw.
If I take out the ProtoInclude lines, I get an error about the subclasses. And, if I take out ProtoMember within Unit, it still throws.
If it matters, I am currently just running this from Xamarin (on Mac OS X — I'm an iOS developer). But that's just for ease of testing, I have managed to hit Protobuf-net with enough sticks to make it run on an iPad.
My eye is drawn immediately to:
byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
Protobuf data is not text, and is not UTF-8 (although strings inside protobuf data are UTF-8, by coincidence) - therefore "decoding" it (wrong word, really) via UTF8 will guarantee you corrupt data. The preferred way to deal with protobuf data is as binary - for example, a byte[] - much like you would with image data etc. However, if you are required to store or transport it in a text form, then Convert.ToBase64String and Convert.FromBase64String are appropriate mechanisms to translate between text and binary. Please see the first section of How many ways can you mess up IO? for more information.

Exception 'Attempting to JIT compile method, while running with --aot-only' with Google.ProtocolBuffersLite

Im using Google.ProtocolBuffersLite in a class library that is used in my Unity3d project.
When attempting to use ParseFrom(System.Byte[] data) function within myClass.cs in the app on IOS I get the following exception:
---> System.TypeInitializationException: An exception was thrown by the type initializer for System.Collections.Generic.EqualityComparer`1
---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ExecutionEngineException: Attempting to JIT compile method 'System.Collections.Generic.GenericEqualityComparer`1<Google.ProtocolBuffers.ExtensionRegistry/ExtensionIntPair>:.ctor ()' while running with --aot-only.
at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
at System.Reflection.MonoCMethod.Invoke (BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
at System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0
at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0
at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
at System.Collections.Generic.EqualityComparer`1[Google.ProtocolBuffers.ExtensionRegistry+ExtensionIntPair]..cctor () [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Collections.Generic.Dictionary`2[Google.ProtocolBuffers.ExtensionRegistry+ExtensionIntPair,Google.ProtocolBuffers.IGeneratedExtensionLite].Init (Int32 capacity, IEqualityComparer`1 hcp) [0x00000] in <filename unknown>:0
at System.Collections.Generic.Dictionary`2[Google.ProtocolBuffers.ExtensionRegistry+ExtensionIntPair,Google.ProtocolBuffers.IGeneratedExtensionLite]..ctor () [0x00000] in <filename unknown>:0
at Google.ProtocolBuffers.ExtensionRegistry..cctor () [0x00000] in <filename unknown>:0 Exception.Message: An exception was thrown by the type initializer for Google.ProtocolBuffers.ExtensionRegistry
at Google.ProtocolBuffers.AbstractBuilderLite`2[TMessage,TBuilder].MergeFrom (System.Byte[] data) [0x00000] in <filename unknown>:0
The procedure to use protocolBuffersLite was:
Add option optimize_for = LITE_RUNTIME; in my .proto class
Generate .cs class using that .proto class and Google.ProtocolBuffers.dll version net20
Add to my library csharp proj the .cs class and the Google.ProtocolBuffersLite.dll
Compile with monoDevelop 2.8.2
Move myLibraryThatUseProtocol.dll and Google.ProtocolBuffersLite.dll to myUnity3d project
In Unity3D->Build Settings->IOS->PlayerSettings I use:
Api Compatibility level: .net 2.0 subset
Aot compilation options: empty
Stripping level: Disabled
Build app in Unity3d (version 4.2.0)
Run app in Xcode
I will be grateful for any help somebody can provide.

Resources