/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.jme3.gde.android; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.List; import org.netbeans.api.project.Project; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor.Message; import org.openide.filesystems.FileChooserBuilder; import org.openide.filesystems.FileLock; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; import org.openide.util.NbPreferences; import org.openide.util.Utilities; /** * * @author normenhansen */ public class AndroidSdkTool { /** * Starts the Android target configuration utility. */ public static void startAndroidTool() { startAndroidTool(false); } public static void startAndroidTool(boolean modal) { final String path = getAndroidToolPath(); if (path == null) { return; } Thread thread = new Thread(new Runnable() { @Override public void run() { String[] command = new String[]{path}; ProcessBuilder builder = new ProcessBuilder(command); try { Process proc = builder.start(); OutputReader outReader = new OutputReader(proc.getInputStream()); OutputReader errReader = new OutputReader(proc.getErrorStream()); outReader.start(); errReader.start(); proc.waitFor(); } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } }); if (modal) { thread.run(); } else { thread.start(); } } /** * Returns a FileObject for the android SDK folder, null if none is specified * @return */ public static FileObject getSdkFolder() { String path = getSdkPath(); if (path == null) { return null; } FileObject fileObj = FileUtil.toFileObject(new File(path)); if (fileObj == null) { return null; } return fileObj; } /** * Returns a String with the path to the SDK or null if none is specified. * @return */ public static String getSdkPath() { String path = NbPreferences.forModule(AndroidSdkTool.class).get("sdk_path", null); if (path == null) { FileChooserBuilder builder = new FileChooserBuilder(AndroidSdkTool.class); builder.setTitle("Please select Android SDK Folder"); builder.setDirectoriesOnly(true); File file = builder.showOpenDialog(); if (file != null) { FileObject folder = FileUtil.toFileObject(file); if (folder.getFileObject("tools") == null) { Message msg = new NotifyDescriptor.Message( "Not a valid SDK folder!", NotifyDescriptor.ERROR_MESSAGE); DialogDisplayer.getDefault().notifyLater(msg); } else { String name = file.getPath(); NbPreferences.forModule(AndroidSdkTool.class).put("sdk_path", name); return name; } } } else { return path; } return null; } /** * Returns a string with the path to the android tool, specific for platform (.exe for windows) * @return */ public static String getAndroidToolPath() { FileObject executable = null; FileObject folder = getSdkFolder(); if (folder == null) { return null; } if (Utilities.isWindows()) { executable = folder.getFileObject("tools/android.bat"); } else { executable = folder.getFileObject("tools/android"); } if (executable != null) { return FileUtil.toFile(executable).getPath(); } else { return null; } } /** * Gets a list of android targets registered in the SDK * @return */ public static List getTargetList() { ArrayList list = new ArrayList(); final String path = getAndroidToolPath(); if (path == null) { return list; } String[] command = new String[]{path, "list", "targets"}; ProcessBuilder builder = new ProcessBuilder(command); try { Process proc = builder.start(); ListReader outReader = new ListReader(proc.getInputStream(), list); OutputReader errReader = new OutputReader(proc.getErrorStream()); outReader.start(); errReader.start(); proc.waitFor(); } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { Exceptions.printStackTrace(ex); } return list; } //TODO: check mainJmeClass public static void checkProject(Project project, String target, String name, String activity, String packag, String mainJmeClass) { final String path = getAndroidToolPath(); if (path == null) { return; } FileObject folder = project.getProjectDirectory().getFileObject("mobile"); if (folder == null) { try { folder = project.getProjectDirectory().createFolder("mobile"); createProject(project, target, name, activity, packag, mainJmeClass); } catch (IOException ex) { Exceptions.printStackTrace(ex); return; } } else { updateProject(project, target, name); } } public static void createProject(Project project, String target, String name, String activity, String packag, String mainJmeClass) { final String path = getAndroidToolPath(); if (path == null) { return; } FileObject folder = project.getProjectDirectory().getFileObject("mobile"); if (folder == null) { try { folder = project.getProjectDirectory().createFolder("mobile"); } catch (IOException ex) { Exceptions.printStackTrace(ex); return; } } String[] command = new String[]{path, "create", "project", "--target", target, "--name", name, "--path", FileUtil.toFile(folder).getPath(), "--activity", activity, "--package", packag}; ProcessBuilder builder = new ProcessBuilder(command); FileLock lock = null; try { Process proc = builder.start(); OutputReader outReader = new OutputReader(proc.getInputStream()); OutputReader errReader = new OutputReader(proc.getErrorStream()); outReader.start(); errReader.start(); proc.waitFor(); String mainActName = "mobile/src/" + packag.replaceAll("\\.", "/") + "/MainActivity.java"; FileObject mainAct = project.getProjectDirectory().getFileObject(mainActName); if (mainAct != null) { lock = mainAct.lock(); OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(mainAct.getOutputStream(lock))); out.write(mainActivityString(mainJmeClass)); out.close(); lock.releaseLock(); } else { throw new IOException("Cannot find " + mainAct); } } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { if (lock != null) { lock.releaseLock(); } Exceptions.printStackTrace(ex); } } public static void updateProject(Project project, String target, String name) { final String path = getAndroidToolPath(); if (path == null) { return; } FileObject folder = project.getProjectDirectory().getFileObject("mobile"); if (folder == null) { return; } String[] command = new String[]{path, "update", "project", "--target", target, "--name", name, "--path", FileUtil.toFile(folder).getPath()}; ProcessBuilder builder = new ProcessBuilder(command); try { Process proc = builder.start(); OutputReader outReader = new OutputReader(proc.getInputStream()); OutputReader errReader = new OutputReader(proc.getErrorStream()); outReader.start(); errReader.start(); proc.waitFor(); } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } private static String mainActivityString(String mainClass) { String str = "import com.jme3.app.AndroidHarness;\n" + "import android.content.pm.ActivityInfo;" + "import com.jme3.system.android.AndroidConfigChooser.ConfigType;" + "public class MainActivity extends AndroidHarness{\n" + " public MainActivity(){\n" + " // Set the application class to run\n" + " appClass = \"" + mainClass + "\";\n" + " //eglConfigType = ConfigType.FASTEST; // Default\n" + " eglConfigType = ConfigType.BEST;\n" + " // Exit Dialog title & message\n" + " exitDialogTitle = \"Exit?\";\n" + " exitDialogMessage = \"Press Yes\";\n" + " // Edit: 25.06.2011: Enable verbose logging\n" + " eglConfigVerboseLogging= true;\n" + " // Edit: 30.06.2011: Choose screen orientation\n" + " screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;\n" + " // Edit 12.07.2011: Invert the MouseEvents X (default = true)\n" + " mouseEventsInvertX = true;\n" + " // Edit 05.07.2011: Invert the MouseEvents Y (default = true)\n" + " mouseEventsInvertY = true;\n" + " }\n" + "}\n"; return str; } public static class AndroidTarget { private int id; private String name; private String title; private String platform; private int apiLevel; private int revision; private String skins; public AndroidTarget() { } public AndroidTarget(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPlatform() { return platform; } public void setPlatform(String platform) { this.platform = platform; } public int getApiLevel() { return apiLevel; } public void setApiLevel(int apiLevel) { this.apiLevel = apiLevel; } public int getRevision() { return revision; } public void setRevision(int revision) { this.revision = revision; } public String getSkins() { return skins; } public void setSkins(String skins) { this.skins = skins; } @Override public String toString() { return getTitle(); } @Override public boolean equals(Object obj) { if (obj instanceof String && getName() != null) { return getName().equals(obj); } else { return super.equals(obj); } } } }