Merge change 7975 into donut

* changes:
  Add support for preview versions of platforms.
This commit is contained in:
Android (Google) Code Review
2009-07-20 18:21:48 -07:00
28 changed files with 826 additions and 530 deletions

View File

@@ -130,9 +130,9 @@ public final class SetupTask extends ImportTask {
System.out.println("Project Target: " + androidTarget.getName());
if (androidTarget.isPlatform() == false) {
System.out.println("Vendor: " + androidTarget.getVendor());
System.out.println("Platform Version: " + androidTarget.getApiVersionName());
System.out.println("Platform Version: " + androidTarget.getVersionName());
}
System.out.println("API level: " + androidTarget.getApiVersionNumber());
System.out.println("API level: " + androidTarget.getVersion().getApiString());
// sets up the properties to find android.jar/framework.aidl/target tools
String androidJar = androidTarget.getPath(IAndroidTarget.ANDROID_JAR);

View File

@@ -28,8 +28,11 @@ import java.util.Map;
public interface IDevice {
public final static String PROP_BUILD_VERSION = "ro.build.version.release";
public final static String PROP_BUILD_VERSION_NUMBER = "ro.build.version.sdk";
public final static String PROP_BUILD_API_LEVEL = "ro.build.version.sdk";
public final static String PROP_BUILD_CODENAME = "ro.build.version.codename";
public final static String PROP_DEBUGGABLE = "ro.debuggable";
/** Serial number of the first connected emulator. */
public final static String FIRST_EMULATOR_SN = "emulator-5554"; //$NON-NLS-1$
/** Device change bit mask: {@link DeviceState} change. */
@@ -39,6 +42,9 @@ public interface IDevice {
/** Device change bit mask: build info change. */
public static final int CHANGE_BUILD_INFO = 0x0004;
/** @deprecated Use {@link #PROP_BUILD_API_LEVEL}. */
public final static String PROP_BUILD_VERSION_NUMBER = PROP_BUILD_API_LEVEL;
/**
* The state of a device.
*/

View File

@@ -24,6 +24,7 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.project.FixLaunchConfig;
import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.BasicXmlErrorListener;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
@@ -225,7 +226,7 @@ public class PreCompilerBuilder extends BaseBuilder {
PreCompilerDeltaVisitor dv = null;
String javaPackage = null;
int minSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
String minSdkVersion = null;
if (kind == FULL_BUILD) {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
@@ -315,16 +316,62 @@ public class PreCompilerBuilder extends BaseBuilder {
minSdkVersion = parser.getApiLevelRequirement();
}
if (minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK &&
minSdkVersion < projectTarget.getApiVersionNumber()) {
// check it against the target api level
if (minSdkVersion != null) {
int minSdkValue = -1;
try {
minSdkValue = Integer.parseInt(minSdkVersion);
} catch (NumberFormatException e) {
// it's ok, it means minSdkVersion contains a (hopefully) valid codename.
}
AndroidVersion projectVersion = projectTarget.getVersion();
if (minSdkValue != -1) {
String codename = projectVersion.getCodename();
if (codename != null) {
// integer minSdk when the target is a preview => fatal error
String msg = String.format(
"Platform %1$s is a preview and requires appication manifests to set %2$s to '%3$s'",
codename, AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION,
codename);
AdtPlugin.printErrorToConsole(project, msg);
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
IMarker.SEVERITY_ERROR);
stopBuild(msg);
} else if (minSdkValue < projectVersion.getApiLevel()) {
// integer minSdk is not high enough for the target => warning
String msg = String.format(
"Manifest min SDK version (%1$d) is lower than project target API level (%2$d)",
minSdkVersion, projectTarget.getApiVersionNumber());
minSdkVersion, projectVersion.getApiLevel());
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
IMarker.SEVERITY_WARNING);
}
} else {
// looks like the min sdk is a codename, check it matches the codename
// of the platform
String codename = projectVersion.getCodename();
if (codename == null) {
// platform is not a preview => fatal error
String msg = String.format(
"Manifest attribute '%1$s' is set to '%2$s'. Integer is expected.",
AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
AdtPlugin.printErrorToConsole(project, msg);
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
IMarker.SEVERITY_ERROR);
stopBuild(msg);
} else if (codename.equals(minSdkVersion) == false) {
// platform and manifest codenames don't match => fatal error.
String msg = String.format(
"Value of manifest attribute '%1$s' does not match platform codename '%2$s'",
AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
AdtPlugin.printErrorToConsole(project, msg);
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
IMarker.SEVERITY_ERROR);
stopBuild(msg);
}
}
}
if (javaPackage == null || javaPackage.length() == 0) {
// looks like the AndroidManifest file isn't valid.

View File

@@ -91,7 +91,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
/** Application Package, gathered from the parsing of the manifest */
private String mJavaPackage = null;
/** minSDKVersion attribute value, gathered from the parsing of the manifest */
private int mMinSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
private String mMinSdkVersion = null;
// Internal usage fields.
/**
@@ -162,16 +162,16 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
/**
* Returns the minSDkVersion attribute from the manifest if it was checked/parsed.
* <p/>
* This can return {@link AndroidManifestParser#INVALID_MIN_SDK} in two cases:
* This can return null in two cases:
* <ul>
* <li>The manifest was not part of the resource change delta, and the manifest was
* not checked/parsed ({@link #getCheckedManifestXml()} returns <code>false</code>)</li>
* <li>The manifest was parsed ({@link #getCheckedManifestXml()} returns <code>true</code>),
* but the package declaration is missing</li>
* </ul>
* @return the minSdkVersion or {@link AndroidManifestParser#INVALID_MIN_SDK}.
* @return the minSdkVersion or null.
*/
public int getMinSdkVersion() {
public String getMinSdkVersion() {
return mMinSdkVersion;
}

View File

@@ -35,9 +35,9 @@ import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.wizards.actions.AvdManagerAction;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.NullSdkLog;
import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
@@ -274,16 +274,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param packageName the Android package name of the app
* @param debugPackageName the Android package name to debug
* @param debuggable the debuggable value of the app, or null if not set.
* @param requiredApiVersionNumber the api version required by the app, or
* {@link AndroidManifestParser#INVALID_MIN_SDK} if none.
* @param requiredApiVersionNumber the api version required by the app, or null if none.
* @param launchAction the action to perform after app sync
* @param config the launch configuration
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
String packageName, String debugPackageName, Boolean debuggable, int requiredApiVersionNumber,
final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
final AndroidLaunch launch, IProgressMonitor monitor) {
String packageName, String debugPackageName, Boolean debuggable,
String requiredApiVersionNumber, final IAndroidLaunchAction launchAction,
final AndroidLaunchConfiguration config, final AndroidLaunch launch,
IProgressMonitor monitor) {
String message = String.format("Performing %1$s", launchAction.getLaunchDescription());
AdtPlugin.printToConsole(project, message);
@@ -398,17 +398,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
} else {
if (projectTarget.isPlatform()) { // means this can run on any device as long
// as api level is high enough
String apiString = d.getProperty(SdkManager.PROP_VERSION_SDK);
try {
int apiNumber = Integer.parseInt(apiString);
if (apiNumber >= projectTarget.getApiVersionNumber()) {
AndroidVersion deviceVersion = Sdk.getDeviceVersion(d);
if (deviceVersion.canRun(projectTarget.getVersion())) {
// device is compatible with project
compatibleRunningAvds.put(d, null);
continue;
}
} catch (NumberFormatException e) {
// do nothing, we'll consider it a non compatible device below.
}
} else {
// for non project platform, we can't be sure if a device can
// run an application or not, since we don't query the device
// for the list of optional libraries that it supports.
}
hasDevice = true;
}
@@ -544,9 +543,12 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
AvdInfo defaultAvd = null;
for (AvdInfo avd : avds) {
if (projectTarget.isCompatibleBaseFor(avd.getTarget())) {
// at this point we can ignore the code name issue since
// IAndroidTarget.isCompatibleBaseFor() will already have filtered the non
// compatible AVDs.
if (defaultAvd == null ||
avd.getTarget().getApiVersionNumber() <
defaultAvd.getTarget().getApiVersionNumber()) {
avd.getTarget().getVersion().getApiLevel() <
defaultAvd.getTarget().getVersion().getApiLevel()) {
defaultAvd = avd;
}
}
@@ -654,46 +656,66 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (device != null) {
// check the app required API level versus the target device API level
String deviceApiVersionName = device.getProperty(IDevice.PROP_BUILD_VERSION);
String value = device.getProperty(IDevice.PROP_BUILD_VERSION_NUMBER);
int deviceApiVersionNumber = AndroidManifestParser.INVALID_MIN_SDK;
String deviceVersion = device.getProperty(IDevice.PROP_BUILD_VERSION);
String deviceApiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL);
String deviceCodeName = device.getProperty(IDevice.PROP_BUILD_CODENAME);
int deviceApiLevel = -1;
try {
deviceApiVersionNumber = Integer.parseInt(value);
deviceApiLevel = Integer.parseInt(deviceApiLevelString);
} catch (NumberFormatException e) {
// pass, we'll keep the deviceVersionNumber value at 0.
// pass, we'll keep the apiLevel value at -1.
}
if (launchInfo.getRequiredApiVersionNumber() == AndroidManifestParser.INVALID_MIN_SDK) {
// warn the API level requirement is not set.
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Application does not specify an API level requirement!");
String requiredApiString = launchInfo.getRequiredApiVersionNumber();
if (requiredApiString != null) {
int requiredApi = -1;
try {
requiredApi = Integer.parseInt(requiredApiString);
} catch (NumberFormatException e) {
// pass, we'll keep requiredApi value at -1.
}
// and display the target device API level (if known)
if (deviceApiVersionName == null ||
deviceApiVersionNumber == AndroidManifestParser.INVALID_MIN_SDK) {
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Unknown device API version!");
} else {
if (requiredApi == -1) {
// this means the manifest uses a codename for minSdkVersion
// check that the device is using the same codename
if (requiredApiString.equals(deviceCodeName) == false) {
AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
"Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
deviceApiVersionName));
"ERROR: Application requires a device running '%1$s'!",
requiredApiString));
return false;
}
} else { // app requires a specific API level
if (deviceApiVersionName == null ||
deviceApiVersionNumber == AndroidManifestParser.INVALID_MIN_SDK) {
} else {
// app requires a specific API level
if (deviceApiLevel == -1) {
AdtPlugin.printToConsole(launchInfo.getProject(),
"WARNING: Unknown device API version!");
} else if (deviceApiVersionNumber < launchInfo.getRequiredApiVersionNumber()) {
} else if (deviceApiLevel < requiredApi) {
String msg = String.format(
"ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
launchInfo.getRequiredApiVersionNumber(), deviceApiVersionNumber,
deviceApiVersionName);
requiredApi, deviceApiLevel, deviceVersion);
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
// abort the launch
return false;
}
}
} else {
// warn the application API level requirement is not set.
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Application does not specify an API level requirement!");
// and display the target device API level (if known)
if (deviceApiLevel == -1) {
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Unknown device API version!");
} else {
AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
"Device API version is %1$d (Android %2$s)", deviceApiLevel,
deviceVersion));
}
}
// now checks that the device/app can be debugged (if needed)
if (device.isEmulator() == false && launchInfo.isDebugMode()) {

View File

@@ -17,7 +17,6 @@
package com.android.ide.eclipse.adt.internal.launch;
import com.android.ddmlib.IDevice;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestParser;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -54,9 +53,8 @@ public final class DelayedLaunchInfo {
/** debuggable attribute of the manifest file. */
private final Boolean mDebuggable;
/** Required ApiVersionNumber by the app. {@link AndroidManifestParser#INVALID_MIN_SDK} means
* no requirements */
private final int mRequiredApiVersionNumber;
/** Required Api level by the app. null means no requirements */
private final String mRequiredApiVersionNumber;
private InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
@@ -87,14 +85,13 @@ public final class DelayedLaunchInfo {
* @param launchAction action to perform after app install
* @param pack IFile to the package (.apk) file
* @param debuggable debuggable attribute of the app's manifest file.
* @param requiredApiVersionNumber required SDK version by the app.
* {@link AndroidManifestParser#INVALID_MIN_SDK} means no requirements.
* @param requiredApiVersionNumber required SDK version by the app. null means no requirements.
* @param launch the launch object
* @param monitor progress monitor for launch
*/
public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName,
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
String requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
mDebugPackageName = debugPackageName;
@@ -160,9 +157,9 @@ public final class DelayedLaunchInfo {
}
/**
* @return the required api version number for the Android app
* @return the required api version number for the Android app.
*/
public int getRequiredApiVersionNumber() {
public String getRequiredApiVersionNumber() {
return mRequiredApiVersionNumber;
}

View File

@@ -27,6 +27,7 @@ import com.android.ddmuilib.TableHelper;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdkuilib.internal.widgets.AvdSelector;
@@ -131,26 +132,19 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
case 2:
// check for compatibility.
if (device.isEmulator() == false) { // physical device
// get the api level of the device
try {
String apiValue = device.getProperty(
IDevice.PROP_BUILD_VERSION_NUMBER);
if (apiValue != null) {
int api = Integer.parseInt(apiValue);
if (api >= mProjectTarget.getApiVersionNumber()) {
// if the project is compiling against an add-on, the optional
// API may be missing from the device.
// get the version of the device
AndroidVersion deviceVersion = Sdk.getDeviceVersion(device);
if (deviceVersion == null) {
return mWarningImage;
} else {
if (deviceVersion.canRun(mProjectTarget.getVersion()) == false) {
return mNoMatchImage;
}
// if the project is compiling against an add-on,
// the optional API may be missing from the device.
return mProjectTarget.isPlatform() ?
mMatchImage : mWarningImage;
} else {
return mNoMatchImage;
}
} else {
return mWarningImage;
}
} catch (NumberFormatException e) {
// lets consider the device non compatible
return mNoMatchImage;
}
} else {
// get the AvdInfo

View File

@@ -51,7 +51,7 @@ public class AndroidManifestParser {
private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
private final static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
@@ -76,8 +76,6 @@ public class AndroidManifestParser {
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 final static int INVALID_MIN_SDK = -1;
/**
* Instrumentation info obtained from manifest
*/
@@ -179,9 +177,8 @@ public class AndroidManifestParser {
private Set<String> mProcesses = null;
/** debuggable attribute value. If null, the attribute is not present. */
private Boolean mDebuggable = null;
/** API level requirement. if {@link AndroidManifestParser#INVALID_MIN_SDK}
* the attribute was not present. */
private int mApiLevelRequirement = INVALID_MIN_SDK;
/** API level requirement. if null the attribute was not present. */
private String mApiLevelRequirement = null;
/** List of all instrumentations declared by the manifest */
private final ArrayList<Instrumentation> mInstrumentations =
new ArrayList<Instrumentation>();
@@ -258,10 +255,9 @@ public class AndroidManifestParser {
}
/**
* Returns the <code>minSdkVersion</code> attribute, or
* {@link AndroidManifestParser#INVALID_MIN_SDK} if it's not set.
* Returns the <code>minSdkVersion</code> attribute, or null if it's not set.
*/
int getApiLevelRequirement() {
String getApiLevelRequirement() {
return mApiLevelRequirement;
}
@@ -331,16 +327,8 @@ public class AndroidManifestParser {
mValidLevel++;
} else if (NODE_USES_SDK.equals(localName)) {
value = getAttributeValue(attributes, ATTRIBUTE_MIN_SDK_VERSION,
true /* hasNamespace */);
if (value != null) {
try {
mApiLevelRequirement = Integer.parseInt(value);
} catch (NumberFormatException e) {
handleError(e, -1 /* lineNumber */);
}
}
mApiLevelRequirement = getAttributeValue(attributes,
ATTRIBUTE_MIN_SDK_VERSION, true /* hasNamespace */);
} else if (NODE_INSTRUMENTATION.equals(localName)) {
processInstrumentationNode(attributes);
}
@@ -636,7 +624,7 @@ public class AndroidManifestParser {
private final Activity mLauncherActivity;
private final String[] mProcesses;
private final Boolean mDebuggable;
private final int mApiLevelRequirement;
private final String mApiLevelRequirement;
private final Instrumentation[] mInstrumentations;
private final String[] mLibraries;
@@ -904,10 +892,9 @@ public class AndroidManifestParser {
}
/**
* Returns the <code>minSdkVersion</code> attribute, or {@link #INVALID_MIN_SDK}
* if it's not set.
* Returns the <code>minSdkVersion</code> attribute, or null if it's not set.
*/
public int getApiLevelRequirement() {
public String getApiLevelRequirement() {
return mApiLevelRequirement;
}
@@ -939,13 +926,13 @@ public class AndroidManifestParser {
* @param launcherActivity the launcher activity parser from the manifest.
* @param processes the list of custom processes declared in the manifest.
* @param debuggable the debuggable attribute, or null if not set.
* @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set.
* @param apiLevelRequirement the minSdkVersion attribute value or null if not set.
* @param instrumentations the list of instrumentations parsed from the manifest.
* @param libraries the list of libraries in use parsed from the manifest.
*/
private AndroidManifestParser(String javaPackage, Activity[] activities,
Activity launcherActivity, String[] processes, Boolean debuggable,
int apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
String apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
mJavaPackage = javaPackage;
mActivities = activities;
mLauncherActivity = launcherActivity;

View File

@@ -203,7 +203,7 @@ public final class AndroidTargetParser {
Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null;
if (mAndroidTarget.getApiVersionNumber() >= 3) {
if (mAndroidTarget.getVersion().getApiLevel() >= 3) {
xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser);
}

View File

@@ -16,12 +16,14 @@
package com.android.ide.eclipse.adt.internal.sdk;
import com.android.ddmlib.IDevice;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor.IProjectListener;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
@@ -394,6 +396,21 @@ public class Sdk implements IProjectListener {
return mAvdManager;
}
public static AndroidVersion getDeviceVersion(IDevice device) {
try {
Map<String, String> props = device.getProperties();
String apiLevel = props.get(IDevice.PROP_BUILD_API_LEVEL);
if (apiLevel == null) {
return null;
}
return new AndroidVersion(Integer.parseInt(apiLevel),
props.get((IDevice.PROP_BUILD_CODENAME)));
} catch (NumberFormatException e) {
return null;
}
}
private Sdk(SdkManager manager, AvdManager avdManager) {
mManager = manager;
mAvdManager = avdManager;

View File

@@ -840,26 +840,22 @@ public class NewProjectCreationPage extends WizardPage {
return;
}
try {
int version = Integer.parseInt(mInfo.getMinSdkVersion());
String minSdkVersion = mInfo.getMinSdkVersion();
// Before changing, compare with the currently selected one, if any.
// There can be multiple targets with the same sdk api version, so don't change
// it if it's already at the right version.
IAndroidTarget curr_target = mInfo.getSdkTarget();
if (curr_target != null && curr_target.getApiVersionNumber() == version) {
if (curr_target != null && curr_target.getVersion().equals(minSdkVersion)) {
return;
}
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (target.getApiVersionNumber() == version) {
if (target.getVersion().equals(minSdkVersion)) {
mSdkTargetSelector.setSelection(target);
break;
}
}
} catch (NumberFormatException e) {
// ignore
}
}
/**
@@ -873,7 +869,7 @@ public class NewProjectCreationPage extends WizardPage {
if (target != null) {
mInternalMinSdkVersionUpdate = true;
mMinSdkVersionField.setText(Integer.toString(target.getApiVersionNumber()));
mMinSdkVersionField.setText(target.getVersion().getApiString());
mInternalMinSdkVersionUpdate = false;
}
}
@@ -932,7 +928,7 @@ public class NewProjectCreationPage extends WizardPage {
String packageName = null;
Activity activity = null;
String activityName = null;
int minSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
String minSdkVersion = null;
try {
packageName = manifestData.getPackage();
minSdkVersion = manifestData.getApiLevelRequirement();
@@ -1033,18 +1029,14 @@ public class NewProjectCreationPage extends WizardPage {
}
}
if (!foundTarget && minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK) {
try {
if (!foundTarget && minSdkVersion != null) {
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (target.getApiVersionNumber() == minSdkVersion) {
if (target.getVersion().equals(minSdkVersion)) {
mSdkTargetSelector.setSelection(target);
foundTarget = true;
break;
}
}
} catch(NumberFormatException e) {
// ignore
}
}
if (!foundTarget) {
@@ -1059,9 +1051,9 @@ public class NewProjectCreationPage extends WizardPage {
if (!foundTarget) {
mInternalMinSdkVersionUpdate = true;
mMinSdkVersionField.setText(
minSdkVersion == AndroidManifestParser.INVALID_MIN_SDK ? "" //$NON-NLS-1$
: Integer.toString(minSdkVersion));
if (minSdkVersion != null) {
mMinSdkVersionField.setText(minSdkVersion);
}
mInternalMinSdkVersionUpdate = false;
}
}
@@ -1269,21 +1261,10 @@ public class NewProjectCreationPage extends WizardPage {
return MSG_NONE;
}
int version = AndroidManifestParser.INVALID_MIN_SDK;
try {
// If not empty, it must be a valid integer > 0
version = Integer.parseInt(mInfo.getMinSdkVersion());
} catch (NumberFormatException e) {
// ignore
}
if (version < 1) {
return setStatus("Min SDK Version must be an integer > 0.", MSG_ERROR);
}
if (mInfo.getSdkTarget() != null && mInfo.getSdkTarget().getApiVersionNumber() != version) {
if (mInfo.getSdkTarget() != null &&
mInfo.getSdkTarget().getVersion().equals(mInfo.getMinSdkVersion()) == false) {
return setStatus("The API level for the selected SDK target does not match the Min SDK version.",
MSG_WARNING);
mInfo.getSdkTarget().getVersion().isPreview() ? MSG_ERROR : MSG_WARNING);
}
return MSG_NONE;

View File

@@ -821,7 +821,7 @@ public class NewTestProjectCreationPage extends WizardPage {
if (manifestData != null) {
String appName = String.format("%1$sTest", project.getName());
String packageName = manifestData.getPackage();
int minSdkVersion = manifestData.getApiLevelRequirement();
String minSdkVersion = manifestData.getApiLevelRequirement();
IAndroidTarget sdkTarget = null;
if (Sdk.getCurrent() != null) {
sdkTarget = Sdk.getCurrent().getTarget(project);
@@ -859,9 +859,9 @@ public class NewTestProjectCreationPage extends WizardPage {
if (!mMinSdkVersionModifiedByUser) {
mInternalMinSdkVersionUpdate = true;
mMinSdkVersionField.setText(
minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK ?
Integer.toString(minSdkVersion) : ""); //$NON-NLS-1$
if (minSdkVersion != null) {
mMinSdkVersionField.setText(minSdkVersion);
}
if (sdkTarget == null) {
updateSdkSelectorToMatchMinSdkVersion();
}
@@ -1052,23 +1052,19 @@ public class NewTestProjectCreationPage extends WizardPage {
* that matches.
*/
private void updateSdkSelectorToMatchMinSdkVersion() {
try {
int version = Integer.parseInt(mInfo.getMinSdkVersion());
String minSdkVersion = mInfo.getMinSdkVersion();
IAndroidTarget curr_target = mInfo.getSdkTarget();
if (curr_target != null && curr_target.getApiVersionNumber() == version) {
if (curr_target != null && curr_target.getVersion().equals(minSdkVersion)) {
return;
}
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (target.getApiVersionNumber() == version) {
if (target.getVersion().equals(minSdkVersion)) {
mSdkTargetSelector.setSelection(target);
return;
}
}
} catch (NumberFormatException e) {
// ignore
}
}
/**
@@ -1086,7 +1082,7 @@ public class NewTestProjectCreationPage extends WizardPage {
if (target != null) {
mInternalMinSdkVersionUpdate = true;
mMinSdkVersionField.setText(Integer.toString(target.getApiVersionNumber()));
mMinSdkVersionField.setText(target.getVersion().getApiString());
mInternalMinSdkVersionUpdate = false;
}
@@ -1261,21 +1257,10 @@ public class NewTestProjectCreationPage extends WizardPage {
return MSG_NONE;
}
int version = AndroidManifestParser.INVALID_MIN_SDK;
try {
// If not empty, it must be a valid integer > 0
version = Integer.parseInt(mInfo.getMinSdkVersion());
} catch (NumberFormatException e) {
// ignore
}
if (version < 1) {
return setStatus("Min SDK Version must be an integer > 0.", MSG_ERROR);
}
if (mInfo.getSdkTarget() != null && mInfo.getSdkTarget().getApiVersionNumber() != version) {
if (mInfo.getSdkTarget() != null &&
mInfo.getSdkTarget().getVersion().equals(mInfo.getMinSdkVersion()) == false) {
return setStatus("The API level for the selected SDK target does not match the Min SDK version.",
MSG_WARNING);
mInfo.getSdkTarget().getVersion().isPreview() ? MSG_ERROR : MSG_WARNING);
}
return MSG_NONE;

View File

@@ -1130,7 +1130,7 @@ class NewXmlFileCreationPage extends WizardPage {
IAndroidTarget target = mProject != null ? Sdk.getCurrent().getTarget(mProject) : null;
int currentApiLevel = 1;
if (target != null) {
currentApiLevel = target.getApiVersionNumber();
currentApiLevel = target.getVersion().getApiLevel();
}
for (TypeInfo type : sTypes) {
@@ -1175,7 +1175,7 @@ class NewXmlFileCreationPage extends WizardPage {
IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
int currentApiLevel = 1;
if (target != null) {
currentApiLevel = target.getApiVersionNumber();
currentApiLevel = target.getVersion().getApiLevel();
}
TypeInfo type = getSelectedType();

View File

@@ -416,7 +416,7 @@ class Main {
mSdkLog.printf(" Name: %s\n", target.getName());
if (target.isPlatform()) {
mSdkLog.printf(" Type: Platform\n");
mSdkLog.printf(" API level: %d\n", target.getApiVersionNumber());
mSdkLog.printf(" API level: %s\n", target.getVersion().getApiString());
mSdkLog.printf(" Revision: %d\n", target.getRevision());
} else {
mSdkLog.printf(" Type: Add-On\n");
@@ -426,7 +426,7 @@ class Main {
mSdkLog.printf(" Description: %s\n", target.getDescription());
}
mSdkLog.printf(" Based on Android %s (API level %d)\n",
target.getApiVersionName(), target.getApiVersionNumber());
target.getVersionName(), target.getVersion().getApiString());
// display the optional libraries.
IOptionalLibrary[] libraries = target.getOptionalLibraries();
@@ -501,13 +501,13 @@ class Main {
// get the target of the AVD
IAndroidTarget target = info.getTarget();
if (target.isPlatform()) {
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
target.getApiVersionNumber());
mSdkLog.printf(" Target: %s (API level %s)\n", target.getName(),
target.getVersion().getApiString());
} else {
mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
.getVendor());
mSdkLog.printf(" Based on Android %s (API level %d)\n", target
.getApiVersionName(), target.getApiVersionNumber());
mSdkLog.printf(" Based on Android %s (API level %s)\n",
target.getVersionName(), target.getVersion().getApiString());
}
// display some extra values.

View File

@@ -137,14 +137,13 @@ final class AddOnTarget implements IAndroidTarget {
return mDescription;
}
public String getApiVersionName() {
public AndroidVersion getVersion() {
// this is always defined by the base platform
return mBasePlatform.getApiVersionName();
return mBasePlatform.getVersion();
}
public int getApiVersionNumber() {
// this is always defined by the base platform
return mBasePlatform.getApiVersionNumber();
public String getVersionName() {
return mBasePlatform.getVersionName();
}
public int getRevision() {
@@ -182,7 +181,7 @@ final class AddOnTarget implements IAndroidTarget {
return sampleLoc.getAbsolutePath();
}
}
// INTENT FALL-THROUGH
// INTENDED FALL-THROUGH
default :
return mBasePlatform.getPath(pathId);
}
@@ -222,21 +221,22 @@ final class AddOnTarget implements IAndroidTarget {
// if the receiver has no optional library, then anything with api version number >= to
// the receiver is compatible.
if (mLibraries.length == 0) {
return target.getApiVersionNumber() >= getApiVersionNumber();
return target.getVersion().getApiLevel() >= getVersion().getApiLevel();
}
// Otherwise, target is only compatible if the vendor and name are equals with the api
// number greater or equal (ie target is a newer version of this add-on).
if (target.isPlatform() == false) {
return (mVendor.equals(target.getVendor()) && mName.equals(target.getName()) &&
target.getApiVersionNumber() >= getApiVersionNumber());
target.getVersion().getApiLevel() >= getVersion().getApiLevel());
}
return false;
}
public String hashString() {
return String.format(ADD_ON_FORMAT, mVendor, mName, mBasePlatform.getApiVersionNumber());
return String.format(ADD_ON_FORMAT, mVendor, mName,
mBasePlatform.getVersion().getApiLevel());
}
@Override
@@ -250,7 +250,7 @@ final class AddOnTarget implements IAndroidTarget {
AddOnTarget addon = (AddOnTarget)obj;
return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
mBasePlatform.getApiVersionNumber() == addon.mBasePlatform.getApiVersionNumber();
mBasePlatform.getVersion().getApiLevel() == addon.mBasePlatform.getVersion().getApiLevel();
}
return super.equals(obj);
@@ -277,7 +277,7 @@ final class AddOnTarget implements IAndroidTarget {
// api version
if (value == 0) {
value = getApiVersionNumber() - target.getApiVersionNumber();
value = getVersion().getApiLevel() - target.getVersion().getApiLevel();
}
return value;

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2009 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.sdklib;
import java.util.Properties;
/**
* Represents the version of a target or device.
* <p/>
* A version is defined by an API level and an optional code name.
* <ul><li>Release versions of the Android platform are identified by their API level (integer),
* (technically the code name for release version is "REL" but this class will return
* <code>null<code> instead.)</li>
* <li>Preview versions of the platform are identified by a code name. Their API level
* is usually set to the value of the previous platform.</li></ul>
* <p/>
* While this class contains both values, its goal is to abstract them, so that code comparing 2+
* versions doesn't have to deal with the logic of handle both values.
* <p/>
* There are some cases where ones may want to access the values directly. This can be done
* with {@link #getApiLevel()} and {@link #getCodename()}.
* <p/>
* For generic UI display of the API version, {@link #getApiString()} is to be used.
*
*/
public class AndroidVersion {
private static final String PROP_API_LEVEL = "AndroidVersion.ApiLevel"; //$NON-NLS-1$
private static final String PROP_CODENAME = "AndroidVersion.CodeName"; //$NON-NLS-1$
private final int mApiLevel;
private final String mCodename;
public AndroidVersion(int apiLevel, String codename) {
mApiLevel = apiLevel;
mCodename = codename;
}
public AndroidVersion(Properties properties) {
throw new UnsupportedOperationException("TODO");
}
public void saveProperties(Properties props) {
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
props.setProperty(PROP_CODENAME, mCodename);
}
/**
* Returns the api level as an integer.
* <p/>For target that are in preview mode, this can be superseded by
* {@link #getCodename()}.
* <p/>To display the API level in the UI, use {@link #getApiString()}, which will use the
* codename if applicable.
* @see #getCodename()
* @see #getApiString()
*/
public int getApiLevel() {
return mApiLevel;
}
/**
* Returns the version code name if applicable, null otherwise.
* <p/>If the codename is non null, then the API level should be ignored, and this should be
* used as a unique identifier of the target instead.
*/
public String getCodename() {
return mCodename;
}
/**
* Returns a string representing the API level and/or the code name.
*/
public String getApiString() {
if (mCodename != null) {
return mCodename;
}
return Integer.toString(mApiLevel);
}
/**
* Returns whether or not the version is a preview version.
*/
public boolean isPreview() {
return mCodename != null;
}
/**
* Checks whether a device running a version similar to the receiver can run a project compiled
* for the given <var>version</var>.
* <p/>
* Be aware that this is not a perfect test, as other properties could break compatibility
* despite this method returning true. For a more comprehensive test, see
* {@link IAndroidTarget#isCompatibleBaseFor(IAndroidTarget)}.
* <p/>
* Nevertheless, when testing if an application can run on a device (where there is no
* access to the list of optional libraries), this method can give a good indication of whether
* there is a chance the application could run, or if there's a direct incompatibility.
*/
public boolean canRun(AndroidVersion appVersion) {
// if the application is compiled for a preview version, the device must be running exactly
// the same.
if (appVersion.mCodename != null) {
return appVersion.mCodename.equals(mCodename);
}
// otherwise, we check the api level (note that a device running a preview version
// will have the api level of the previous platform).
return mApiLevel >= appVersion.mApiLevel;
}
/**
* Returns <code>true</code> if the AndroidVersion is an API level equals to
* <var>apiLevel</var>.
*/
public boolean equals(int apiLevel) {
return mCodename == null && apiLevel == mApiLevel;
}
/**
* Compares the receiver with either an {@link AndroidVersion} object or a {@link String}
* object.
* <p/>If <var>obj</var> is a {@link String}, then the method will first check if it's a string
* representation of a number, in which case it'll compare it to the api level. Otherwise, it'll
* compare it against the code name.
* <p/>For all other type of object give as parameter, this method will return
* <code>false</code>.
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof AndroidVersion) {
AndroidVersion version = (AndroidVersion)obj;
if (mCodename == null) {
return version.mCodename == null &&
mApiLevel == version.mApiLevel;
} else {
return mCodename.equals(version.mCodename) &&
mApiLevel == version.mApiLevel;
}
} else if (obj instanceof String) {
try {
int value = Integer.parseInt((String)obj);
return value == mApiLevel;
} catch (NumberFormatException e) {
// not a number? compare to the code name
return obj.equals(mCodename);
}
}
return false;
}
@Override
public int hashCode() {
if (mCodename != null) {
return mCodename.hashCode();
}
// there may be some collisions between the hashcode of the codename and the api level
// but it's acceptable.
return mApiLevel;
}
}

View File

@@ -119,14 +119,14 @@ public interface IAndroidTarget extends Comparable<IAndroidTarget> {
String getDescription();
/**
* Returns the api version as an integer.
* Returns the version of the target. This is guaranteed to be non-null.
*/
int getApiVersionNumber();
AndroidVersion getVersion();
/**
* Returns the platform version as a readable string.
*/
String getApiVersionName();
public String getVersionName();
/** Returns the revision number for the target. */
int getRevision();

View File

@@ -26,32 +26,41 @@ import java.util.Map;
*/
final class PlatformTarget implements IAndroidTarget {
/** String used to get a hash to the platform target */
private final static String PLATFORM_HASH = "android-%d";
private final static String PLATFORM_HASH_API_LEVEL = "android-%d";
private final static String PLATFORM_HASH_CODENAME = "android-%s";
private final static String PLATFORM_VENDOR = "Android Open Source Project";
private final static String PLATFORM_NAME = "Android %s";
private final static String PLATFORM_NAME_PREVIEW = "Android %s (Preview)";
private final String mLocation;
private final String mName;
private final int mApiVersionNumber;
private final String mApiVersionName;
private final AndroidVersion mVersion;
private final String mVersionName;
private final int mRevision;
private final Map<String, String> mProperties;
private final Map<Integer, String> mPaths = new HashMap<Integer, String>();
private String[] mSkins;
PlatformTarget(String location, Map<String, String> properties,
int apiNumber, String apiName, int revision) {
mName = String.format(PLATFORM_NAME, apiName);
int apiLevel, String codeName, String versionName, int revision) {
if (location.endsWith(File.separator) == false) {
location = location + File.separator;
}
mLocation = location;
mProperties = Collections.unmodifiableMap(properties);
mApiVersionNumber = apiNumber;
mApiVersionName = apiName;
mVersion = new AndroidVersion(apiLevel, codeName);
mVersionName = versionName;
mRevision = revision;
if (mVersion.isPreview()) {
mName = String.format(PLATFORM_NAME_PREVIEW, mVersionName);
} else {
mName = String.format(PLATFORM_NAME, mVersionName);
}
// pre-build the path to the platform components
mPaths.put(ANDROID_JAR, mLocation + SdkConstants.FN_FRAMEWORK_LIBRARY);
mPaths.put(SOURCES, mLocation + SdkConstants.FD_ANDROID_SOURCES);
@@ -119,15 +128,15 @@ final class PlatformTarget implements IAndroidTarget {
* @see com.android.sdklib.IAndroidTarget#getDescription()
*/
public String getDescription() {
return String.format("Standard Android platform %s", mApiVersionName);
return String.format("Standard Android platform %s", mVersionName);
}
public int getApiVersionNumber(){
return mApiVersionNumber;
public AndroidVersion getVersion() {
return mVersion;
}
public String getApiVersionName() {
return mApiVersionName;
public String getVersionName() {
return mVersionName;
}
public int getRevision() {
@@ -189,13 +198,23 @@ final class PlatformTarget implements IAndroidTarget {
return true;
}
// if the platform has a codename (ie it's a preview of an upcoming platform), then
// both platform must be exactly identical.
if (mVersion.getCodename() != null) {
return equals(target);
}
// target is compatible wit the receiver as long as its api version number is greater or
// equal.
return target.getApiVersionNumber() >= mApiVersionNumber;
return target.getVersion().getApiLevel() >= mVersion.getApiLevel();
}
public String hashString() {
return String.format(PLATFORM_HASH, mApiVersionNumber);
if (mVersion.getCodename() != null) {
return String.format(PLATFORM_HASH_CODENAME, mVersion.getCodename());
}
return String.format(PLATFORM_HASH_API_LEVEL, mVersion.getApiLevel());
}
@Override
@@ -206,10 +225,12 @@ final class PlatformTarget implements IAndroidTarget {
@Override
public boolean equals(Object obj) {
if (obj instanceof PlatformTarget) {
return mApiVersionNumber == ((PlatformTarget)obj).mApiVersionNumber;
PlatformTarget platform = (PlatformTarget)obj;
return mVersion.equals(platform.getVersion());
}
return super.equals(obj);
return false;
}
/*
@@ -223,7 +244,13 @@ final class PlatformTarget implements IAndroidTarget {
return -1;
}
return mApiVersionNumber - target.getApiVersionNumber();
int apiDiff = mVersion.getApiLevel() - target.getVersion().getApiLevel();
if (mVersion.getCodename() != null && apiDiff == 0) {
return mVersion.getCodename().compareTo(target.getVersion().getCodename());
}
return apiDiff;
}
// ---- platform only methods.

View File

@@ -42,6 +42,7 @@ import java.util.regex.Pattern;
public final class SdkManager {
public final static String PROP_VERSION_SDK = "ro.build.version.sdk";
public final static String PROP_VERSION_CODENAME = "ro.build.version.codename";
public final static String PROP_VERSION_RELEASE = "ro.build.version.release";
public final static String PROP_VERSION_REVISION = "ro.build.version.incremental";
@@ -263,23 +264,28 @@ public final class SdkManager {
if (map != null) {
// look for some specific values in the map.
// version string
String apiName = map.get(PROP_VERSION_RELEASE);
if (apiName == null) {
if (log != null) {
log.error(null,
"Ignoring platform '%1$s': %2$s is missing from '%3$s'",
platform.getName(), PROP_VERSION_RELEASE, SdkConstants.FN_BUILD_PROP);
platform.getName(), PROP_VERSION_RELEASE,
SdkConstants.FN_BUILD_PROP);
}
return null;
}
// api level
int apiNumber;
String stringValue = map.get(PROP_VERSION_SDK);
if (stringValue == null) {
if (log != null) {
log.error(null,
"Ignoring platform '%1$s': %2$s is missing from '%3$s'",
platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
platform.getName(), PROP_VERSION_SDK,
SdkConstants.FN_BUILD_PROP);
}
return null;
} else {
@@ -291,19 +297,28 @@ public final class SdkManager {
if (log != null) {
log.error(null,
"Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
platform.getName(), PROP_VERSION_SDK,
SdkConstants.FN_BUILD_PROP);
}
return null;
}
}
// codename (optional)
String apiCodename = map.get(PROP_VERSION_CODENAME);
if (apiCodename != null && apiCodename.equals("REL")) {
apiCodename = null; // REL means it's a release version and therefore the
// codename is irrelevant at this point.
}
int revision = 1;
stringValue = map.get(PROP_VERSION_REVISION);
if (stringValue == null) {
if (log != null) {
log.error(null,
"Ignoring platform '%1$s': %2$s is missing from '%3$s'",
platform.getName(), PROP_VERSION_REVISION, SdkConstants.FN_BUILD_PROP);
platform.getName(), PROP_VERSION_REVISION,
SdkConstants.FN_BUILD_PROP);
}
return null;
} else {
@@ -346,6 +361,7 @@ public final class SdkManager {
platform.getAbsolutePath(),
map,
apiNumber,
apiCodename,
apiName,
revision);
@@ -435,8 +451,7 @@ public final class SdkManager {
try {
int apiValue = Integer.parseInt(api);
for (IAndroidTarget target : targetList) {
if (target.isPlatform() &&
target.getApiVersionNumber() == apiValue) {
if (target.isPlatform() && target.getVersion().equals(apiValue)) {
baseTarget = (PlatformTarget)target;
break;
}

View File

@@ -16,6 +16,7 @@
package com.android.sdklib.internal.repository;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
@@ -36,13 +37,12 @@ import java.util.Properties;
*/
public class AddonPackage extends Package {
private static final String PROP_API_LEVEL = "Addon.ApiLevel"; //$NON-NLS-1$
private static final String PROP_NAME = "Addon.Name"; //$NON-NLS-1$
private static final String PROP_VENDOR = "Addon.Vendor"; //$NON-NLS-1$
private final String mVendor;
private final String mName;
private final int mApiLevel;
private final AndroidVersion mVersion;
/** An add-on library. */
public static class Lib {
@@ -74,7 +74,10 @@ public class AddonPackage extends Package {
super(source, packageNode, licenses);
mVendor = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VENDOR);
mName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_NAME);
mApiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);
mVersion = new AndroidVersion(
XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0),
null); // add-ons on platform previews is not supported, so the codename is always
// null in this case.
mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepository.NODE_LIBS));
}
@@ -88,7 +91,7 @@ public class AddonPackage extends Package {
AddonPackage(IAndroidTarget target, Properties props) {
super( null, //source
props, //properties
0, //revision
target.getRevision(), //revision
null, //license
target.getDescription(), //description
null, //descUrl
@@ -97,7 +100,7 @@ public class AddonPackage extends Package {
target.getLocation() //archiveOsPath
);
mApiLevel = target.getApiVersionNumber();
mVersion = target.getVersion();
mName = target.getName();
mVendor = target.getVendor();
@@ -114,13 +117,13 @@ public class AddonPackage extends Package {
/**
* Save the properties of the current packages in the given {@link Properties} object.
* These properties will later be give the constructor that takes a {@link Properties} object.
* These properties will later be given to a constructor that takes a {@link Properties} object.
*/
@Override
void saveProperties(Properties props) {
super.saveProperties(props);
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
mVersion.saveProperties(props);
props.setProperty(PROP_NAME, mName);
props.setProperty(PROP_VENDOR, mVendor);
}
@@ -167,7 +170,8 @@ public class AddonPackage extends Package {
/** Returns the api-level, an int > 0, for platform, add-on and doc packages. */
public int getApiLevel() {
return mApiLevel;
// FIXME: return the AndroidVersion instead.
return mVersion.getApiLevel();
}
/** Returns the libs defined in this add-on. Can be an empty array but not null. */
@@ -214,7 +218,7 @@ public class AddonPackage extends Package {
// First find if this add-on is already installed. If so, reuse the same directory.
for (IAndroidTarget target : sdkManager.getTargets()) {
if (!target.isPlatform() &&
target.getApiVersionNumber() == getApiLevel() &&
target.getVersion().equals(mVersion) &&
target.getName().equals(getName()) &&
target.getVendor().equals(getVendor())) {
return new File(target.getLocation());

View File

@@ -16,6 +16,7 @@
package com.android.sdklib.internal.repository;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
@@ -34,11 +35,10 @@ import java.util.Properties;
*/
public class PlatformPackage extends Package {
private static final String PROP_API_LEVEL = "Platform.ApiLevel"; //$NON-NLS-1$
private static final String PROP_VERSION = "Platform.Version"; //$NON-NLS-1$
private final String mVersion;
private final int mApiLevel;
private final AndroidVersion mVersion;
private final String mVersionName;
/**
* Creates a new platform package from the attributes and elements of the given XML node.
@@ -47,8 +47,13 @@ public class PlatformPackage extends Package {
*/
PlatformPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {
super(source, packageNode, licenses);
mVersion = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VERSION);
mApiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);
mVersionName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VERSION);
int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);
String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_API_CODENAME);
if (codeName.length() == 0) {
codeName = null;
}
mVersion = new AndroidVersion(apiLevel, codeName);
}
/**
@@ -60,7 +65,7 @@ public class PlatformPackage extends Package {
PlatformPackage(IAndroidTarget target, Properties props) {
super( null, //source
props, //properties
0, //revision
target.getRevision(), //revision
null, //license
target.getDescription(), //description
null, //descUrl
@@ -69,37 +74,43 @@ public class PlatformPackage extends Package {
target.getLocation() //archiveOsPath
);
mApiLevel = target.getApiVersionNumber();
mVersion = target.getApiVersionName();
mVersion = target.getVersion();
mVersionName = target.getVersionName();
}
/**
* Save the properties of the current packages in the given {@link Properties} object.
* These properties will later be give the constructor that takes a {@link Properties} object.
* These properties will later be given to a constructor that takes a {@link Properties} object.
*/
@Override
void saveProperties(Properties props) {
super.saveProperties(props);
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
props.setProperty(PROP_VERSION, mVersion);
mVersion.saveProperties(props);
props.setProperty(PROP_VERSION, mVersionName);
}
/** Returns the version, a string, for platform packages. */
public String getVersion() {
return mVersion;
public String getVersionName() {
return mVersionName;
}
/** Returns the api-level, an int > 0, for platform, add-on and doc packages. */
public int getApiLevel() {
return mApiLevel;
// FIXME: return the AndroidVersion instead.
return mVersion.getApiLevel();
}
/** Returns a short description for an {@link IDescription}. */
@Override
public String getShortDescription() {
if (mVersion.isPreview()) {
return String.format("SDK Platform Android %1$s (Preview)",
getVersionName());
}
return String.format("SDK Platform Android %1$s, API %2$d",
getVersion(),
getVersionName(),
getApiLevel());
}
@@ -128,17 +139,17 @@ public class PlatformPackage extends Package {
@Override
public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
// First find if this add-on is already installed. If so, reuse the same directory.
// First find if this platform is already installed. If so, reuse the same directory.
for (IAndroidTarget target : sdkManager.getTargets()) {
if (target.isPlatform() &&
target.getApiVersionNumber() == getApiLevel() &&
target.getApiVersionName().equals(getVersion())) {
target.getVersion().equals(mVersion) &&
target.getVersionName().equals(getVersionName())) {
return new File(target.getLocation());
}
}
File platforms = new File(osSdkRoot, SdkConstants.FD_PLATFORMS);
File folder = new File(platforms, String.format("android-%s", getVersion())); //$NON-NLS-1$
File folder = new File(platforms, String.format("android-%s", getVersionName())); //$NON-NLS-1$
return folder;
}
@@ -162,7 +173,7 @@ public class PlatformPackage extends Package {
}
PlatformPackage newPkg = (PlatformPackage) replacementPackage;
return newPkg.getVersion().equalsIgnoreCase(this.getVersion()) &&
return newPkg.getVersionName().equalsIgnoreCase(this.getVersionName()) &&
newPkg.getApiLevel() == this.getApiLevel() &&
newPkg.getRevision() > this.getRevision();
}

View File

@@ -63,6 +63,8 @@ public class SdkRepository {
public static final String NODE_VERSION = "version"; //$NON-NLS-1$
/** The api-level, an int > 0, for platform, add-on and doc packages. */
public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$
/** The api-codename, a string, for platform packages. */
public static final String NODE_API_CODENAME = "api-codename"; //$NON-NLS-1$
/** The vendor, a string, for add-on packages. */
public static final String NODE_VENDOR = "vendor"; //$NON-NLS-1$
/** The name, a string, for add-on packages or for libraries. */

View File

@@ -52,6 +52,8 @@
<xsd:element name="version" type="xsd:normalizedString" />
<!-- The Android API Level for the platform. An int > 0. -->
<xsd:element name="api-level" type="xsd:positiveInteger" />
<!-- The optional codename for this platform, if it's a preview. -->
<xsd:element name="api-codename" type="xsd:string" minOccurs="0" />
<!-- The revision, an int > 0, incremented each time a new
package is generated. -->

View File

@@ -157,6 +157,24 @@
<sdk:uses-license ref="license2" />
</sdk:add-on>
<sdk:platform>
<sdk:version>Pastry</sdk:version>
<sdk:api-level>5</sdk:api-level>
<sdk:api-codename>Pastry</sdk:api-codename>
<sdk:revision>3</sdk:revision>
<sdk:uses-license ref="license1" />
<sdk:description>Preview version for Pastry</sdk:description>
<sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
<!-- The archives node is mandatory and it cannot be empty. -->
<sdk:archives>
<sdk:archive os="any">
<sdk:size>65536</sdk:size>
<sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
<sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
</sdk:archive>
</sdk:archives>
</sdk:platform>
<sdk:tool>
<sdk:revision>1</sdk:revision>
<sdk:description>Some optional description</sdk:description>

View File

@@ -273,14 +273,14 @@ final class AvdCreationDialog extends Dialog {
for (IAndroidTarget target : sdkManager.getTargets()) {
String name;
if (target.isPlatform()) {
name = String.format("%s - API Level %d",
name = String.format("%s - API Level %s",
target.getName(),
target.getApiVersionNumber());
target.getVersion().getApiString());
} else {
name = String.format("%s (%s) - API Level %d",
name = String.format("%s (%s) - API Level %s",
target.getName(),
target.getVendor(),
target.getApiVersionNumber());
target.getVersion().getApiString());
}
mCurrentTargets.put(name, target);
mTargetCombo.add(name);

View File

@@ -16,6 +16,7 @@
package com.android.sdkuilib.internal.widgets;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
@@ -106,8 +107,9 @@ final class AvdDetailsDialog extends Dialog {
displayValue(c, "Error:", mAvdInfo.getErrorMessage());
} else {
IAndroidTarget target = mAvdInfo.getTarget();
displayValue(c, "Target:", String.format("%s (API level %d)",
target.getName(), target.getApiVersionNumber()));
AndroidVersion version = target.getVersion();
displayValue(c, "Target:", String.format("%s (API level %s)",
target.getName(), version.getApiString()));
// display some extra values.
Map<String, String> properties = mAvdInfo.getProperties();

View File

@@ -723,8 +723,8 @@ public final class AvdSelector {
IAndroidTarget target = avd.getTarget();
if (target != null) {
item.setText(1, target.getFullName());
item.setText(2, target.getApiVersionName());
item.setText(3, Integer.toString(target.getApiVersionNumber()));
item.setText(2, target.getVersionName());
item.setText(3, target.getVersion().getApiString());
} else {
item.setText(1, "?");
item.setText(2, "?");

View File

@@ -323,8 +323,8 @@ public class SdkTargetSelector {
item.setData(target);
item.setText(0, target.getName());
item.setText(1, target.getVendor());
item.setText(2, target.getApiVersionName());
item.setText(3, Integer.toString(target.getApiVersionNumber()));
item.setText(2, target.getVersionName());
item.setText(3, target.getVersion().getApiString());
}
} else {
table.setEnabled(false);