Resolución de valores de recursos en reglas personalizadas de pelusa
Tengo una base de código Android grande y estoy escribiendo una regla de pelusa personalizada que comprueba si los valores de ciertos atributos se encuentran dentro de un rango determinado.
Por ejemplo, tengo este componente:
- ¿Cómo añadir -Xlint: desmarcado a mi proyecto basado en Android Gradle?
- Los recursos no utilizados de la capa de androide del módulo de la biblioteca se utilizan en la aplicación
- ¿Por qué estoy recibiendo una advertencia sin marcar?
- Android añadiendo regla de pelusa personalizada al proyecto (git)
- Retrolambda: Lint se bloquea al usar expresiones lambda con retrolambda
<MyCustomComponent my:animation_factor="0.7" ...> </MyCustomComponent>
Y quiero escribir una regla de pelusa que avisa a los desarrolladores que los valores de my:animation_factor
> = 1 deben utilizarse con precaución.
Seguí las instrucciones en http://tools.android.com/tips/lint-custom-rules y logré recuperar el valor de my:animation_factor
usando este código:
import com.android.tools.lint.detector.api.*; public class XmlInterpolatorFactorTooHighDetector { .... @Override public Collection<String> getApplicableElements() { return ImmutableList.of("MyCustomComponent"); } @Override public void visitElement(XmlContext context, Element element) { String factor = element.getAttribute("my:animation_factor"); ... if (value.startsWith("@dimen/")) { // How do I resolve @dimen/xyz to 1.85? } else { String value = Float.parseFloat(factor); } } }
Este código funciona bien cuando atributos como my:animation_factor
tienen valores literales (por ejemplo, 0.7
).
Sin embargo, cuando el valor del atributo es un recurso (por ejemplo, @dimen/standard_anim_factor
) entonces element.getAttribute(...)
devuelve el valor de cadena del atributo en lugar del valor resuelto real.
Por ejemplo, cuando tengo un MyCustomComponent
que se parece a esto:
<MyCustomComponent my:animation_factor="@dimen/standard_anim_factory" ...> </MyCustomComponent>
Y @dimen/standard_anim_factor
se define en otra parte:
<dimen name="standard_anim_factor">1.85</dimen>
Entonces el factor
cadena se convierte en "@ dimen / standard_anim_factor" en lugar de "1.85".
¿Hay una manera de resolver "@ dimen / standard_anim_factor" al valor real del recurso (es decir, "1.85") mientras se procesa el elemento MyCustomComponent
?
- Lint falló al usar la aplicación android de gradle build
- MissingTranslation para el idioma predeterminado ("..." no está traducido en "en")
- SignedConfigs me da un error de Lint en build.gradle después de actualizar a v22
- Incapaz de construir el slidingmenu con gradle, fallando en la pelusa
- NoReadAccessException excepción al exportar errores de Lint para generar Informe HTML en Android Studio
- Contexto de lint.xml y perfil de inspección
- Comprobar los permisos de Android en un método
- Suprimir advertencia de pelusa en el nivel de vista
El problema general con la resolución de valores es que dependen del contexto de ejecución de Android en el que se encuentre. Puede haber varias carpetas de values
con diferentes valores concretos para su clave @dimen/standard_anim_factory
, de modo que usted sepa.
Sin embargo, AFAIK existen dos opciones:
-
Realice una detección de dos fases:
- Fase 1: Escanee sus recursos
- Busca tu atributo y ponlo en una lista (en lugar de evaluarlo inmediatamente)
- Analiza tus valores de dimensión y ponlos en una lista también
- Fase 2:
- Anule
Detector.afterProjectCheck
y resuelva sus atributos iterando sobre las dos listas llenadas dentro de la fase 1
-
Por lo general la clase
LintUtils
[1] es un lugar perfecto para ese material, pero por desgracia no hay ningún método que resuelve los valores de las dimensiones. Sin embargo, hay un método llamadogetStyleAttributes
que demuestra cómo resolver valores de recursos. Así que usted podría escribir su propio método conveniente para resolver valores de dimensión:
private int resolveDimensionValue(String name, Context context){ LintClient client = context.getDriver().getClient(); LintProject project = context.getDriver().getProject(); AbstractResourceRepository resources = client.getProjectResources(project, true); return Integer.valueOf(resources.getResourceItem(ResourceType.DIMEN, name).get(0).getResourceValue(false).getValue()); }
Nota: No he probado el código anterior todavía. Así que por favor verlo como un consejo teórico 🙂
Sólo un consejo más leve para su código de regla Lint personalizado, ya que sólo están interesados en el atributo:
En lugar de hacer algo como esto en visitElement
:
String factor = element.getAttribute("my:animation_factor");
… puede que desee hacer algo como esto:
@Override public Collection<String> getApplicableAttributes() { return ImmutableList.of("my:animation_factor"); } @Override void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute){ ... }
Pero es sólo una cuestión de preferencia 🙂
Creo que estás buscando buscar getResources().getDimension()
.
Fuente: http://developer.android.com/reference/android/content/res/Resources.html#getDimension%28int%29
Asumiendo que el nodo xml después de analizar sus datos, intente lo siguiente
Element element = null; //It is your root node. NamedNodeMap attrib = (NamedNodeMap) element; int numAttrs = attrib.getLength (); for (int i = 0; i < numAttrs; i++) { Attr attr = (Attr) attrib.item (i); String attrName = attr.getNodeName (); String attrValue = attr.getNodeValue (); System.out.println ("Found attribute: " + attrName + " with value: " + attrValue); }
- Cómo cargar más vistas usando un adaptador ListView
- Android2.x: Código de error de MediaPlayer (1, -19)