import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.project.AndroidNature;
import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage.IMainInfo;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewTestProjectCreationPage.TestInfo;
SdkConstants.FD_ASSETS + AndroidConstants.WS_SEP;
private static final String DRAWABLE_DIRECTORY =
SdkConstants.FD_DRAWABLE + AndroidConstants.WS_SEP;
+ private static final String DRAWABLE_HDPI_DIRECTORY =
+ SdkConstants.FD_DRAWABLE + "-" + Density.HIGH.getValue() + AndroidConstants.WS_SEP; //$NON-NLS-1$
+ private static final String DRAWABLE_MDPI_DIRECTORY =
+ SdkConstants.FD_DRAWABLE + "-" + Density.MEDIUM.getValue() + AndroidConstants.WS_SEP; //$NON-NLS-1$
+ private static final String DRAWABLE_LDPI_DIRECTORY =
+ SdkConstants.FD_DRAWABLE + "-" + Density.LOW.getValue() + AndroidConstants.WS_SEP; //$NON-NLS-1$
private static final String LAYOUT_DIRECTORY =
SdkConstants.FD_LAYOUT + AndroidConstants.WS_SEP;
private static final String VALUES_DIRECTORY =
+ "strings.template"; //$NON-NLS-1$
private static final String TEMPLATE_STRING = TEMPLATES_DIRECTORY
+ "string.template"; //$NON-NLS-1$
- private static final String ICON = "icon.png"; //$NON-NLS-1$
+ private static final String PROJECT_ICON = "icon.png"; //$NON-NLS-1$
+ private static final String ICON_HDPI = "icon_hdpi.png"; //$NON-NLS-1$
+ private static final String ICON_MDPI = "icon_mdpi.png"; //$NON-NLS-1$
+ private static final String ICON_LDPI = "icon_ldpi.png"; //$NON-NLS-1$
private static final String STRINGS_FILE = "strings.xml"; //$NON-NLS-1$
private static final String[] DEFAULT_DIRECTORIES = new String[] {
BIN_DIRECTORY, RES_DIRECTORY, ASSETS_DIRECTORY };
private static final String[] RES_DIRECTORIES = new String[] {
- DRAWABLE_DIRECTORY, LAYOUT_DIRECTORY, VALUES_DIRECTORY};
+ DRAWABLE_DIRECTORY, LAYOUT_DIRECTORY, VALUES_DIRECTORY };
+ private static final String[] RES_DENSITY_ENABLED_DIRECTORIES = new String[] {
+ DRAWABLE_HDPI_DIRECTORY, DRAWABLE_MDPI_DIRECTORY, DRAWABLE_LDPI_DIRECTORY,
+ LAYOUT_DIRECTORY, VALUES_DIRECTORY };
private static final String PROJECT_LOGO_LARGE = "icons/android_large.png"; //$NON-NLS-1$
private static final String JAVA_ACTIVITY_TEMPLATE = "java_file.template"; //$NON-NLS-1$
Map<String, String> dictionary)
throws CoreException, IOException {
+ // get the project target
+ IAndroidTarget target = (IAndroidTarget) parameters.get(PARAM_SDK_TARGET);
+ boolean legacy = target.getVersion().getApiLevel() < 4;
+
// Create project and open it
project.create(description, new SubProgressMonitor(monitor, 10));
if (monitor.isCanceled()) throw new OperationCanceledException();
addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolders, monitor);
// Create the resource folders in the project if they don't already exist.
- addDefaultDirectories(project, RES_DIRECTORY, RES_DIRECTORIES, monitor);
+ if (legacy) {
+ addDefaultDirectories(project, RES_DIRECTORY, RES_DIRECTORIES, monitor);
+ } else {
+ addDefaultDirectories(project, RES_DIRECTORY, RES_DENSITY_ENABLED_DIRECTORIES, monitor);
+ }
// Setup class path: mark folders as source folders
IJavaProject javaProject = JavaCore.create(project);
addManifest(project, parameters, dictionary, monitor);
// add the default app icon
- addIcon(project, monitor);
+ addIcon(project, legacy, monitor);
// Create the default package components
addSampleCode(project, sourceFolders[0], parameters, dictionary, monitor);
// the currently-empty current list.
desc.setReferencedProjects(new IProject[] { refProject });
- project.setDescription(desc, IResource.KEEP_HISTORY, new SubProgressMonitor(monitor, 10));
+ project.setDescription(desc, IResource.KEEP_HISTORY,
+ new SubProgressMonitor(monitor, 10));
IClasspathEntry entry = JavaCore.newProjectEntry(
refProject.getFullPath(), //path
}
}
- Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET),
- null /* apkConfigMap*/);
+ Sdk.getCurrent().setProject(project, target, null /* apkConfigMap*/);
// Fix the project to make sure all properties are as expected.
// Necessary for existing projects and good for new ones to.
* Adds default application icon to the project.
*
* @param project The Java Project to update.
+ * @param legacy whether we're running in legacy mode (no density support)
* @param monitor An existing monitor.
* @throws CoreException if the method fails to update the project.
*/
- private void addIcon(IProject project, IProgressMonitor monitor)
+ private void addIcon(IProject project, boolean legacy, IProgressMonitor monitor)
throws CoreException {
- IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
- + DRAWABLE_DIRECTORY + AndroidConstants.WS_SEP + ICON);
- if (!file.exists()) {
- // read the content from the template
- byte[] buffer = AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON);
-
- // if valid
- if (buffer != null) {
- // Save in the project
- InputStream stream = new ByteArrayInputStream(buffer);
- file.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
+ if (legacy) { // density support
+ // do medium density icon only, in the default drawable folder.
+ IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ + DRAWABLE_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+ if (!file.exists()) {
+ addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_MDPI), monitor);
+ }
+ } else {
+ // do all 3 icons.
+ IFile file;
+
+ // high density
+ file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ + DRAWABLE_HDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+ if (!file.exists()) {
+ addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_HDPI), monitor);
+ }
+
+ // medium density
+ file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ + DRAWABLE_MDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+ if (!file.exists()) {
+ addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_MDPI), monitor);
+ }
+
+ // low density
+ file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ + DRAWABLE_LDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+ if (!file.exists()) {
+ addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_LDPI), monitor);
}
}
}
/**
+ * Creates a file from a data source.
+ * @param dest the file to write
+ * @param source the content of the file.
+ * @param monitor the progress monitor
+ * @throws CoreException
+ */
+ private void addFile(IFile dest, byte[] source, IProgressMonitor monitor) throws CoreException {
+ if (source != null) {
+ // Save in the project
+ InputStream stream = new ByteArrayInputStream(source);
+ dest.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
+ }
+ }
+
+ /**
* Creates the package folder and copies the sample code in the project.
*
* @param project The Java Project to update.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
private final static String PH_ACTIVITY_TESTED_CLASS_NAME = "ACTIVITY_TESTED_CLASS_NAME";
/** Project name substitution string used in template files, i.e. "PROJECT_NAME". */
private final static String PH_PROJECT_NAME = "PROJECT_NAME";
+ /** Application icon substitution string used in the manifest template */
+ private final static String PH_ICON = "ICON";
/** Pattern for characters accepted in a project name. Since this will be used as a
* directory name, we're being a bit conservative on purpose: dot and space cannot be used. */
/** default UID. This will not be serialized anyway. */
private static final long serialVersionUID = 1L;
+ @SuppressWarnings("unused")
ProjectCreateException(String message) {
super(message);
}
}
// create other useful folders
- File resourceFodler = createDirs(projectFolder, SdkConstants.FD_RESOURCES);
+ File resourceFolder = createDirs(projectFolder, SdkConstants.FD_RESOURCES);
createDirs(projectFolder, SdkConstants.FD_OUTPUT);
createDirs(projectFolder, SdkConstants.FD_NATIVE_LIBS);
if (isTestProject == false) {
/* Make res files only for non test projects */
- File valueFolder = createDirs(resourceFodler, SdkConstants.FD_VALUES);
+ File valueFolder = createDirs(resourceFolder, SdkConstants.FD_VALUES);
installTemplate("strings.template", new File(valueFolder, "strings.xml"),
keywords, target);
- File layoutFolder = createDirs(resourceFodler, SdkConstants.FD_LAYOUT);
+ File layoutFolder = createDirs(resourceFolder, SdkConstants.FD_LAYOUT);
installTemplate("layout.template", new File(layoutFolder, "main.xml"),
keywords, target);
+
+ // create the icons
+ if (installIcons(resourceFolder, target)) {
+ keywords.put(PH_ICON, "android:icon=\"@drawable/icon\"");
+ } else {
+ keywords.put(PH_ICON, "");
+ }
}
/* Make AndroidManifest.xml and build.xml files */
String line;
while ((line = in.readLine()) != null) {
- for (String key : placeholderMap.keySet()) {
- line = line.replace(key, placeholderMap.get(key));
+ if (placeholderMap != null) {
+ for (String key : placeholderMap.keySet()) {
+ line = line.replace(key, placeholderMap.get(key));
+ }
}
out.write(line);
}
/**
+ * Installs the project icons.
+ * @param resourceFolder the resource folder
+ * @param target the target of the project.
+ * @return true if any icon was installed.
+ */
+ private boolean installIcons(File resourceFolder, IAndroidTarget target)
+ throws ProjectCreateException {
+ // query the target for its template directory
+ String templateFolder = target.getPath(IAndroidTarget.TEMPLATES);
+
+ boolean installedIcon = false;
+
+ installedIcon |= installIcon(templateFolder, "icon_hdpi.png", resourceFolder, "drawable-hdpi");
+ installedIcon |= installIcon(templateFolder, "icon_mdpi.png", resourceFolder, "drawable-mdpi");
+ installedIcon |= installIcon(templateFolder, "icon_ldpi.png", resourceFolder, "drawable-ldpi");
+
+ return installedIcon;
+ }
+
+ /**
+ * Installs an Icon in the project.
+ * @return true if the icon was installed.
+ */
+ private boolean installIcon(String templateFolder, String iconName, File resourceFolder,
+ String folderName) throws ProjectCreateException {
+ File icon = new File(templateFolder, iconName);
+ if (icon.exists()) {
+ File drawable = createDirs(resourceFolder, folderName);
+ installBinaryFile(icon, new File(drawable, "icon.png"));
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Installs a binary file
+ * @param source the source file to copy
+ * @param destination the destination file to write
+ */
+ private void installBinaryFile(File source, File destination) {
+ byte[] buffer = new byte[8192];
+
+ FileInputStream fis = null;
+ FileOutputStream fos = null;
+ try {
+ fis = new FileInputStream(source);
+ fos = new FileOutputStream(destination);
+
+ int read;
+ while ((read = fis.read(buffer)) != -1) {
+ fos.write(buffer, 0, read);
+ }
+
+ } catch (FileNotFoundException e) {
+ // shouldn't happen since we check before.
+ } catch (IOException e) {
+ new ProjectCreateException(e, "Failed to read binary file: %1$s",
+ source.getAbsolutePath());
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ }
+
+ /**
* Prints a message unless silence is enabled.
* <p/>
* This is just a convenience wrapper around {@link ISdkLog#printf(String, Object...)} from