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:
- Call class 'constructor por reflexión con Kotlin
- Métodos de reflexión no funcionan cuando se utiliza proguard para la aplicación de Android
- Cómo moverse repetición similar-variable en declaraciones if
- UnsuppotedOperationException.getCause se devuelve
- Android Bluetooth no puede conectarse a dispositivos médicos con puerto fijo # - ¿utilizar reflexión de Java?
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?
- ¿Debo dejar el hack de reflexión bluetooth en código de producción?
- Java Reflection - Obtener todos los nombres de variables de instancia de una clase
- Invocación de un método privado (no publicado) en la API de Android
- Java / Android Método de llamada desde cadena WITH Value
- Compruebe si el objeto tiene un método en Java?
- ¿Cómo utilizar la reflexión para cambiar el servicio de copia de seguridad?
- ¿Cómo se crea una instancia de la actividad de Android (con reflexión)?
- Acceso a campos desde un objeto proxy
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 "???"; }
- Disposición de Android, cambiar el tamaño por porcentaje y mantener la proporción
- Monitorización de startActivity en logcat