Back to project page Processing-Android-Eclipse-Demos.
The source code is released under:
MIT License
If you think the Android project Processing-Android-Eclipse-Demos listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ //w w w.jav a2s . c o m /* Part of the Processing project - http://processing.org Copyright (c) 2010-11 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.mode.android; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import processing.app.*; import processing.core.PApplet; import processing.data.XML; public class Manifest { static final String MANIFEST_XML = "AndroidManifest.xml"; static final String WORLD_OF_HURT_COMING = "Errors occurred while reading or writing " + MANIFEST_XML + ",\n" + "which means lots of things are likely to stop working properly.\n" + "To prevent losing any data, it's recommended that you use Save As??\n" + "to save a separate copy of your sketch, and the restart Processing."; static final String MULTIPLE_ACTIVITIES = "Processing only supports a single Activity in the AndroidManifest.xml\n" + "file. Only the first activity entry will be updated, and you better \n" + "hope that's the right one, smartypants."; // private Editor editor; private Sketch sketch; // entries we care about from the manifest file // private String packageName; /** the manifest data read from the file */ private XML xml; // public Manifest(Editor editor) { // this.editor = editor; // this.sketch = editor.getSketch(); // load(); // } public Manifest(Sketch sketch) { this.sketch = sketch; load(); } private String defaultPackageName() { // Sketch sketch = editor.getSketch(); return AndroidBuild.basePackage + "." + sketch.getName().toLowerCase(); } // called by other classes who want an actual package name // internally, we'll figure this out ourselves whether it's filled or not public String getPackageName() { String pkg = xml.getString("package"); return pkg.length() == 0 ? defaultPackageName() : pkg; } public void setPackageName(String packageName) { // this.packageName = packageName; // this is the package attribute in the root <manifest> object xml.setString("package", packageName); save(); } //writer.println(" <uses-permission android:name=\"android.permission.INTERNET\" />"); //writer.println(" <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />"); static final String PERMISSION_PREFIX = "android.permission."; public String[] getPermissions() { XML[] elements = xml.getChildren("uses-permission"); int count = elements.length; String[] names = new String[count]; for (int i = 0; i < count; i++) { names[i] = elements[i].getString("android:name").substring(PERMISSION_PREFIX.length()); } return names; } public void setPermissions(String[] names) { // just remove all the old ones for (XML kid : xml.getChildren("uses-permission")) { xml.removeChild(kid); } // ...and add the new kids back for (String name : names) { // PNode newbie = new PNodeXML("uses-permission"); // newbie.setString("android:name", PERMISSION_PREFIX + name); // xml.addChild(newbie); XML newbie = xml.addChild("uses-permission"); newbie.setString("android:name", PERMISSION_PREFIX + name); } save(); } public void setClassName(String className) { XML[] kids = xml.getChildren("application/activity"); if (kids.length != 1) { Base.showWarning("Don't touch that", MULTIPLE_ACTIVITIES, null); } XML activity = kids[0]; String currentName = activity.getString("android:name"); // only update if there are changes if (currentName == null || !currentName.equals(className)) { activity.setString("android:name", "." + className); save(); } } private void writeBlankManifest(final File file) { final PrintWriter writer = PApplet.createWriter(file); writer.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); writer.println("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "); // writer.println(" package=\"" + defaultPackageName() + "\" "); writer.println(" package=\"\" "); // Tempting to use 'preferExternal' here, but might annoy some users. // 'auto' at least enables it to be moved back and forth // http://developer.android.com/guide/appendix/install-location.html // writer.println(" android:installLocation=\"auto\" "); // Disabling this for now (0190), requires default.properties to use API 8 // This is just a number (like the Processing 'revision'). It should // increment with each release. Perhaps P5 should do this automatically // with each build or read/write of the manifest file? writer.println(" android:versionCode=\"1\" "); // This is the version number/name seen by users writer.println(" android:versionName=\"1.0\">"); // for now including this... we're wiring to a particular SDK version anyway... writer.println(" <uses-sdk android:minSdkVersion=\"" + AndroidBuild.sdkVersion + "\" />"); // writer.println(" <uses-sdk android:minSdkVersion=\"\" />"); // insert sdk version // writer.println(" <application android:label=\"@string/app_name\""); writer.println(" <application android:label=\"\""); // insert pretty name writer.println(" android:icon=\"@drawable/icon\""); writer.println(" android:debuggable=\"true\">"); // turns out label is not required for the activity, so nixing it // writer.println(" <activity android:name=\"\""); // insert class name prefixed w/ dot //// writer.println(" android:label=\"@string/app_name\">"); // pretty name // writer.println(" android:label=\"\">"); // activity/android:name should be the full name (package + class name) of // the actual activity class. or the package can be replaced by a single // dot as a prefix as an easier shorthand. writer.println(" <activity android:name=\"\">"); writer.println(" <intent-filter>"); writer.println(" <action android:name=\"android.intent.action.MAIN\" />"); writer.println(" <category android:name=\"android.intent.category.LAUNCHER\" />"); writer.println(" </intent-filter>"); writer.println(" </activity>"); writer.println(" </application>"); writer.println("</manifest>"); writer.flush(); writer.close(); } /** * Save a new version of the manifest info to the build location. * Also fill in any missing attributes that aren't yet set properly. */ protected void writeBuild(File file, String className, boolean debug) throws IOException { // write a copy to the build location save(file); // load the copy from the build location and start messing with it XML mf = null; try { mf = new XML(file); // package name, or default String p = mf.getString("package").trim(); if (p.length() == 0) { mf.setString("package", defaultPackageName()); } // app name and label, or the class name XML app = mf.getChild("application"); String label = app.getString("android:label"); if (label.length() == 0) { app.setString("android:label", className); } app.setString("android:debuggable", debug ? "true" : "false"); XML activity = app.getChild("activity"); // the '.' prefix is just an alias for the full package name // http://developer.android.com/guide/topics/manifest/activity-element.html#name activity.setString("android:name", "." + className); // this has to be right PrintWriter writer = PApplet.createWriter(file); writer.print(mf.toString()); writer.flush(); // mf.write(writer); writer.close(); } catch (Exception e) { e.printStackTrace(); } } protected void load() { // Sketch sketch = editor.getSketch(); // File manifestFile = new File(sketch.getFolder(), MANIFEST_XML); // XMLElement xml = null; File manifestFile = getManifestFile(); if (manifestFile.exists()) { try { xml = new XML(manifestFile); } catch (Exception e) { e.printStackTrace(); System.err.println("Problem reading AndroidManifest.xml, creating a new version"); // remove the old manifest file, rename it with date stamp long lastModified = manifestFile.lastModified(); String stamp = AndroidMode.getDateStamp(lastModified); File dest = new File(sketch.getFolder(), MANIFEST_XML + "." + stamp); boolean moved = manifestFile.renameTo(dest); if (!moved) { System.err.println("Could not move/rename " + manifestFile.getAbsolutePath()); System.err.println("You'll have to move or remove it before continuing."); return; } } } if (xml == null) { writeBlankManifest(manifestFile); try { xml = new XML(manifestFile); } catch (FileNotFoundException e) { System.err.println("Could not read " + manifestFile.getAbsolutePath()); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } } if (xml == null) { Base.showWarning("Error handling " + MANIFEST_XML, WORLD_OF_HURT_COMING, null); } // return xml; } protected void save() { save(getManifestFile()); } /** * Save to the sketch folder, so that it can be copied in later. */ protected void save(File file) { PrintWriter writer = PApplet.createWriter(file); // xml.write(writer); writer.print(xml.toString()); writer.flush(); writer.close(); } private File getManifestFile() { return new File(sketch.getFolder(), MANIFEST_XML); } }