Reflexión para un campo que va mal

He estado intentando utilizar la reflexión para un campo specifiec en la clase android.os.build, el campo MANUFACTURER … He intentado usar este código:

try { Class myBuildClass = android.os.Build.class; Field m1 = Build.class.getDeclaredField("MANUFACTURER"); validField = true; manufacturer = Build.MANUFACTURER; } catch(Exception ex) { manufacturer = Build.PRODUCT; System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString()); } 

Estoy gettign los siguientes errores:

 06-01 11:26:37.639: WARN/dalvikvm(7342): VFY: unable to resolve static field 2 (MANUFACTURER) in Landroid/os/Build; 06-01 11:26:37.639: WARN/dalvikvm(7342): VFY: rejecting opcode 0x62 at 0x0048 06-01 11:26:37.639: WARN/dalvikvm(7342): VFY: rejected Lmypackage/android/managementModule/Management;.getDeviceSpecifics ()V 06-01 11:26:37.639: WARN/dalvikvm(7342): Verifier rejected class Lmypackage/android/managementModule/Management; 

Y al depurar me di cuenta de que InvocationtargetException es continuamente lanzado, por lo que estoy adivinando que no he estado implementando el principio de reflexión todo correctamente … ¿Alguna idea de dónde van las cosas mal o de otra manera sobre cómo implementar Refelction para un solo campo correctamente?

Solución perfecta

 try // reflection { Field manufacturerField = android.os.Build.class .getDeclaredField("MANUFACTURER"); manufacturerField.setAccessible(true); String manufacturerName = manufacturerField.get( android.os.Build.class).toString(); System.out.println("manufacturerName: " + manufacturerName); } catch (Exception ex) { System.err .println("getManufacturerName, got an exception during getting Field : " + ex.toString()); } 

Este campo es público. Usted no necesita reflexión para leerlo.

Pero hay varios problemas en su código que causan este error:

 Class myBuildClass = android.os.Build.class; Field m1 = Build.class.getDeclaredField("MANUFACTURER"); 

Estás definiendo myBuildClass pero más tarde nunca lo utilizas. Lo mismo para el campo m1. Y después de eso su acceso directo simplemente llamando

 Build.MANUFACTURER; 

Entonces, ¿qué es todo el material de reflexión utilizado?

Si fuera privado, lo harías de la siguiente manera:

 Field manufacturer = android.os.Build.class.getDeclaredField("MANUFACTURER"); manufacturer.setAccessible(true); int myManufacturer = manufacturer.getInt(android.os.Build.class); 

Nota: manufacturer.getInt (android.os.Build.class) sólo es posible porque es un campo estático. De lo contrario, necesitará pasar un objeto real de esta clase.

Vi en tus comentarios que quieres comprobar si el campo está disponible. El campo siempre estará disponible, pero tal vez tenga valores diferentes de vez en cuando. ¿Por qué no debería estar disponible?

Ok ahora también vi en tus comentarios que quieres hacerlo por 1.6. Echa un vistazo a la documentación y verá que este campo se ha añadido en el API de nivel 1.4.

Su código puede funcionar en 1.6, pero voy a tener que mencionar que creo que es realmente innecesario y en parte también mal.

Si observa los documentos de la API, verá que Build.Manufacturer está disponible sólo desde el nivel 4 de la API. Esto significa que si ejecuta el código en un dispositivo Android de la versión API 3 o inferior, se producirá un error ya que ese campo no existe.

Desde la lectura de los comentarios a las otras preguntas, ahora entiendo mejor por qué no se puede acceder directamente al campo. Debido a que su código puede ejecutar una versión previa a la versión 4.0 de Android.

Sin embargo, no creo que sea necesario reflexionar. Qué tal si

 try { Build . MANUFACTURER ; // do stuff with Build . MANUFACTURER } catch ( AppropriateException ) { // pre version 4.0 Contingency Plan } 

¿No sería más fácil comprobar la versión del SDK en primer lugar en lugar de buscar el campo a través de la reflexión?

 if (Build.VERSION.SDK_INT >= 4) { return Build.MANUFACTURER; } else { return Build.PRODUCT; } 

@Sebi, por la presente el código completo, lo he colocado como una "respuesta" porque el código de publicación en esos comentarios es bastante ilegible

 String manufacturer; try //reflection { Field manufacturerField = android.os.Build.class.getDeclaredField("MANUFACTURER"); manufacturerField.setAccessible(true); int myManufacturer = manufacturerField.getInt(android.os.Build.class); manufacturer = Build.MANUFACTURER; } catch(Exception ex) { manufacturer = Build.PRODUCT; System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString()); } 

Esto NO funcionará en mi dispositivo 1.5. Eso es porque la línea

 manufacturer = Build.MANUFACTURER; 

Está ahí, así que si aquél se omite como en:

  try //reflection { Field manufacturerField = android.os.Build.class.getDeclaredField("MANUFACTURER"); manufacturerField.setAccessible(true); int myManufacturer = manufacturerField.getInt(android.os.Build.class); } catch(Exception ex) { manufacturer = Build.PRODUCT; System.err.println("getDeviceSpecifics, got an exception during getting Field : " + ex.toString()); } 

En realidad funcionará, el problema obviamente es que también quiero que una sola línea en mi código, por lo que en un dispositivo 1.6 puedo recuperar el fabricante = Build.MANUFACTURER;

Btw, acabo de probar todas las sugerencias en un dispositivo 1.5 y emulador 1.5 y ambos lanzan errores, la parte divertida es que incluso el código más corto dentro de una construcción try-catch todavía lanzará un

 06-02 09:26:54.741: ERROR/AndroidRuntime(782): Uncaught handler: thread main exiting due to uncaught exception 06-02 09:26:54.791: ERROR/AndroidRuntime(782): java.lang.VerifyError: mypackage.android.Reflection.reflectiontest 

He tenido un problema simular, he aquí el fragmento con el que jugué:

 try { return android.os.Build.class.getField("MANUFACTURER").get(null).toString(); } catch (Exception e) { return "???"; } 
  • Android Java objModelClass.getClass (). GetDeclaredFields () devuelve "$ change" como un campo
  • Modo de avión en Jelly Bean
  • Cargador de clases personalizado para android?
  • Android: cómo codificar dependiendo de la versión de la API?
  • Android getOnTouchListener con la versión del API> = 15
  • Cómo comprobar qué sim se establece como predeterminado en android programatically
  • ¿Cómo obtengo el nombre del método dentro de ese método?
  • Interceptar llamadas de método
  • BackupAgent compatible con versiones anteriores
  • Proguard y reflexión en Android
  • Recuperación de una lista de clases de un paquete en un proyecto de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.