Parse the manifest min/targetSdkVersion to configure the layoutlib.
This is needed to configure ApplicationInfo in the layoutlib
so that some widgets properly apply different behaviors based
on the app targetSdkVersion.
Change-Id: Ic78af4390d1b871469583f3efc0de3a9da718a6c
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
index 48d6cb4..eafc910 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
@@ -28,6 +28,7 @@
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager.IResourceListener;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarkerDelta;
@@ -64,9 +65,10 @@
public boolean layout = false;
public boolean rClass = false;
public boolean localeList = false;
+ public boolean manifest = false;
boolean isAllTrue() {
- return code && resources && rClass && localeList;
+ return code && resources && rClass && localeList && manifest;
}
}
@@ -237,6 +239,16 @@
changeFlags.code = true;
}
+ } else if (SdkConstants.FN_ANDROID_MANIFEST_XML.equals(file.getName()) &&
+ file.getParent().equals(project)) {
+ // this is a manifest change!
+ if (changeFlags == null) {
+ changeFlags = new ChangeFlags();
+ mProjectFlags.put(project, changeFlags);
+ }
+
+ changeFlags.manifest = true;
+
}
}
};
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 15d46e9..f396a71 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -67,8 +67,13 @@
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
import com.android.ide.eclipse.adt.io.IFileWrapper;
+import com.android.ide.eclipse.adt.io.IFolderWrapper;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.io.IAbstractFile;
+import com.android.sdklib.io.StreamException;
+import com.android.sdklib.xml.AndroidManifest;
+import com.android.sdklib.xml.AndroidManifestParser;
import com.android.sdkuilib.internal.widgets.ResolutionChooserDialog;
import org.eclipse.core.resources.IFile;
@@ -138,6 +143,8 @@
import java.util.Map;
import java.util.Set;
+import javax.xml.xpath.XPathExpressionException;
+
/**
* Graphical layout editor part, version 2.
* <p/>
@@ -242,6 +249,9 @@
private CustomButton mZoomFitButton;
private CustomButton mClippingButton;
+ private int mMinSdkVersion;
+ private int mTargetSdkVersion;
+
public GraphicalEditorPart(LayoutEditor layoutEditor) {
mLayoutEditor = layoutEditor;
setPartName("Graphical Layout");
@@ -1080,6 +1090,8 @@
AdtPlugin.log(e, "Can't access session property %1$s", NAME_INCLUDE);
}
}
+
+ computeSdkVersion();
}
/**
@@ -1089,6 +1101,7 @@
public void replaceFile(IFile file) {
mEditedFile = file;
mConfigComposite.replaceFile(mEditedFile);
+ computeSdkVersion();
}
/**
@@ -1642,8 +1655,8 @@
density, xdpi, ydpi,
resolver,
mProjectCallback,
- 1 /*minSdkVersion*/,
- 1 /*targetSdkVersion */,
+ mMinSdkVersion,
+ mTargetSdkVersion,
logger);
if (transparentBackground) {
@@ -1774,6 +1787,10 @@
}
}
+ if (flags.manifest) {
+ recompute |= computeSdkVersion();
+ }
+
if (recompute) {
if (mLayoutEditor.isGraphicalEditorActive()) {
recomputeLayout();
@@ -2363,4 +2380,51 @@
public FolderConfiguration getConfiguration() {
return mConfigComposite.getCurrentConfig();
}
+
+
+ /**
+ * Figures out the project's minSdkVersion and targetSdkVersion and return whether the values
+ * have changed.
+ */
+ private boolean computeSdkVersion() {
+ int oldMinSdkVersion = mMinSdkVersion;
+ int oldTargetSdkVersion = mTargetSdkVersion;
+
+ IAbstractFile manifestFile = AndroidManifestParser.getManifest(
+ new IFolderWrapper(mEditedFile.getProject()));
+
+ if (manifestFile != null) {
+ try {
+ Object value = AndroidManifest.getMinSdkVersion(manifestFile);
+ if (value instanceof Integer) {
+ mMinSdkVersion = ((Integer) value).intValue();
+ } else if (value instanceof String) {
+ // handle codename
+ IAndroidTarget target = Sdk.getCurrent().getTargetFromHashString(
+ "android-" + value); //$NON-NLS-1$
+ if (target == null) {
+ mMinSdkVersion = 1; // missing value? same as api 1
+ } else {
+ // codename future API level is current api + 1
+ mMinSdkVersion = target.getVersion().getApiLevel() + 1;
+ }
+ } else {
+ mMinSdkVersion = 1; // missing value? same as api 1
+ }
+
+ Integer i = AndroidManifest.getTargetSdkVersion(manifestFile);
+ if (i == null) {
+ mTargetSdkVersion = mMinSdkVersion;
+ } else {
+ mTargetSdkVersion = i.intValue();
+ }
+ } catch (XPathExpressionException e) {
+ // do nothing we'll use 1 below.
+ } catch (StreamException e) {
+ // do nothing we'll use 1 below.
+ }
+ }
+
+ return oldMinSdkVersion != mMinSdkVersion || oldTargetSdkVersion != mTargetSdkVersion;
+ }
}
diff --git a/files/sdk.properties b/files/sdk.properties
index efa50d9..a1affe4 100644
--- a/files/sdk.properties
+++ b/files/sdk.properties
@@ -1,4 +1,4 @@
-# SDK properties
-# This file is copied in the root folder of each platform component.
-# If it used by various tools to figure out what the platform can do.
-sdk.ant.templates.revision=1
\ No newline at end of file
+# THIS FILE IS OBSOLETE AND IS ONLY THERE TO BUILD
+# OLDER VERSION OF THE PLATFORM
+#
+# THE NEW FILE IS LOCATED IN development.git/sdk
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java
index 4012300..6ed6e49 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java
@@ -183,14 +183,20 @@
}
/**
- * Returns the value of the minSdkVersion attribute (defaults to 1 if the attribute is not set),
- * or -1 if the value is a codename.
+ * Returns the value of the minSdkVersion attribute.
+ * <p/>
+ * If the attribute is set with an int value, the method returns an Integer object.
+ * <p/>
+ * If the attribute is set with a codename, it returns the codename as a String object.
+ * <p/>
+ * If the attribute is not set, it returns null.
+ *
* @param manifestFile the manifest file to read the attribute from.
- * @return the integer value or -1 if not set.
+ * @return the attribute value.
* @throws XPathExpressionException
* @throws StreamException If any error happens when reading the manifest.
*/
- public static int getMinSdkVersion(IAbstractFile manifestFile)
+ public static Object getMinSdkVersion(IAbstractFile manifestFile)
throws XPathExpressionException, StreamException {
XPath xPath = AndroidXPathFactory.newXPath();
@@ -202,9 +208,35 @@
new InputSource(manifestFile.getContents()));
try {
- return Integer.parseInt(result);
+ return Integer.valueOf(result);
} catch (NumberFormatException e) {
- return result.length() > 0 ? -1 : 1;
+ return result.length() > 0 ? result : null;
+ }
+ }
+
+ /**
+ * Returns the value of the targetSdkVersion attribute (defaults to 1 if the attribute is
+ * not set), or -1 if the value is a codename.
+ * @param manifestFile the manifest file to read the attribute from.
+ * @return the integer value or -1 if not set.
+ * @throws XPathExpressionException
+ * @throws StreamException If any error happens when reading the manifest.
+ */
+ public static Integer getTargetSdkVersion(IAbstractFile manifestFile)
+ throws XPathExpressionException, StreamException {
+ XPath xPath = AndroidXPathFactory.newXPath();
+
+ String result = xPath.evaluate(
+ "/" + NODE_MANIFEST +
+ "/" + NODE_USES_SDK +
+ "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX +
+ ":" + ATTRIBUTE_TARGET_SDK_VERSION,
+ new InputSource(manifestFile.getContents()));
+
+ try {
+ return Integer.valueOf(result);
+ } catch (NumberFormatException e) {
+ return result.length() > 0 ? -1 : null;
}
}