diff options
5 files changed, 126 insertions, 5 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index d80dc77..ed5586d 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -95,7 +95,8 @@ public class BuiltinIssueRegistry extends IssueRegistry { issues.add(PrivateResourceDetector.ISSUE); issues.add(ArraySizeDetector.INCONSISTENT); issues.add(HardcodedDebugModeDetector.ISSUE); - issues.add(ManifestOrderDetector.ISSUE); + issues.add(ManifestOrderDetector.ORDER); + issues.add(ManifestOrderDetector.USES_SDK); issues.add(SecurityDetector.EXPORTED_SERVICE); issues.add(SecurityDetector.OPEN_PROVIDER); issues.add(SecurityDetector.WORLD_WRITEABLE); diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java index 281dccb..144a191 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java @@ -17,6 +17,9 @@ package com.android.tools.lint.checks; import static com.android.tools.lint.detector.api.LintConstants.ANDROID_MANIFEST_XML; +import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_MIN_SDK_VERSION; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_TARGET_SDK_VERSION; import static com.android.tools.lint.detector.api.LintConstants.TAG_APPLICATION; import static com.android.tools.lint.detector.api.LintConstants.TAG_USES_PERMISSION; import static com.android.tools.lint.detector.api.LintConstants.TAG_USES_SDK; @@ -25,6 +28,7 @@ import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Context; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.Speed; @@ -43,8 +47,8 @@ import java.util.EnumSet; */ public class ManifestOrderDetector extends Detector implements Detector.XmlScanner { - /** The main issue discovered by this detector */ - public static final Issue ISSUE = Issue.create( + /** Wrong order of elements in the manifest */ + public static final Issue ORDER = Issue.create( "ManifestOrder", //$NON-NLS-1$ "Checks for manifest problems like <uses-sdk> after the <application> tag", "The <application> tag should appear after the elements which declare " + @@ -59,11 +63,29 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann ManifestOrderDetector.class, EnumSet.of(Scope.MANIFEST)); + /** Missing a {@code <uses-sdk>} element */ + public static final Issue USES_SDK = Issue.create( + "UsesSdk", //$NON-NLS-1$ + "Checks that the minimum SDK and target SDK attributes are defined", + + "The manifest should contain a <uses-sdk> element which defines the " + + "minimum minimum API Level required for the application to run, " + + "as well as the target version (the highest API level you have tested " + + "the version for.)", + + Category.CORRECTNESS, + 2, + Severity.WARNING, + ManifestOrderDetector.class, + EnumSet.of(Scope.MANIFEST)).setMoreInfo( + "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"); //$NON-NLS-1$ + /** Constructs a new accessibility check */ public ManifestOrderDetector() { } private boolean mSeenApplication; + private boolean mSeenUsesSdk; @Override public Speed getSpeed() { @@ -78,6 +100,17 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann @Override public void beforeCheckFile(Context context) { mSeenApplication = false; + mSeenUsesSdk = false; + } + + @Override + public void afterCheckFile(Context context) { + if (!mSeenUsesSdk) { + context.report(USES_SDK, Location.create(context.file), + "Manifest should specify a minimum API level with " + + "<uses-sdk android:minSdkVersion=\"?\" />; if it really supports " + + "all versions of Android set it to 1.", null); + } } // ---- Implements Detector.XmlScanner ---- @@ -102,10 +135,29 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann @Override public void visitElement(XmlContext context, Element element) { String tag = element.getTagName(); + if (tag.equals(TAG_USES_SDK)) { + mSeenUsesSdk = true; + if (!element.hasAttributeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION)) { + context.report(USES_SDK, element, context.getLocation(element), + "<uses-sdk> tag should specify a minimum API level with " + + "android:minSdkVersion=\"?\"", null); + } else if (context.getProject().getMinSdk() <= 9 + && !element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) { + // Warn if not setting target SDK -- but only if the min SDK is somewhat + // old so there's some compatibility stuff kicking in (such as the menu + // button etc) + context.report(USES_SDK, element, context.getLocation(element), + "<uses-sdk> tag should specify a target API level (the " + + "highest verified version; when running on later versions, " + + "compatibility behaviors may be enabled) with " + + "android:targetSdkVersion=\"?\"", null); + } + } + if (tag.equals(TAG_APPLICATION)) { mSeenApplication = true; } else if (mSeenApplication) { - context.report(ISSUE, element, context.getLocation(element), + context.report(ORDER, element, context.getLocation(element), String.format("<%1$s> tag appears after <application> tag", tag), null); // Don't complain for *every* element following the <application> tag diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java index 1313dbc..cebf793 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java @@ -35,9 +35,33 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { public void testBrokenOrder() throws Exception { assertEquals( - "AndroidManifest.xml:16: Warning: <uses-sdk> tag appears after <application> tag", + "AndroidManifest.xml:16: Warning: <uses-sdk> tag appears after <application> " + + "tag\n" + + "AndroidManifest.xml:16: Warning: <uses-sdk> tag should specify a target API " + + "level (the highest verified version; when running on later versions, " + + "compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\"", + lintProject( "broken-manifest.xml=>AndroidManifest.xml", "res/values/strings.xml")); } + + public void testMissingUsesSdk() throws Exception { + assertEquals( + "AndroidManifest.xml: Warning: Manifest should specify a minimum API level " + + "with <uses-sdk android:minSdkVersion=\"?\" />; if it really supports all " + + "versions of Android set it to 1.", + lintProject( + "missingusessdk.xml=>AndroidManifest.xml", + "res/values/strings.xml")); + } + + public void testMissingMinSdk() throws Exception { + assertEquals( + "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a minimum API " + + "level with android:minSdkVersion=\"?\"", + lintProject( + "missingmin.xml=>AndroidManifest.xml", + "res/values/strings.xml")); + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingmin.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingmin.xml new file mode 100644 index 0000000..19b3d0a --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingmin.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="test.bytecode" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:targetSdkVersion="10" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <activity + android:name=".BytecodeTestsActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingusessdk.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingusessdk.xml new file mode 100644 index 0000000..00c0167 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingusessdk.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="test.bytecode" + android:versionCode="1" + android:versionName="1.0" > + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <activity + android:name=".BytecodeTestsActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> |