From 00dc18a488189b7c56da206402702d7b0814c000 Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Fri, 17 Sep 2010 15:41:48 -0500 Subject: [PATCH] Convert FileUtils to plugin architecture. --- framework/src/com/phonegap/DroidGap.java | 4 +- framework/src/com/phonegap/FileUtils.java | 336 +++++++++++++++------- 2 files changed, 238 insertions(+), 102 deletions(-) diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java index 4786d357..56eeb0e7 100755 --- a/framework/src/com/phonegap/DroidGap.java +++ b/framework/src/com/phonegap/DroidGap.java @@ -82,7 +82,6 @@ public class DroidGap extends Activity { protected Boolean loadInWebView = false; private LinearLayout root; - private FileUtils fs; private BrowserKey mKey; public CallbackServer callbackServer; private PluginManager pluginManager; @@ -266,13 +265,11 @@ public class DroidGap extends Activity { private void bindBrowser(WebView appView) { this.callbackServer = new CallbackServer(); this.pluginManager = new PluginManager(appView, this); - this.fs = new FileUtils(appView, this); this.mKey = new BrowserKey(appView, this); // This creates the new javascript interfaces for PhoneGap appView.addJavascriptInterface(this.pluginManager, "PluginManager"); - appView.addJavascriptInterface(this.fs, "FileUtil"); appView.addJavascriptInterface(this.mKey, "BackButton"); appView.addJavascriptInterface(this.callbackServer, "CallbackServer"); @@ -296,6 +293,7 @@ public class DroidGap extends Activity { this.addService("Camera", "com.phonegap.CameraLauncher"); this.addService("Contacts", "com.phonegap.ContactManager"); this.addService("Crypto", "com.phonegap.CryptoHandler"); + this.addService("File", "com.phonegap.FileUtils"); this.addService("Location", "com.phonegap.GeoBroker"); this.addService("Network Status", "com.phonegap.NetworkManager"); this.addService("Storage", "com.phonegap.Storage"); diff --git a/framework/src/com/phonegap/FileUtils.java b/framework/src/com/phonegap/FileUtils.java index 3f54f9b6..1e538080 100644 --- a/framework/src/com/phonegap/FileUtils.java +++ b/framework/src/com/phonegap/FileUtils.java @@ -2,123 +2,261 @@ package com.phonegap; import java.io.*; +import org.apache.commons.codec.binary.Base64; +import org.json.JSONArray; +import org.json.JSONException; + +import com.phonegap.api.Plugin; +import com.phonegap.api.PluginResult; + +import android.content.Intent; import android.webkit.WebView; -public class FileUtils { +/** + * This class provides SD card file and directory services to JavaScript. + * Only files on the SD card can be accessed. + */ +public class FileUtils implements Plugin { + + public static int NOT_FOUND_ERR = 8; + public static int SECURITY_ERR = 18; + public static int ABORT_ERR = 20; + + public static int NOT_READABLE_ERR = 24; + public static int ENCODING_ERR = 26; - WebView mView; + WebView webView; // WebView object + DroidGap ctx; // DroidGap object + FileReader f_in; FileWriter f_out; - public FileUtils(WebView view, DroidGap gap) - { - mView = view; + /** + * Constructor. + */ + public FileUtils() { + System.out.println("FileUtils()"); } - - public int testSaveLocationExists(){ - if (DirectoryManager.testSaveLocationExists()) - return 0; - else - return 1; - } - - public long getFreeDiskSpace(){ - long freeDiskSpace=DirectoryManager.getFreeDiskSpace(); - return freeDiskSpace; - } - public int testFileExists(String file){ - if (DirectoryManager.testFileExists(file)) - return 0; - else - return 1; - } - - public int testDirectoryExists(String file){ - if (DirectoryManager.testFileExists(file)) - return 0; - else - return 1; - } - - /** - * Delete a specific directory. - * Everyting in side the directory would be gone. - * TODO: JavaScript Call backs for success and error handling + /** + * Sets the context of the Command. This can then be used to do things like + * get file paths associated with the Activity. + * + * @param ctx The context of the main Activity. */ - public int deleteDirectory (String dir){ - if (DirectoryManager.deleteDirectory(dir)) - return 0; - else - return 1; - } - + public void setContext(DroidGap ctx) { + this.ctx = ctx; + } - /** - * Delete a specific file. - * TODO: JavaScript Call backs for success and error handling + /** + * Sets the main View of the application, this is the WebView within which + * a PhoneGap app runs. + * + * @param webView The PhoneGap WebView */ - public int deleteFile (String file){ - if (DirectoryManager.deleteFile(file)) - return 0; - else - return 1; - } - + public void setView(WebView webView) { + this.webView = webView; + } - /** - * Create a new directory. - * TODO: JavaScript Call backs for success and error handling + /** + * Executes the request and returns CommandResult. + * + * @param action The command to execute. + * @param args JSONArry of arguments for the command. + * @return A CommandResult object with a status and message. */ - public int createDirectory(String dir){ - if (DirectoryManager.createDirectory(dir)) - return 0; - else - return 1; - } - - public String read(String filename) - { - String data = ""; - String output = ""; - try { - FileInputStream fstream = new FileInputStream(filename); - DataInputStream in = new DataInputStream(fstream); - while (in.available() !=0) - { - data += in.readLine(); - } - - } catch (FileNotFoundException e) { - data = "FAIL: File not found"; - } catch (IOException e) { - data = "FAIL: IO ERROR"; - } + public PluginResult execute(String action, JSONArray args) { + PluginResult.Status status = PluginResult.Status.OK; + String result = ""; + //System.out.println("FileUtils.execute("+action+")"); - //mView.loadUrl("javascript:navigator.FileReader.hasRead('" + data + "')"); + try { + if (action.equals("testSaveLocationExists")) { + boolean b = DirectoryManager.testSaveLocationExists(); + return new PluginResult(status, b); + } + else if (action.equals("getFreeDiskSpace")) { + long l = DirectoryManager.getFreeDiskSpace(); + return new PluginResult(status, l); + } + else if (action.equals("testFileExists")) { + boolean b = DirectoryManager.testFileExists(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("testDirectoryExists")) { + boolean b = DirectoryManager.testFileExists(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("deleteDirectory")) { + boolean b = DirectoryManager.deleteDirectory(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("deleteFile")) { + boolean b = DirectoryManager.deleteFile(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("createDirectory")) { + boolean b = DirectoryManager.createDirectory(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("readAsText")) { + try { + String s = this.readAsText(args.getString(0), args.getString(1)); + return new PluginResult(status, s); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR); + } catch (IOException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR); + } + } + else if (action.equals("readAsDataURL")) { + try { + String s = this.readAsDataURL(args.getString(0)); + return new PluginResult(status, s); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR); + } catch (IOException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR); + } + } + else if (action.equals("writeAsText")) { + try { + this.writeAsText(args.getString(0), args.getString(1), args.getBoolean(2)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR); + } catch (IOException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR); + } + } + return new PluginResult(status, result); + } catch (JSONException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.JSON_EXCEPTION); + } + } + + /** + * Identifies if action to be executed returns a value and should be run synchronously. + * + * @param action The action to execute + * @return T=returns value + */ + public boolean isSynch(String action) { + if (action.equals("read")) { + return false; + } + else if (action.equals("write")) { + return false; + } + return true; + } + + /** + * Called when the system is about to start resuming a previous activity. + */ + public void onPause() { + } + + /** + * Called when the activity will start interacting with the user. + */ + public void onResume() { + } + + /** + * Called by AccelBroker when listener is to be shut down. + * Stop listener. + */ + public void onDestroy() { + } + + /** + * Called when an activity you launched exits, giving you the requestCode you started it with, + * the resultCode it returned, and any additional data from it. + * + * @param requestCode The request code originally supplied to startActivityForResult(), + * allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + } + + //-------------------------------------------------------------------------- + // LOCAL METHODS + //-------------------------------------------------------------------------- + + /** + * Read content of text file. + * + * @param filename The name of the file. + * @param encoding The encoding to return contents as. Typical value is UTF-8. + * (see http://www.iana.org/assignments/character-sets) + * @return Contents of file. + * @throws FileNotFoundException, IOException + */ + public String readAsText(String filename, String encoding) throws FileNotFoundException, IOException { + System.out.println("FileUtils.readAsText("+filename+", "+encoding+")"); + StringBuilder data = new StringBuilder(); + FileInputStream fis = new FileInputStream(filename); + BufferedReader reader = new BufferedReader(new InputStreamReader(fis, encoding), 1024); + String line; + while ((line = reader.readLine()) != null) { + data.append(line); + } + return data.toString(); + } + + /** + * Read content of text file and return as base64 encoded data url. + * + * @param filename The name of the file. + * @return Contents of file = data:;base64, + * @throws FileNotFoundException, IOException + */ + public String readAsDataURL(String filename) throws FileNotFoundException, IOException { + byte[] bytes = new byte[1000]; + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename), 1024); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int numRead = 0; + while ((numRead = bis.read(bytes, 0, 1000)) >= 0) { + bos.write(bytes, 0, numRead); + } + + // Determine content type from file name + // TODO + String contentType = ""; + + byte[] base64 = Base64.encodeBase64(bos.toByteArray()); + String data = "data:" + contentType + ";base64," + new String(base64); return data; } - public int write(String filename, String data, boolean append) - { - String FilePath= filename; - try { - byte [] rawData = data.getBytes(); - ByteArrayInputStream in = new ByteArrayInputStream(rawData); - FileOutputStream out= new FileOutputStream(FilePath, append); - byte buff[] = new byte[rawData.length]; - in.read(buff, 0, buff.length); - out.write(buff, 0, rawData.length); - out.flush(); - out.close(); - //mView.loadUrl("javascript:navigator.FileReader.onsuccess('File written')"); - } catch (Exception e) { - //mView.loadUrl("javascript:navigator.FileReader.onerror('Fail')"); - // So, do we just return -1 at this point! - return -1; - } - return 0; + /** + * Write contents of file. + * + * @param filename The name of the file. + * @param data The contents of the file. + * @param append T=append, F=overwrite + * @throws FileNotFoundException, IOException + */ + public void writeAsText(String filename, String data, boolean append) throws FileNotFoundException, IOException { + String FilePath= filename; + byte [] rawData = data.getBytes(); + ByteArrayInputStream in = new ByteArrayInputStream(rawData); + FileOutputStream out= new FileOutputStream(FilePath, append); + byte buff[] = new byte[rawData.length]; + in.read(buff, 0, buff.length); + out.write(buff, 0, rawData.length); + out.flush(); + out.close(); }