aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java58
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java26
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingmin.xml23
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingusessdk.xml21
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>