diff options
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 |