A way to create GUIDs reliably

We need a way to create GUIDs reliably. This works for Android:

public string NewRandom() { 
    return ((string)Android.java.util.UUID.randomUUID().toString()).Replace("-", ""); 
}

This works for iOS:

public string NewRandom() { 
    var uuid = new iOS.Foundation.NSUUID();
    uuid.init();
    return uuid.UUIDString.Replace("-", "");
}

We have nothing that works reliably on DotNetExe, and would love for this to be part of the offerings of the platform.

Hi!

In .NET/CIL you can do this:

[DotNetType("System.Guid")]
struct Guid
{
    int _foo; // dummy - empty structs not allowed
    public static extern Guid NewGuid();
}

And to use it:

if defined(CIL)
    debug_log Guid.NewGuid().ToString();

I agree that this should ideally be a Fuse platform feature.

Thanks for the iOS/Android implementations, I’ve linked all this to a ticket so we’ll add an official API for this at some point.

Perfect!

Here is our implementation in case anyone needs it:

using Uno;
using Uno.Diagnostics;
using Uno.Collections;
using Uno.Compiler.ExportTargetInterop;
using Fuse;
using Android.java.util;
using iOS.Foundation;

namespace Flare
{

    interface IGuidProvider 
    {
        string NewGuid();
    }

    [ExportCondition("Android")]
    public class AndroidGuidProvider : IGuidProvider
    {

        public string NewGuid() { 
            return ((string)Android.java.util.UUID.randomUUID().toString()).Replace("-", ""); 
        }        
    }

    [DotNetType("System.Guid")]
    struct DotNetGuid
    {
        int _foo; // dummy - empty structs not allowed
        public static extern DotNetGuid NewGuid();
    }

    [ExportCondition("CIL")]
    public class CilGuidProvider : IGuidProvider 
    {
        public string NewGuid() {
            return DotNetGuid.NewGuid().ToString().Replace("-", "");
        }
    }

    [ExportCondition("iOS")]
    public class iOSGuidProvider : IGuidProvider
    {
        public string NewGuid() { 
            var uuid = new iOS.Foundation.NSUUID();
            uuid.init();
            return uuid.UUIDString.Replace("-", "");
        }
    }

    public static class Guid 
    {
        static IGuidProvider guidProvider = null;

        static void CreateGuidProvider() 
        {
            if defined(Android) 
            {
                guidProvider = new AndroidGuidProvider();
            } 
            else if defined(iOS)
            {
                guidProvider = new iOSGuidProvider();
            } 
            else if defined(CIL) 
            {
                guidProvider = new CilGuidProvider();
            }
        }

        public static string NewGuid() 
        {
            if (guidProvider == null) 
            {
                CreateGuidProvider();
            }
            return guidProvider.NewGuid();
        }
    }
}

I’d just like to point out that since every implementation does Replace("-", ""), you probably should consider that those dashes are part of the UUID (which is the standardized name) spec, and should thus be kept in the API. You can call Replace on the result, if needed instead.

Also, renaming to UUID instead of GUID is probably also a good idea, GUID is the Microsoft-name.

Hey all,
here’s a module that returns a UUID, written in Foreign Code.
Usage in JS:

var UUID = require('UUIDModule');
var guid = UUID.getUUID();

On iOS and Android it will return a UUID string that the device comes up with, while on local preview it will always return “00000000-0000-0000-0000-000000000000”.

The module code - save it as UUIDModule.uno in your project root:

using Uno;
using Uno.UX;
using Uno.Threading;
using Uno.Text;
using Uno.Platform;
using Uno.Compiler.ExportTargetInterop;
using Uno.Collections;
using Fuse;
using Fuse.Scripting;
using Fuse.Reactive;

[ForeignInclude(Language.Java, "java.util.UUID")]

[UXGlobalModule]
public sealed class UUIDModule : NativeModule
{
	static readonly UUIDModule _instance;

	public UUIDModule()
	{
	    if(_instance != null) return;
	    Resource.SetGlobalKey(_instance = this, "UUIDModule");

	    AddMember(new NativeFunction("getUUID", getUUID));
	}

	static string getUUID(Context c, object[] args)
	{
	    return GetUUID();
	}

	[Foreign(Language.Java)]
	extern(android)
	public static string GetUUID()
	@{
	    return UUID.randomUUID().toString();
	@}

	[Foreign(Language.ObjC)]
	extern(iOS)
	public static string GetUUID()
	@{
		NSString *uuid = [[NSUUID UUID] UUIDString];
		return uuid;
	@}

	extern(!mobile)
	public static string GetUUID()
	{
	    return "00000000-0000-0000-0000-000000000000";
	}
}

Hi, Uldis.

That happens because preview’s code part constantly return string with zeros:

extern(!mobile)
public static string GetUUID()
{
    return "00000000-0000-0000-0000-000000000000";
}

I recommend use this package for valid result for all cases. But actually I’m little bit surprise about your question because you help me test this package for android several month ago=)

Hey Max,
I know the reason because I put the zeroes there myself, no worries :slight_smile: In my case, I did not need anything for identifying local preview.
As for the package, yeah, I should have remembered about the one you wrote, but it somehow skipped my mind completely. Well in any case, here’s another, simplified take on just he UUID part.

I do not seem to have carefully read your post=) I just saw one problem - only on iOS we will have the right UUID

Why is that?

This of course depends on what kind of behaviour you should:

  1. Get a unique UUID for each device;
  2. Simply generate a random UUID each time when you call getUUID()

The thing is that you have for iOS - first case and for Android - second. For Preview - neither.

If you call twice this method on iOS we get the same UUID for a specific device every time. For Android, you would get each time a different value.

Well that’s interesting. Because in my tests, iOS gave me a random UUID every time I called getUUID() too, just as Android did.

Yep, I changed code to using identifierForVendor instead NSUUID which generate random UUID every call-time.

[[[UIDevice currentDevice] identifierForVendor] UUIDString]