import com.android.sdklib.SdkConstants;
import com.android.sdklib.xml.ManifestData;
import com.android.sdklib.xml.ManifestData.Instrumentation;
+import com.android.sdklib.xml.ManifestData.UsesLibrary;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
* @return true if test runner library found, false otherwise
*/
private boolean hasTestRunnerLibrary(ManifestData manifestData) {
- for (String lib : manifestData.getUsesLibraries()) {
- if (lib.equals(AndroidConstants.LIBRARY_TEST_RUNNER)) {
+ for (UsesLibrary lib : manifestData.getUsesLibraries()) {
+ if (AndroidConstants.LIBRARY_TEST_RUNNER.equals(lib.getName())) {
return true;
}
}
public final static String NODE_USES_LIBRARY = "uses-library";
public final static String NODE_SUPPORTS_SCREENS = "supports-screens";
public final static String NODE_USES_CONFIGURATION = "uses-configuration";
+ public final static String NODE_USES_FEATURE = "uses-feature";
public final static String ATTRIBUTE_PACKAGE = "package";
public final static String ATTRIBUTE_VERSIONCODE = "versionCode";
public final static String ATTRIBUTE_NAME = "name";
+ public final static String ATTRIBUTE_REQUIRED = "required";
+ public final static String ATTRIBUTE_GLESVERSION = "glEsVersion";
public final static String ATTRIBUTE_PROCESS = "process";
public final static String ATTRIBUTE_DEBUGGABLE = "debuggable";
public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion";
import com.android.sdklib.xml.ManifestData.Instrumentation;
import com.android.sdklib.xml.ManifestData.SupportsScreens;
import com.android.sdklib.xml.ManifestData.UsesConfiguration;
+import com.android.sdklib.xml.ManifestData.UsesFeature;
+import com.android.sdklib.xml.ManifestData.UsesLibrary;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
public class AndroidManifestParser {
- private final static int LEVEL_MANIFEST = 0;
- private final static int LEVEL_APPLICATION = 1;
- private final static int LEVEL_ACTIVITY = 2;
- private final static int LEVEL_INTENT_FILTER = 3;
- private final static int LEVEL_CATEGORY = 4;
+ 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$
if (mValidLevel == mCurrentLevel) {
String value;
switch (mValidLevel) {
- case LEVEL_MANIFEST:
+ case LEVEL_TOP:
if (AndroidManifest.NODE_MANIFEST.equals(localName)) {
// lets get the package name.
mManifestData.mPackage = getAttributeValue(attributes,
mValidLevel++;
}
break;
- case LEVEL_APPLICATION:
+ case LEVEL_INSIDE_MANIFEST:
if (AndroidManifest.NODE_APPLICATION.equals(localName)) {
value = getAttributeValue(attributes,
AndroidManifest.ATTRIBUTE_PROCESS,
} 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_ACTIVITY:
+ case LEVEL_INSIDE_APPLICATION:
if (AndroidManifest.NODE_ACTIVITY.equals(localName)) {
processActivityNode(attributes);
mValidLevel++;
AndroidManifest.ATTRIBUTE_NAME,
true /* hasNamespace */);
if (value != null) {
- mManifestData.mLibraries.add(value);
+ 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_INTENT_FILTER:
+ case LEVEL_INSIDE_APP_COMPONENT:
// only process this level if we are in an activity
if (mCurrentActivity != null &&
AndroidManifest.NODE_INTENT.equals(localName)) {
mValidLevel++;
}
break;
- case LEVEL_CATEGORY:
+ case LEVEL_INSIDE_INTENT_FILTER:
if (mCurrentActivity != null) {
if (AndroidManifest.NODE_ACTION.equals(localName)) {
// get the name attribute
// process the end of the element
if (mValidLevel == mCurrentLevel) {
switch (mValidLevel) {
- case LEVEL_ACTIVITY:
+ case LEVEL_INSIDE_APPLICATION:
mCurrentActivity = null;
break;
- case LEVEL_INTENT_FILTER:
+ 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 &&
final ArrayList<Instrumentation> mInstrumentations =
new ArrayList<Instrumentation>();
/** List of all libraries in use declared by the manifest */
- final ArrayList<String> mLibraries = new ArrayList<String>();
+ 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 mSupportsScreens;
UsesConfiguration mUsesConfiguration;
}
/**
+ * 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 {
/**
* Returns the list of libraries in use found in the manifest.
- * @return An array of library names, or empty if no libraries were found.
+ * @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 String[] getUsesLibraries() {
- return mLibraries.toArray(new String[mLibraries.size()]);
+ public UsesFeature[] getUsesFeatures() {
+ return mFeatures.toArray(new UsesFeature[mFeatures.size()]);
}
/**
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.testapp"
- android:versionCode="42"
+ package="com.android.testapp" android:versionCode="42"
android:versionName="1.42">
- <application android:icon="@drawable/icon">
- <activity android:name="com.android.testapp.MainActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />"
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- <uses-library android:name="android.test.runner"/>
- </application>"
- <uses-sdk android:minSdkVersion="7"/>
- <supports-screens android:resizeable="true" android:smallScreens="true"
- android:anyDensity="true" android:largeScreens="true" android:normalScreens="true"/>
- <uses-configuration android:reqKeyboardType="twelvekey"
- android:reqTouchScreen="finger" android:reqFiveWayNav="true" android:reqHardKeyboard="true"
- android:reqNavigation="nonav"/>
- <uses-feature android:glEsVersion="1"/>
- <uses-feature android:name="com.foo.feature"/>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.example.android.apis"
- android:label="Tests for Api Demos."/>
-</manifest>
\ No newline at end of file
+ <application android:icon="@drawable/icon">
+ <activity android:name="com.android.testapp.MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <uses-library android:name="android.test.runner"
+ android:required="false" />
+ <uses-library android:name="android.test.runner2" />
+ </application>
+ <uses-sdk android:minSdkVersion="7" />
+ <supports-screens android:resizeable="true"
+ android:smallScreens="true" android:anyDensity="true"
+ android:largeScreens="true" android:normalScreens="true" />
+ <uses-configuration android:reqKeyboardType="twelvekey"
+ android:reqTouchScreen="finger" android:reqFiveWayNav="true"
+ android:reqHardKeyboard="true" android:reqNavigation="nonav" />
+ <uses-feature android:glEsVersion="0x00020001" />
+ <uses-feature android:name="com.foo.feature" />
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.apis" android:label="Tests for Api Demos." />
+</manifest>
import com.android.sdklib.resources.Keyboard;
import com.android.sdklib.resources.Navigation;
import com.android.sdklib.resources.TouchScreen;
+import com.android.sdklib.xml.ManifestData.UsesFeature;
+import com.android.sdklib.xml.ManifestData.UsesLibrary;
import java.io.InputStream;
private static final Integer VERSION_CODE = 42;
private static final String ACTIVITY_NAME = "com.android.testapp.MainActivity"; //$NON-NLS-1$
private static final String LIBRARY_NAME = "android.test.runner"; //$NON-NLS-1$
+ private static final String LIBRARY_NAME2 = "android.test.runner2"; //$NON-NLS-1$
+ private static final String FEATURE_NAME = "com.foo.feature"; //$NON-NLS-1$
private static final String INSTRUMENTATION_NAME = "android.test.InstrumentationTestRunner"; //$NON-NLS-1$
private static final String INSTRUMENTATION_TARGET = "com.android.AndroidProject"; //$NON-NLS-1$
}
public void testGetUsesLibraries() {
- assertEquals(1, mManifestTestApp.getUsesLibraries().length);
- assertEquals(LIBRARY_NAME, mManifestTestApp.getUsesLibraries()[0]);
+ UsesLibrary[] libraries = mManifestTestApp.getUsesLibraries();
+
+ assertEquals(2, libraries.length);
+ assertEquals(LIBRARY_NAME, libraries[0].getName());
+ assertEquals(Boolean.FALSE, libraries[0].getRequired());
+ assertEquals(LIBRARY_NAME2, libraries[1].getName());
+ assertEquals(Boolean.TRUE, libraries[1].getRequired());
+ }
+
+ public void testGetUsesFeatures() {
+ UsesFeature[] features = mManifestTestApp.getUsesFeatures();
+
+ assertEquals(2, features.length);
+ assertEquals(0x00020001, features[0].mGlEsVersion);
+ assertEquals(Boolean.TRUE, features[0].getRequired());
+ assertEquals(FEATURE_NAME, features[1].getName());
+ assertEquals(Boolean.TRUE, features[1].getRequired());
}
public void testGetPackageName() {