0

Similar question to this one : How can I detect the Android runtime (Dalvik or ART)?

How to do it in Xamarin.Android (MonoDroid), since I dont have java reflection here?

Since ART is not working on xamarin yet, I would like to detect it and show user some friendly message instead on app crash at least. Thanks.

Community
  • 1
  • 1
rouen
  • 5,003
  • 2
  • 25
  • 48

2 Answers2

3

Seems to work on the emulator, don't know what happens with actual device until it gets some charge:

[Activity (Label = "RuntimeActivity", MainLauncher = true)]
public class RuntimeActivity : Activity 
{
    private static readonly string SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib";
    private static readonly string LIB_DALVIK = "libdvm.so";
    private static readonly string  LIB_ART = "libart.so";
    private static readonly string  LIB_ART_D = "libartd.so";

    override protected void OnCreate(Bundle savedInstanceState) {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.runtime);

        var tv = FindViewById<TextView>(Resource.Id.textView1);
        tv.Text = getCurrentRuntimeValue ();
    }

    private string getCurrentRuntimeValue() 
    {
        try 
        {
            var systemProperties = Java.Lang.Class.ForName("android.os.SystemProperties");

            try 
            {
                var str = new Java.Lang.String();
                var getMethod = systemProperties.GetMethod("get", str.Class, str.Class);

                if (getMethod == null) 
                {
                    return "WTF?!";
                }

                try 
                {
                    var value = getMethod.Invoke(systemProperties, SELECT_RUNTIME_PROPERTY,
                        /* Assuming default is */"Dalvik").ToString();
                    if (LIB_DALVIK.Equals(value)) {
                        return "Dalvik";
                    } else if (LIB_ART.Equals(value)) {
                        return "ART";
                    } else if (LIB_ART_D.Equals(value)) {
                        return "ART debug build";
                    }

                    return value;
                } 
                catch (IllegalAccessException e) 
                {
                    Log.Error(this.ToString(), e.Message);
                    return "IllegalAccessException";
                } 
                catch (IllegalArgumentException e) 
                {
                    Log.Error(this.ToString(), e.Message);
                    return "IllegalArgumentException";
                } 
                catch (InvocationTargetException e) 
                {
                    Log.Error(this.ToString(), e.Message);
                    return "InvocationTargetException";
                }
            } 
            catch (NoSuchMethodException e) 
            {
                Log.Error(this.ToString(), e.Message);
                return "SystemProperties.get(String key, String def) method is not found";
            }
        } 
        catch (ClassNotFoundException e) 
        {
            Log.Error(this.ToString(), e.Message);
            return "SystemProperties class is not found";
        }
    }
}
SKall
  • 5,234
  • 1
  • 16
  • 25
  • Thanks. I implemented simple version - just the var value = getMethod.Invoke(...).ToString(); and for ART it is returning "libart.so" but for Dalvik it actually returns "Dalvik" (not "libdvm.so") which is strange, but good enough for detecting ART – rouen Feb 26 '14 at 12:31
1

Xamarin.Android itself uses __system_property_get, which is a stable, documented, API, so you can use P/Invoke to do the same:

// <sys/system_properties.h>
[DllImport ("/system/lib/libc.so")]
static extern int __system_property_get (string name, StringBuilder value);

const int MaxPropertyNameLength   = 32; // <sys/system_properties.h>
const int MaxPropertyValueLength  = 92; // <sys/system_properties.h>

static bool OnArt {
    get {
        var buf = new StringBuilder (MaxPropertyValueLength + 1);
        int n   = __system_property_get ("persist.sys.dalvik.vm.lib", buf);
        if (n > 0)
            return buf.ToString () == "libart.so";
        return false;
    }
}
jonp
  • 13,512
  • 5
  • 45
  • 60