2014-02-25 304 views
0

类似问题发现了Android运行时(Dalvik的或艺术)在Xamarin这一个:How can I detect the Android runtime (Dalvik or ART)?我怎样才能

如何做到这一点在Xamarin.Android(MonoDroid的),因为我没有Java反射吗?

由于ART尚未在Xamarin上工作,我想检测它并向用户显示一些友好的消息,而不是应用程序崩溃。谢谢。

回答

3

似乎在模拟器上工作,不知道实际设备发生了什么,直到它得到了一些负责人:

[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"; 
     } 
    } 
} 
+0

谢谢。我实现了简单的版本 - 只是var value = getMethod.Invoke(...)。ToString();而对于ART,它会返回“libart.so”,但对于Dalvik,它实际上会返回“Dalvik”(而不是“libdvm.so”),这很奇怪,但足以检测ART – rouen

1

Xamarin.Android本身使用__system_property_get,这是一个稳定的,有记录,API,所以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; 
    } 
}