diff options
Diffstat (limited to 'sdk_common/src/com/android/ide/common/xml')
-rw-r--r-- | sdk_common/src/com/android/ide/common/xml/AndroidManifestParser.java | 672 | ||||
-rw-r--r-- | sdk_common/src/com/android/ide/common/xml/ManifestData.java | 747 |
2 files changed, 0 insertions, 1419 deletions
diff --git a/sdk_common/src/com/android/ide/common/xml/AndroidManifestParser.java b/sdk_common/src/com/android/ide/common/xml/AndroidManifestParser.java deleted file mode 100644 index 7fde6ce..0000000 --- a/sdk_common/src/com/android/ide/common/xml/AndroidManifestParser.java +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.common.xml; - -import com.android.SdkConstants; -import com.android.ide.common.xml.ManifestData.Activity; -import com.android.ide.common.xml.ManifestData.Instrumentation; -import com.android.ide.common.xml.ManifestData.SupportsScreens; -import com.android.ide.common.xml.ManifestData.UsesConfiguration; -import com.android.ide.common.xml.ManifestData.UsesFeature; -import com.android.ide.common.xml.ManifestData.UsesLibrary; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.io.StreamException; -import com.android.resources.Keyboard; -import com.android.resources.Navigation; -import com.android.resources.TouchScreen; -import com.android.xml.AndroidManifest; - -import org.xml.sax.Attributes; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -public class AndroidManifestParser { - - private final static int LEVEL_TOP = 0; - private final static int LEVEL_INSIDE_MANIFEST = 1; - private final static int LEVEL_INSIDE_APPLICATION = 2; - private final static int LEVEL_INSIDE_APP_COMPONENT = 3; - private final static int LEVEL_INSIDE_INTENT_FILTER = 4; - - private final static String ACTION_MAIN = "android.intent.action.MAIN"; //$NON-NLS-1$ - private final static String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; //$NON-NLS-1$ - - public interface ManifestErrorHandler extends ErrorHandler { - /** - * Handles a parsing error and an optional line number. - */ - void handleError(Exception exception, int lineNumber); - - /** - * Checks that a class is valid and can be used in the Android Manifest. - * <p/> - * Errors are put as {@code org.eclipse.core.resources.IMarker} on the manifest file. - * - * @param locator - * @param className the fully qualified name of the class to test. - * @param superClassName the fully qualified name of the class it is supposed to extend. - * @param testVisibility if <code>true</code>, the method will check the visibility of - * the class or of its constructors. - */ - void checkClass(Locator locator, String className, String superClassName, - boolean testVisibility); - } - - /** - * XML error & data handler used when parsing the AndroidManifest.xml file. - * <p/> - * During parsing this will fill up the {@link ManifestData} object given to the constructor - * and call out errors to the given {@link ManifestErrorHandler}. - */ - private static class ManifestHandler extends DefaultHandler { - - //--- temporary data/flags used during parsing - private final ManifestData mManifestData; - private final ManifestErrorHandler mErrorHandler; - private int mCurrentLevel = 0; - private int mValidLevel = 0; - private Activity mCurrentActivity = null; - private Locator mLocator; - - /** - * Creates a new {@link ManifestHandler}. - * - * @param manifestFile The manifest file being parsed. Can be null. - * @param manifestData Class containing the manifest info obtained during the parsing. - * @param errorHandler An optional error handler. - */ - ManifestHandler(IAbstractFile manifestFile, ManifestData manifestData, - ManifestErrorHandler errorHandler) { - super(); - mManifestData = manifestData; - mErrorHandler = errorHandler; - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator) - */ - @Override - public void setDocumentLocator(Locator locator) { - mLocator = locator; - super.setDocumentLocator(locator); - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, - * java.lang.String, org.xml.sax.Attributes) - */ - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) - throws SAXException { - try { - if (mManifestData == null) { - return; - } - - // if we're at a valid level - if (mValidLevel == mCurrentLevel) { - String value; - switch (mValidLevel) { - case LEVEL_TOP: - if (AndroidManifest.NODE_MANIFEST.equals(localName)) { - // lets get the package name. - mManifestData.mPackage = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_PACKAGE, - false /* hasNamespace */); - - // and the versionCode - String tmp = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_VERSIONCODE, true); - if (tmp != null) { - try { - mManifestData.mVersionCode = Integer.valueOf(tmp); - } catch (NumberFormatException e) { - // keep null in the field. - } - } - mValidLevel++; - } - break; - case LEVEL_INSIDE_MANIFEST: - if (AndroidManifest.NODE_APPLICATION.equals(localName)) { - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (value != null) { - mManifestData.addProcessName(value); - } - - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_DEBUGGABLE, - true /* hasNamespace*/); - if (value != null) { - mManifestData.mDebuggable = Boolean.parseBoolean(value); - } - - mValidLevel++; - } else if (AndroidManifest.NODE_USES_SDK.equals(localName)) { - mManifestData.setMinSdkVersionString(getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION, - true /* hasNamespace */)); - mManifestData.setTargetSdkVersionString(getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_TARGET_SDK_VERSION, - true /* hasNamespace */)); - } else if (AndroidManifest.NODE_INSTRUMENTATION.equals(localName)) { - processInstrumentationNode(attributes); - - } else if (AndroidManifest.NODE_SUPPORTS_SCREENS.equals(localName)) { - processSupportsScreensNode(attributes); - - } else if (AndroidManifest.NODE_USES_CONFIGURATION.equals(localName)) { - processUsesConfiguration(attributes); - - } else if (AndroidManifest.NODE_USES_FEATURE.equals(localName)) { - UsesFeature feature = new UsesFeature(); - - // get the name - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (value != null) { - feature.mName = value; - } - - // read the required attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQUIRED, - true /*hasNamespace*/); - if (value != null) { - Boolean b = Boolean.valueOf(value); - if (b != null) { - feature.mRequired = b; - } - } - - // read the gl es attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_GLESVERSION, - true /*hasNamespace*/); - if (value != null) { - try { - int version = Integer.decode(value); - feature.mGlEsVersion = version; - } catch (NumberFormatException e) { - // ignore - } - - } - - mManifestData.mFeatures.add(feature); - } - break; - case LEVEL_INSIDE_APPLICATION: - if (AndroidManifest.NODE_ACTIVITY.equals(localName) - || AndroidManifest.NODE_ACTIVITY_ALIAS.equals(localName)) { - processActivityNode(attributes); - mValidLevel++; - } else if (AndroidManifest.NODE_SERVICE.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_SERVICE); - mValidLevel++; - } else if (AndroidManifest.NODE_RECEIVER.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_BROADCASTRECEIVER); - mValidLevel++; - } else if (AndroidManifest.NODE_PROVIDER.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_CONTENTPROVIDER); - mValidLevel++; - } else if (AndroidManifest.NODE_USES_LIBRARY.equals(localName)) { - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (value != null) { - UsesLibrary library = new UsesLibrary(); - library.mName = value; - - // read the required attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQUIRED, - true /*hasNamespace*/); - if (value != null) { - Boolean b = Boolean.valueOf(value); - if (b != null) { - library.mRequired = b; - } - } - - mManifestData.mLibraries.add(library); - } - } - break; - case LEVEL_INSIDE_APP_COMPONENT: - // only process this level if we are in an activity - if (mCurrentActivity != null && - AndroidManifest.NODE_INTENT.equals(localName)) { - mCurrentActivity.resetIntentFilter(); - mValidLevel++; - } - break; - case LEVEL_INSIDE_INTENT_FILTER: - if (mCurrentActivity != null) { - if (AndroidManifest.NODE_ACTION.equals(localName)) { - // get the name attribute - String action = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (action != null) { - mCurrentActivity.setHasAction(true); - mCurrentActivity.setHasMainAction( - ACTION_MAIN.equals(action)); - } - } else if (AndroidManifest.NODE_CATEGORY.equals(localName)) { - String category = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (CATEGORY_LAUNCHER.equals(category)) { - mCurrentActivity.setHasLauncherCategory(true); - } - } - - // no need to increase mValidLevel as we don't process anything - // below this level. - } - break; - } - } - - mCurrentLevel++; - } finally { - super.startElement(uri, localName, name, attributes); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, - * java.lang.String) - */ - @Override - public void endElement(String uri, String localName, String name) throws SAXException { - try { - if (mManifestData == null) { - return; - } - - // decrement the levels. - if (mValidLevel == mCurrentLevel) { - mValidLevel--; - } - mCurrentLevel--; - - // if we're at a valid level - // process the end of the element - if (mValidLevel == mCurrentLevel) { - switch (mValidLevel) { - case LEVEL_INSIDE_APPLICATION: - mCurrentActivity = null; - break; - case LEVEL_INSIDE_APP_COMPONENT: - // if we found both a main action and a launcher category, this is our - // launcher activity! - if (mManifestData.mLauncherActivity == null && - mCurrentActivity != null && - mCurrentActivity.isHomeActivity() && - mCurrentActivity.isExported()) { - mManifestData.mLauncherActivity = mCurrentActivity; - } - break; - default: - break; - } - - } - } finally { - super.endElement(uri, localName, name); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException) - */ - @Override - public void error(SAXParseException e) { - if (mErrorHandler != null) { - mErrorHandler.handleError(e, e.getLineNumber()); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException) - */ - @Override - public void fatalError(SAXParseException e) { - if (mErrorHandler != null) { - mErrorHandler.handleError(e, e.getLineNumber()); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException) - */ - @Override - public void warning(SAXParseException e) throws SAXException { - if (mErrorHandler != null) { - mErrorHandler.warning(e); - } - } - - /** - * Processes the activity node. - * @param attributes the attributes for the activity node. - */ - private void processActivityNode(Attributes attributes) { - // lets get the activity name, and add it to the list - String activityName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (activityName != null) { - activityName = AndroidManifest.combinePackageAndClassName(mManifestData.mPackage, - activityName); - - // get the exported flag. - String exportedStr = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_EXPORTED, true); - boolean exported = exportedStr == null || - exportedStr.toLowerCase(Locale.US).equals("true"); //$NON-NLS-1$ - mCurrentActivity = new Activity(activityName, exported); - mManifestData.mActivities.add(mCurrentActivity); - - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, activityName, SdkConstants.CLASS_ACTIVITY, - true /* testVisibility */); - } - } else { - // no activity found! Aapt will output an error, - // so we don't have to do anything - mCurrentActivity = null; - } - - String processName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (processName != null) { - mManifestData.addProcessName(processName); - } - } - - /** - * Processes the service/receiver/provider nodes. - * @param attributes the attributes for the activity node. - * @param superClassName the fully qualified name of the super class that this - * node is representing - */ - private void processNode(Attributes attributes, String superClassName) { - // lets get the class name, and check it if required. - String serviceName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (serviceName != null) { - serviceName = AndroidManifest.combinePackageAndClassName(mManifestData.mPackage, - serviceName); - - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, serviceName, superClassName, - false /* testVisibility */); - } - } - - String processName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (processName != null) { - mManifestData.addProcessName(processName); - } - } - - /** - * Processes the instrumentation node. - * @param attributes the attributes for the instrumentation node. - */ - private void processInstrumentationNode(Attributes attributes) { - // lets get the class name, and check it if required. - String instrumentationName = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (instrumentationName != null) { - String instrClassName = AndroidManifest.combinePackageAndClassName( - mManifestData.mPackage, instrumentationName); - String targetPackage = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_TARGET_PACKAGE, - true /* hasNamespace */); - mManifestData.mInstrumentations.add( - new Instrumentation(instrClassName, targetPackage)); - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, instrClassName, - SdkConstants.CLASS_INSTRUMENTATION, true /* testVisibility */); - } - } - } - - /** - * Processes the supports-screens node. - * @param attributes the attributes for the supports-screens node. - */ - private void processSupportsScreensNode(Attributes attributes) { - mManifestData.mSupportsScreensFromManifest = new SupportsScreens(); - - mManifestData.mSupportsScreensFromManifest.setResizeable(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_RESIZEABLE, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setAnyDensity(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_ANYDENSITY, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setSmallScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_SMALLSCREENS, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setNormalScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_NORMALSCREENS, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setLargeScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_LARGESCREENS, true /*hasNamespace*/)); - } - - /** - * Processes the supports-screens node. - * @param attributes the attributes for the supports-screens node. - */ - private void processUsesConfiguration(Attributes attributes) { - mManifestData.mUsesConfiguration = new UsesConfiguration(); - - mManifestData.mUsesConfiguration.mReqFiveWayNav = getAttributeBooleanValue( - attributes, - AndroidManifest.ATTRIBUTE_REQ_5WAYNAV, true /*hasNamespace*/); - mManifestData.mUsesConfiguration.mReqNavigation = Navigation.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_NAVIGATION, true /*hasNamespace*/)); - mManifestData.mUsesConfiguration.mReqHardKeyboard = getAttributeBooleanValue( - attributes, - AndroidManifest.ATTRIBUTE_REQ_HARDKEYBOARD, true /*hasNamespace*/); - mManifestData.mUsesConfiguration.mReqKeyboardType = Keyboard.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_KEYBOARDTYPE, true /*hasNamespace*/)); - mManifestData.mUsesConfiguration.mReqTouchScreen = TouchScreen.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_TOUCHSCREEN, true /*hasNamespace*/)); - } - - /** - * Searches through the attributes list for a particular one and returns its value. - * @param attributes the attribute list to search through - * @param attributeName the name of the attribute to look for. - * @param hasNamespace Indicates whether the attribute has an android namespace. - * @return a String with the value or null if the attribute was not found. - * @see SdkConstants#NS_RESOURCES - */ - private String getAttributeValue(Attributes attributes, String attributeName, - boolean hasNamespace) { - int count = attributes.getLength(); - for (int i = 0 ; i < count ; i++) { - if (attributeName.equals(attributes.getLocalName(i)) && - ((hasNamespace && - SdkConstants.NS_RESOURCES.equals(attributes.getURI(i))) || - (hasNamespace == false && attributes.getURI(i).length() == 0))) { - return attributes.getValue(i); - } - } - - return null; - } - - /** - * Searches through the attributes list for a particular one and returns its value as a - * Boolean. If the attribute is not present, this will return null. - * @param attributes the attribute list to search through - * @param attributeName the name of the attribute to look for. - * @param hasNamespace Indicates whether the attribute has an android namespace. - * @return a String with the value or null if the attribute was not found. - * @see SdkConstants#NS_RESOURCES - */ - private Boolean getAttributeBooleanValue(Attributes attributes, String attributeName, - boolean hasNamespace) { - int count = attributes.getLength(); - for (int i = 0 ; i < count ; i++) { - if (attributeName.equals(attributes.getLocalName(i)) && - ((hasNamespace && - SdkConstants.NS_RESOURCES.equals(attributes.getURI(i))) || - (hasNamespace == false && attributes.getURI(i).length() == 0))) { - String attr = attributes.getValue(i); - if (attr != null) { - return Boolean.valueOf(attr); - } else { - return null; - } - } - } - - return null; - } - - } - - private final static SAXParserFactory sParserFactory; - - static { - sParserFactory = SAXParserFactory.newInstance(); - sParserFactory.setNamespaceAware(true); - } - - /** - * Parses the Android Manifest, and returns a {@link ManifestData} object containing the - * result of the parsing. - * - * @param manifestFile the {@link IAbstractFile} representing the manifest file. - * @param gatherData indicates whether the parsing will extract data from the manifest. If false - * the method will always return null. - * @param errorHandler an optional errorHandler. - * @return A class containing the manifest info obtained during the parsing, or null on error. - * - * @throws StreamException - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - public static ManifestData parse( - IAbstractFile manifestFile, - boolean gatherData, - ManifestErrorHandler errorHandler) - throws SAXException, IOException, StreamException, ParserConfigurationException { - if (manifestFile != null) { - SAXParser parser = sParserFactory.newSAXParser(); - - ManifestData data = null; - if (gatherData) { - data = new ManifestData(); - } - - ManifestHandler manifestHandler = new ManifestHandler(manifestFile, - data, errorHandler); - parser.parse(new InputSource(manifestFile.getContents()), manifestHandler); - - return data; - } - - return null; - } - - /** - * Parses the Android Manifest, and returns an object containing the result of the parsing. - * - * <p/> - * This is the equivalent of calling <pre>parse(manifestFile, true, null)</pre> - * - * @param manifestFile the manifest file to parse. - * - * @throws ParserConfigurationException - * @throws StreamException - * @throws IOException - * @throws SAXException - */ - public static ManifestData parse(IAbstractFile manifestFile) - throws SAXException, IOException, StreamException, ParserConfigurationException { - return parse(manifestFile, true, null); - } - - public static ManifestData parse(IAbstractFolder projectFolder) - throws SAXException, IOException, StreamException, ParserConfigurationException { - IAbstractFile manifestFile = AndroidManifest.getManifest(projectFolder); - if (manifestFile == null) { - throw new FileNotFoundException(); - } - - return parse(manifestFile, true, null); - } - - /** - * Parses the Android Manifest from an {@link InputStream}, and returns a {@link ManifestData} - * object containing the result of the parsing. - * - * @param manifestFileStream the {@link InputStream} representing the manifest file. - * @return A class containing the manifest info obtained during the parsing or null on error. - * - * @throws StreamException - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - public static ManifestData parse(InputStream manifestFileStream) - throws SAXException, IOException, StreamException, ParserConfigurationException { - if (manifestFileStream != null) { - SAXParser parser = sParserFactory.newSAXParser(); - - ManifestData data = new ManifestData(); - - ManifestHandler manifestHandler = new ManifestHandler(null, data, null); - parser.parse(new InputSource(manifestFileStream), manifestHandler); - - return data; - } - - return null; - } -} diff --git a/sdk_common/src/com/android/ide/common/xml/ManifestData.java b/sdk_common/src/com/android/ide/common/xml/ManifestData.java deleted file mode 100644 index 9b68d60..0000000 --- a/sdk_common/src/com/android/ide/common/xml/ManifestData.java +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.common.xml; - -import com.android.resources.Keyboard; -import com.android.resources.Navigation; -import com.android.resources.TouchScreen; - -import java.util.ArrayList; -import java.util.Set; -import java.util.TreeSet; - -/** - * Class containing the manifest info obtained during the parsing. - */ -public final class ManifestData { - - /** - * Value returned by {@link #getMinSdkVersion()} when the value of the minSdkVersion attribute - * in the manifest is a codename and not an integer value. - */ - public final static int MIN_SDK_CODENAME = 0; - - /** - * Value returned by {@link #getGlEsVersion()} when there are no <uses-feature> node with the - * attribute glEsVersion set. - */ - public final static int GL_ES_VERSION_NOT_SET = -1; - - /** Application package */ - String mPackage; - /** Application version Code, null if the attribute is not present. */ - Integer mVersionCode = null; - /** List of all activities */ - final ArrayList<Activity> mActivities = new ArrayList<Activity>(); - /** Launcher activity */ - Activity mLauncherActivity = null; - /** list of process names declared by the manifest */ - Set<String> mProcesses = null; - /** debuggable attribute value. If null, the attribute is not present. */ - Boolean mDebuggable = null; - /** API level requirement. if null the attribute was not present. */ - private String mMinSdkVersionString = null; - /** API level requirement. Default is 1 even if missing. If value is a codename, then it'll be - * 0 instead. */ - private int mMinSdkVersion = 1; - private int mTargetSdkVersion = 0; - /** List of all instrumentations declared by the manifest */ - final ArrayList<Instrumentation> mInstrumentations = - new ArrayList<Instrumentation>(); - /** List of all libraries in use declared by the manifest */ - final ArrayList<UsesLibrary> mLibraries = new ArrayList<UsesLibrary>(); - /** List of all feature in use declared by the manifest */ - final ArrayList<UsesFeature> mFeatures = new ArrayList<UsesFeature>(); - - SupportsScreens mSupportsScreensFromManifest; - SupportsScreens mSupportsScreensValues; - UsesConfiguration mUsesConfiguration; - - /** - * Instrumentation info obtained from manifest - */ - public final static class Instrumentation { - private final String mName; - private final String mTargetPackage; - - Instrumentation(String name, String targetPackage) { - mName = name; - mTargetPackage = targetPackage; - } - - /** - * Returns the fully qualified instrumentation class name - */ - public String getName() { - return mName; - } - - /** - * Returns the Android app package that is the target of this instrumentation - */ - public String getTargetPackage() { - return mTargetPackage; - } - } - - /** - * Activity info obtained from the manifest. - */ - public final static class Activity { - private final String mName; - private final boolean mIsExported; - private boolean mHasAction = false; - private boolean mHasMainAction = false; - private boolean mHasLauncherCategory = false; - - public Activity(String name, boolean exported) { - mName = name; - mIsExported = exported; - } - - public String getName() { - return mName; - } - - public boolean isExported() { - return mIsExported; - } - - public boolean hasAction() { - return mHasAction; - } - - public boolean isHomeActivity() { - return mHasMainAction && mHasLauncherCategory; - } - - void setHasAction(boolean hasAction) { - mHasAction = hasAction; - } - - /** If the activity doesn't yet have a filter set for the launcher, this resets both - * flags. This is to handle multiple intent-filters where one could have the valid - * action, and another one of the valid category. - */ - void resetIntentFilter() { - if (isHomeActivity() == false) { - mHasMainAction = mHasLauncherCategory = false; - } - } - - void setHasMainAction(boolean hasMainAction) { - mHasMainAction = hasMainAction; - } - - void setHasLauncherCategory(boolean hasLauncherCategory) { - mHasLauncherCategory = hasLauncherCategory; - } - } - - /** - * Class representing the <code>supports-screens</code> node in the manifest. - * By default, all the getters will return null if there was no value defined in the manifest. - * - * To get an instance with all the actual values, use {@link #resolveSupportsScreensValues(int)} - */ - public final static class SupportsScreens { - private Boolean mResizeable; - private Boolean mAnyDensity; - private Boolean mSmallScreens; - private Boolean mNormalScreens; - private Boolean mLargeScreens; - - public SupportsScreens() { - } - - /** - * Instantiate an instance from a string. The string must have been created with - * {@link #getEncodedValues()}. - * @param value the string. - */ - public SupportsScreens(String value) { - String[] values = value.split("\\|"); - - mAnyDensity = Boolean.valueOf(values[0]); - mResizeable = Boolean.valueOf(values[1]); - mSmallScreens = Boolean.valueOf(values[2]); - mNormalScreens = Boolean.valueOf(values[3]); - mLargeScreens = Boolean.valueOf(values[4]); - } - - /** - * Returns an instance of {@link SupportsScreens} initialized with the default values - * based on the given targetSdkVersion. - * @param targetSdkVersion - */ - public static SupportsScreens getDefaultValues(int targetSdkVersion) { - SupportsScreens result = new SupportsScreens(); - - result.mNormalScreens = Boolean.TRUE; - // Screen size and density became available in Android 1.5/API3, so before that - // non normal screens were not supported by default. After they are considered - // supported. - result.mResizeable = result.mAnyDensity = result.mSmallScreens = result.mLargeScreens = - targetSdkVersion <= 3 ? Boolean.FALSE : Boolean.TRUE; - - return result; - } - - /** - * Returns a version of the receiver for which all values have been set, even if they - * were not present in the manifest. - * @param targetSdkVersion the target api level of the app, since this has an effect - * on default values. - */ - public SupportsScreens resolveSupportsScreensValues(int targetSdkVersion) { - SupportsScreens result = getDefaultValues(targetSdkVersion); - - // Override the default with the existing values: - if (mResizeable != null) result.mResizeable = mResizeable; - if (mAnyDensity != null) result.mAnyDensity = mAnyDensity; - if (mSmallScreens != null) result.mSmallScreens = mSmallScreens; - if (mNormalScreens != null) result.mNormalScreens = mNormalScreens; - if (mLargeScreens != null) result.mLargeScreens = mLargeScreens; - - return result; - } - - /** - * returns the value of the <code>resizeable</code> attribute or null if not present. - */ - public Boolean getResizeable() { - return mResizeable; - } - - void setResizeable(Boolean resizeable) { - mResizeable = getConstantBoolean(resizeable); - } - - /** - * returns the value of the <code>anyDensity</code> attribute or null if not present. - */ - public Boolean getAnyDensity() { - return mAnyDensity; - } - - void setAnyDensity(Boolean anyDensity) { - mAnyDensity = getConstantBoolean(anyDensity); - } - - /** - * returns the value of the <code>smallScreens</code> attribute or null if not present. - */ - public Boolean getSmallScreens() { - return mSmallScreens; - } - - void setSmallScreens(Boolean smallScreens) { - mSmallScreens = getConstantBoolean(smallScreens); - } - - /** - * returns the value of the <code>normalScreens</code> attribute or null if not present. - */ - public Boolean getNormalScreens() { - return mNormalScreens; - } - - void setNormalScreens(Boolean normalScreens) { - mNormalScreens = getConstantBoolean(normalScreens); - } - - /** - * returns the value of the <code>largeScreens</code> attribute or null if not present. - */ - public Boolean getLargeScreens() { - return mLargeScreens; - } - - void setLargeScreens(Boolean largeScreens) { - mLargeScreens = getConstantBoolean(largeScreens); - } - - /** - * Returns either {@link Boolean#TRUE} or {@link Boolean#FALSE} based on the value of - * the given Boolean object. - */ - private Boolean getConstantBoolean(Boolean v) { - if (v != null) { - if (v.equals(Boolean.TRUE)) { - return Boolean.TRUE; - } else { - return Boolean.FALSE; - } - } - - return null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof SupportsScreens) { - SupportsScreens support = (SupportsScreens) obj; - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - return mResizeable == support.mResizeable && - mAnyDensity == support.mAnyDensity && - mSmallScreens == support.mSmallScreens && - mNormalScreens == support.mNormalScreens && - mLargeScreens == support.mLargeScreens; - } - - return false; - } - - /* Override hashCode, mostly to make Eclipse happy and not warn about it. - * And if you ever put this in a Map or Set, it will avoid surprises. */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mAnyDensity == null) ? 0 : mAnyDensity.hashCode()); - result = prime * result + ((mLargeScreens == null) ? 0 : mLargeScreens.hashCode()); - result = prime * result + ((mNormalScreens == null) ? 0 : mNormalScreens.hashCode()); - result = prime * result + ((mResizeable == null) ? 0 : mResizeable.hashCode()); - result = prime * result + ((mSmallScreens == null) ? 0 : mSmallScreens.hashCode()); - return result; - } - - /** - * Returns true if the two instances support the same screen sizes. - * This is similar to {@link #equals(Object)} except that it ignores the values of - * {@link #getAnyDensity()} and {@link #getResizeable()}. - * @param support the other instance to compare to. - * @return true if the two instances support the same screen sizes. - */ - public boolean hasSameScreenSupportAs(SupportsScreens support) { - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - - // This only checks that matter here are the screen sizes. resizeable and anyDensity - // are not checked. - return mSmallScreens == support.mSmallScreens && - mNormalScreens == support.mNormalScreens && - mLargeScreens == support.mLargeScreens; - } - - /** - * Returns true if the two instances have strictly different screen size support. - * This means that there is no screen size that they both support. - * @param support the other instance to compare to. - * @return true if they are stricly different. - */ - public boolean hasStrictlyDifferentScreenSupportAs(SupportsScreens support) { - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - - // This only checks that matter here are the screen sizes. resizeable and anyDensity - // are not checked. - return (mSmallScreens != Boolean.TRUE || support.mSmallScreens != Boolean.TRUE) && - (mNormalScreens != Boolean.TRUE || support.mNormalScreens != Boolean.TRUE) && - (mLargeScreens != Boolean.TRUE || support.mLargeScreens != Boolean.TRUE); - } - - /** - * Comparison of 2 Supports-screens. This only uses screen sizes (ignores resizeable and - * anyDensity), and considers that - * {@link #hasStrictlyDifferentScreenSupportAs(SupportsScreens)} returns true and - * {@link #overlapWith(SupportsScreens)} returns false. - * @throws IllegalArgumentException if the two instanced are not strictly different or - * overlap each other - * @see #hasStrictlyDifferentScreenSupportAs(SupportsScreens) - * @see #overlapWith(SupportsScreens) - */ - public int compareScreenSizesWith(SupportsScreens o) { - if (hasStrictlyDifferentScreenSupportAs(o) == false) { - throw new IllegalArgumentException("The two instances are not strictly different."); - } - if (overlapWith(o)) { - throw new IllegalArgumentException("The two instances overlap each other."); - } - - int comp = mLargeScreens.compareTo(o.mLargeScreens); - if (comp != 0) return comp; - - comp = mNormalScreens.compareTo(o.mNormalScreens); - if (comp != 0) return comp; - - comp = mSmallScreens.compareTo(o.mSmallScreens); - if (comp != 0) return comp; - - return 0; - } - - /** - * Returns a string encoding of the content of the instance. This string can be used to - * instantiate a {@link SupportsScreens} object through - * {@link #SupportsScreens(String)}. - */ - public String getEncodedValues() { - return String.format("%1$s|%2$s|%3$s|%4$s|%5$s", - mAnyDensity, mResizeable, mSmallScreens, mNormalScreens, mLargeScreens); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - boolean alreadyOutputSomething = false; - - if (Boolean.TRUE.equals(mSmallScreens)) { - alreadyOutputSomething = true; - sb.append("small"); - } - - if (Boolean.TRUE.equals(mNormalScreens)) { - if (alreadyOutputSomething) { - sb.append(", "); - } - alreadyOutputSomething = true; - sb.append("normal"); - } - - if (Boolean.TRUE.equals(mLargeScreens)) { - if (alreadyOutputSomething) { - sb.append(", "); - } - alreadyOutputSomething = true; - sb.append("large"); - } - - if (alreadyOutputSomething == false) { - sb.append("<none>"); - } - - return sb.toString(); - } - - /** - * Returns true if the two instance overlap with each other. - * This can happen if one instances supports a size, when the other instance doesn't while - * supporting a size above and a size below. - * @param otherSS the other supports-screens to compare to. - */ - public boolean overlapWith(SupportsScreens otherSS) { - if (mSmallScreens == null || mNormalScreens == null || mLargeScreens == null || - otherSS.mSmallScreens == null || otherSS.mNormalScreens == null || - otherSS.mLargeScreens == null) { - throw new IllegalArgumentException("Some screen sizes Boolean are not initialized"); - } - - if (mSmallScreens == Boolean.TRUE && mNormalScreens == Boolean.FALSE && - mLargeScreens == Boolean.TRUE) { - return otherSS.mNormalScreens == Boolean.TRUE; - } - - if (otherSS.mSmallScreens == Boolean.TRUE && otherSS.mNormalScreens == Boolean.FALSE && - otherSS.mLargeScreens == Boolean.TRUE) { - return mNormalScreens == Boolean.TRUE; - } - - return false; - } - } - - /** - * Class representing a <code>uses-library</code> node in the manifest. - */ - public final static class UsesLibrary { - String mName; - Boolean mRequired = Boolean.TRUE; // default is true even if missing - - public String getName() { - return mName; - } - - public Boolean getRequired() { - return mRequired; - } - } - - /** - * Class representing a <code>uses-feature</code> node in the manifest. - */ - public final static class UsesFeature { - String mName; - int mGlEsVersion = 0; - Boolean mRequired = Boolean.TRUE; // default is true even if missing - - public String getName() { - return mName; - } - - /** - * Returns the value of the glEsVersion attribute, or 0 if the attribute was not present. - */ - public int getGlEsVersion() { - return mGlEsVersion; - } - - public Boolean getRequired() { - return mRequired; - } - } - - /** - * Class representing the <code>uses-configuration</code> node in the manifest. - */ - public final static class UsesConfiguration { - Boolean mReqFiveWayNav; - Boolean mReqHardKeyboard; - Keyboard mReqKeyboardType; - TouchScreen mReqTouchScreen; - Navigation mReqNavigation; - - /** - * returns the value of the <code>reqFiveWayNav</code> attribute or null if not present. - */ - public Boolean getReqFiveWayNav() { - return mReqFiveWayNav; - } - - /** - * returns the value of the <code>reqNavigation</code> attribute or null if not present. - */ - public Navigation getReqNavigation() { - return mReqNavigation; - } - - /** - * returns the value of the <code>reqHardKeyboard</code> attribute or null if not present. - */ - public Boolean getReqHardKeyboard() { - return mReqHardKeyboard; - } - - /** - * returns the value of the <code>reqKeyboardType</code> attribute or null if not present. - */ - public Keyboard getReqKeyboardType() { - return mReqKeyboardType; - } - - /** - * returns the value of the <code>reqTouchScreen</code> attribute or null if not present. - */ - public TouchScreen getReqTouchScreen() { - return mReqTouchScreen; - } - } - - /** - * Returns the package defined in the manifest, if found. - * @return The package name or null if not found. - */ - public String getPackage() { - return mPackage; - } - - /** - * Returns the versionCode value defined in the manifest, if found, null otherwise. - * @return the versionCode or null if not found. - */ - public Integer getVersionCode() { - return mVersionCode; - } - - /** - * Returns the list of activities found in the manifest. - * @return An array of fully qualified class names, or empty if no activity were found. - */ - public Activity[] getActivities() { - return mActivities.toArray(new Activity[mActivities.size()]); - } - - /** - * Returns the name of one activity found in the manifest, that is configured to show - * up in the HOME screen. - * @return the fully qualified name of a HOME activity or null if none were found. - */ - public Activity getLauncherActivity() { - return mLauncherActivity; - } - - /** - * Returns the list of process names declared by the manifest. - */ - public String[] getProcesses() { - if (mProcesses != null) { - return mProcesses.toArray(new String[mProcesses.size()]); - } - - return new String[0]; - } - - /** - * Returns the <code>debuggable</code> attribute value or null if it is not set. - */ - public Boolean getDebuggable() { - return mDebuggable; - } - - /** - * Returns the <code>minSdkVersion</code> attribute, or null if it's not set. - */ - public String getMinSdkVersionString() { - return mMinSdkVersionString; - } - - /** - * Sets the value of the <code>minSdkVersion</code> attribute. - * @param minSdkVersion the string value of the attribute in the manifest. - */ - public void setMinSdkVersionString(String minSdkVersion) { - mMinSdkVersionString = minSdkVersion; - if (mMinSdkVersionString != null) { - try { - mMinSdkVersion = Integer.parseInt(mMinSdkVersionString); - } catch (NumberFormatException e) { - mMinSdkVersion = MIN_SDK_CODENAME; - } - } - } - - /** - * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set or is a codename. - * @see #getMinSdkVersionString() - */ - public int getMinSdkVersion() { - return mMinSdkVersion; - } - - - /** - * Sets the value of the <code>minSdkVersion</code> attribute. - * @param targetSdkVersion the string value of the attribute in the manifest. - */ - public void setTargetSdkVersionString(String targetSdkVersion) { - if (targetSdkVersion != null) { - try { - mTargetSdkVersion = Integer.parseInt(targetSdkVersion); - } catch (NumberFormatException e) { - // keep the value at 0. - } - } - } - - /** - * Returns the <code>targetSdkVersion</code> attribute, or the same value as - * {@link #getMinSdkVersion()} if it was not set in the manifest. - */ - public int getTargetSdkVersion() { - if (mTargetSdkVersion == 0) { - return getMinSdkVersion(); - } - - return mTargetSdkVersion; - } - - /** - * Returns the list of instrumentations found in the manifest. - * @return An array of {@link Instrumentation}, or empty if no instrumentations were - * found. - */ - public Instrumentation[] getInstrumentations() { - return mInstrumentations.toArray(new Instrumentation[mInstrumentations.size()]); - } - - /** - * Returns the list of libraries in use found in the manifest. - * @return An array of {@link UsesLibrary} objects, or empty if no libraries were found. - */ - public UsesLibrary[] getUsesLibraries() { - return mLibraries.toArray(new UsesLibrary[mLibraries.size()]); - } - - /** - * Returns the list of features in use found in the manifest. - * @return An array of {@link UsesFeature} objects, or empty if no libraries were found. - */ - public UsesFeature[] getUsesFeatures() { - return mFeatures.toArray(new UsesFeature[mFeatures.size()]); - } - - /** - * Returns the glEsVersion from a <uses-feature> or {@link #GL_ES_VERSION_NOT_SET} if not set. - */ - public int getGlEsVersion() { - for (UsesFeature feature : mFeatures) { - if (feature.mGlEsVersion > 0) { - return feature.mGlEsVersion; - } - } - return GL_ES_VERSION_NOT_SET; - } - - /** - * Returns the {@link SupportsScreens} object representing the <code>supports-screens</code> - * node, or null if the node doesn't exist at all. - * Some values in the {@link SupportsScreens} instance maybe null, indicating that they - * were not present in the manifest. To get an instance that contains the values, as seen - * by the Android platform when the app is running, use {@link #getSupportsScreensValues()}. - */ - public SupportsScreens getSupportsScreensFromManifest() { - return mSupportsScreensFromManifest; - } - - /** - * Returns an always non-null instance of {@link SupportsScreens} that's been initialized with - * the default values, and the values from the manifest. - * The default values depends on the manifest values for minSdkVersion and targetSdkVersion. - */ - public synchronized SupportsScreens getSupportsScreensValues() { - if (mSupportsScreensValues == null) { - if (mSupportsScreensFromManifest == null) { - mSupportsScreensValues = SupportsScreens.getDefaultValues(getTargetSdkVersion()); - } else { - // get a SupportsScreen that replace the missing values with default values. - mSupportsScreensValues = mSupportsScreensFromManifest.resolveSupportsScreensValues( - getTargetSdkVersion()); - } - } - - return mSupportsScreensValues; - } - - /** - * Returns the {@link UsesConfiguration} object representing the <code>uses-configuration</code> - * node, or null if the node doesn't exist at all. - */ - public UsesConfiguration getUsesConfiguration() { - return mUsesConfiguration; - } - - void addProcessName(String processName) { - if (mProcesses == null) { - mProcesses = new TreeSet<String>(); - } - - if (processName.startsWith(":")) { - mProcesses.add(mPackage + processName); - } else { - mProcesses.add(processName); - } - } - -} |