summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java48
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_selector.xml48
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_vector.xml9
-rwxr-xr-xlint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java37
4 files changed, 119 insertions, 23 deletions
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
index 60a201106f..9ae581ec09 100644
--- a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
@@ -1120,10 +1120,7 @@ public class ApiDetectorTest extends AbstractCheckTest {
+ "res/drawable/ripple.xml:1: Error: <ripple> requires API level 21 (current min is 14) [NewApi]\n"
+ "<ripple\n"
+ "^\n"
- + "res/drawable/ripple.xml:4: Warning: Attribute tintMode is only used in API level 21 and higher (current min is 14) [UnusedAttribute]\n"
- + " android:tintMode=\"src_over\"\n"
- + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- + "1 errors, 1 warnings\n",
+ + "1 errors, 0 warnings\n",
lintProject(
"apicheck/minsdk14.xml=>AndroidManifest.xml",
"apicheck/ripple.xml=>res/drawable/ripple.xml"
@@ -1150,28 +1147,41 @@ public class ApiDetectorTest extends AbstractCheckTest {
public void testVector() throws Exception {
assertEquals(""
- + "res/drawable/vector.xml:1: Error: <vector> requires API level 21 (current min is 1) [NewApi]\n"
+ + "res/drawable/vector.xml:1: Error: <vector> requires API level 21 (current min is 4) [NewApi]\n"
+ "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n"
+ "^\n"
- + "AndroidManifest.xml:8: Warning: Attribute viewportHeight is only used in API level 21 and higher (current min is 1) [UnusedAttribute]\n"
- + " android:viewportHeight=\"24\"\n"
- + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- + "AndroidManifest.xml:9: Warning: Attribute viewportWidth is only used in API level 21 and higher (current min is 1) [UnusedAttribute]\n"
- + " android:viewportWidth=\"24\" />\n"
- + " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- + "res/drawable/vector.xml:8: Warning: Attribute viewportHeight is only used in API level 21 and higher (current min is 1) [UnusedAttribute]\n"
- + " android:viewportHeight=\"24\"\n"
- + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- + "res/drawable/vector.xml:9: Warning: Attribute viewportWidth is only used in API level 21 and higher (current min is 1) [UnusedAttribute]\n"
- + " android:viewportWidth=\"24\" />\n"
- + " ~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- + "1 errors, 4 warnings\n",
+ + "1 errors, 0 warnings\n",
+
lintProject(
- "apicheck/vector.xml=>AndroidManifest.xml",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
"apicheck/vector.xml=>res/drawable/vector.xml"
));
}
+ public void testAnimatedSelector() throws Exception {
+ assertEquals(""
+ + "res/drawable/animated_selector.xml:1: Error: <animated-selector> requires API level 21 (current min is 14) [NewApi]\n"
+ + "<animated-selector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + "^\n"
+ + "1 errors, 0 warnings\n",
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "apicheck/animated_selector.xml=>res/drawable/animated_selector.xml"
+ ));
+ }
+
+ public void testAnimatedVector() throws Exception {
+ assertEquals(""
+ + "res/drawable/animated_vector.xml:1: Error: <animated-vector> requires API level 21 (current min is 14) [NewApi]\n"
+ + "<animated-vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + "^\n"
+ + "1 errors, 0 warnings\n",
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "apicheck/animated_vector.xml=>res/drawable/animated_vector.xml"
+ ));
+ }
+
public void testPaddingStart() throws Exception {
assertEquals(""
+ "res/layout/padding_start.xml:14: Error: Attribute paddingStart referenced here can result in a crash on some specific devices older than API 17 (current min is 4) [NewApi]\n"
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_selector.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_selector.xml
new file mode 100644
index 0000000000..030eba17b7
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_selector.xml
@@ -0,0 +1,48 @@
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_enabled="false" android:id="@+id/off">
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00001"
+ android:gravity="center"
+ android:tintMode="multiply"
+ android:tint="?attr/colorSwitchThumbNormal" />
+ </item>
+ <item
+ android:state_checked="true"
+ android:id="@+id/on">
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00012"
+ android:gravity="center"
+ android:tintMode="multiply"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:id="@+id/off">
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00001"
+ android:gravity="center"
+ android:tintMode="multiply"
+ android:tint="?attr/colorSwitchThumbNormal" />
+ </item>
+ <transition
+ android:fromId="@+id/off"
+ android:toId="@+id/on">
+ <animation-list>
+ <item android:duration="15">
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
+ </item>
+ <item android:duration="15">
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
+ </item>
+ </animation-list>
+ </transition>
+ <transition android:fromId="@+id/on" android:toId="@+id/off">
+ <animation-list>
+ <item android:duration="15">
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+</animated-selector>
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_vector.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_vector.xml
new file mode 100644
index 0000000000..78278c6c2b
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/animated_vector.xml
@@ -0,0 +1,9 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/vector_drawable_progress_bar_large" >
+ <target
+ android:name="progressBar"
+ android:animation="@anim/progress_indeterminate_material" />
+ <target
+ android:name="root"
+ android:animation="@anim/progress_indeterminate_rotation_material" />
+</animated-vector>
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
index 69322b358a..34551bb46f 100755
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
@@ -285,6 +285,11 @@ public class ApiDetector extends ResourceXmlDetector
private static final String ORDINAL_METHOD = "ordinal"; //$NON-NLS-1$
public static final String ENUM_SWITCH_PREFIX = "$SwitchMap$"; //$NON-NLS-1$
+ private static final String TAG_RIPPLE = "ripple";
+ private static final String TAG_VECTOR = "vector";
+ private static final String TAG_ANIMATED_VECTOR = "animated-vector";
+ private static final String TAG_ANIMATED_SELECTOR = "animated-selector";
+
protected ApiLookup mApiDatabase;
private boolean mWarnedMissingDb;
private int mMinApi = -1;
@@ -348,7 +353,8 @@ public class ApiDetector extends ResourceXmlDetector
int minSdk = getMinSdk(context);
if (attributeApiLevel > minSdk && attributeApiLevel > context.getFolderVersion()
&& attributeApiLevel > getLocalMinSdk(attribute.getOwnerElement())
- && !isBenignUnusedAttribute(name)) {
+ && !isBenignUnusedAttribute(name)
+ && !isAlreadyWarnedDrawableFile(context, attribute, attributeApiLevel)) {
if (RtlDetector.isRtlAttributeName(name)) {
// No need to warn for example that
// "layout_alignParentEnd will only be used in API level 17 and higher"
@@ -493,6 +499,28 @@ public class ApiDetector extends ResourceXmlDetector
}
/**
+ * Returns true if this attribute is in a drawable document with one of the
+ * root tags that require API 21
+ */
+ private static boolean isAlreadyWarnedDrawableFile(@NonNull XmlContext context,
+ @NonNull Attr attribute, int attributeApiLevel) {
+ // Don't complain if it's in a drawable file where we've already
+ // flagged the root drawable type as being unsupported
+ if (context.getResourceFolderType() == ResourceFolderType.DRAWABLE
+ && attributeApiLevel == 21) {
+ String root = attribute.getOwnerDocument().getDocumentElement().getTagName();
+ if (TAG_RIPPLE.equals(root)
+ || TAG_VECTOR.equals(root)
+ || TAG_ANIMATED_VECTOR.equals(root)
+ || TAG_ANIMATED_SELECTOR.equals(root)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Is the given attribute a "benign" unused attribute, one we probably don't need to
* flag to the user as not applicable on all versions? These are typically attributes
* which add some nice platform behavior when available, but that are not critical
@@ -519,9 +547,10 @@ public class ApiDetector extends ResourceXmlDetector
ResourceFolderType folderType = context.getResourceFolderType();
if (folderType != ResourceFolderType.LAYOUT) {
if (folderType == ResourceFolderType.DRAWABLE) {
- checkElement(context, element, "ripple", 21, UNSUPPORTED);
- checkElement(context, element, "vector", 21, UNSUPPORTED);
- checkElement(context, element, "animated-selector", 21, UNSUPPORTED);
+ checkElement(context, element, TAG_RIPPLE, 21, UNSUPPORTED);
+ checkElement(context, element, TAG_VECTOR, 21, UNSUPPORTED);
+ checkElement(context, element, TAG_ANIMATED_SELECTOR, 21, UNSUPPORTED);
+ checkElement(context, element, TAG_ANIMATED_VECTOR, 21, UNSUPPORTED);
}
if (element.getParentNode().getNodeType() != Node.ELEMENT_NODE) {
// Root node