Search code examples
c#monoruntime.net-standard

How can I distinguish between Unix and Android on NetStandard 2.0?


I need to distinguish between Android and Unix at runtime in a .NetStandard 2.0 library. The library must compile for .Net Standard so an #if ANDROID solution is not suitable. Environment.OSVersion returns Unix 3.18.14.12365438 on Android.

Other solutions like https://www.nuget.org/packages/Xam.Plugin.DeviceInfo/ wont work on Android because then the Mono Profile is missing at runtime and are only possible if the library is compiled for multiple targets.

Is there a way to detect this at runtime ?


Solution

  • You need something environmental.

    Without getting into native shared libraries (.so) and the permission issues, API differences, etc.. DLLImport externs are not a great option.

    An OS file existent can be troublesome due to sandboxing so File.Exists should be avoided.

    But Android does have a cmd getprop that is available to any user (i.e. non-root), is always in the shell path and thus if it executes and returns a value you are on Android. Cheap but it works...

    public static class AndroidTest
    {
        static bool? isAndroid;
        public static bool Check()
        {
            if (isAndroid != null) return (bool)isAndroid;
            using (var process = new System.Diagnostics.Process())
            {
                process.StartInfo.FileName = "getprop";
                process.StartInfo.Arguments = "ro.build.user";
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                try
                {
                    process.Start();
                    var output = process.StandardOutput.ReadToEnd();
                    isAndroid = string.IsNullOrEmpty(output) ? (bool?)false : (bool?)true;
                }
                catch
                {
                    isAndroid = false;
                }
                return (bool)isAndroid;
            }
        }
    }
    

    Note: Of course someone could spoof a getprop cmd and its return value to fool this, or any other environmental check, but unless you have access to Android native APIs and have a desire to stay 100% portable, I do not see a way around it...