2014-02-25 85 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; 
    } 
}