diff --git a/code/smartphone.js b/code/smartphone.js index 8078cbd4..d01d2545 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -176,3 +176,18 @@ window.useAndroidPanes = function() { return (typeof android !== 'undefined' && android && android.addPane && window.isSmartphone()); } +if(typeof android !== 'undefined' && android && android.getFileRequestUrlPrefix) { + window.requestFile = function(callback) { + do { + var funcName = "onFileSelected" + parseInt(Math.random()*0xFFFF).toString(16); + } while(window[funcName] !== undefined) + + window[funcName] = function(filename, content) { + callback(decodeURIComponent(filename), atob(content)); + }; + var script = document.createElement('script'); + script.src = android.getFileRequestUrlPrefix() + funcName; + (document.body || document.head || document.documentElement).appendChild(script); + }; +} + diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_FileManager.java b/mobile/src/com/cradle/iitc_mobile/IITC_FileManager.java index 9bc8d73b..6fceb214 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_FileManager.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_FileManager.java @@ -1,11 +1,19 @@ package com.cradle.iitc_mobile; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; import android.content.SharedPreferences; import android.content.res.AssetManager; import android.net.Uri; import android.os.Environment; import android.preference.PreferenceManager; +import android.util.Base64; +import android.util.Base64OutputStream; import android.webkit.WebResourceResponse; +import android.widget.Toast; + +import com.cradle.iitc_mobile.IITC_Mobile.ResponseHandler; import org.json.JSONObject; @@ -16,7 +24,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; import java.net.URL; +import java.net.URLEncoder; import java.util.HashMap; public class IITC_FileManager { @@ -112,6 +123,10 @@ public class IITC_FileManager { return mAssetManager.open(filename); } + private WebResourceResponse getFileRequest(Uri uri) { + return new FileRequest(uri); + } + private WebResourceResponse getScript(Uri uri) { InputStream stream; try { @@ -179,6 +194,10 @@ public class IITC_FileManager { return os.toString(); } + public String getFileRequestPrefix() { + return "//file-request" + DOMAIN + "/"; + } + public String getIITCVersion() throws IOException { InputStream stream = getAssetFile("total-conversion-build.user.js"); @@ -196,8 +215,76 @@ public class IITC_FileManager { return getScript(uri); if ("user-plugin".equals(host)) return getUserPlugin(uri); + if ("file-request".equals(host)) + return getFileRequest(uri); Log.e("could not generate response for url: " + uri); return EMPTY; } + + private class FileRequest extends WebResourceResponse implements ResponseHandler { + private PipedOutputStream mStreamOut; + private String mFunctionName; + + private FileRequest(Uri uri) { + super("application/x-javascript", "UTF-8", new PipedInputStream()); + + try { + mStreamOut = new PipedOutputStream((PipedInputStream) getData()); + } catch (IOException e) { + Log.w(e); + } + + mFunctionName = uri.getPathSegments().get(0); + + final Intent target = new Intent(Intent.ACTION_GET_CONTENT); + target.setType("file/*"); + target.addCategory(Intent.CATEGORY_OPENABLE); + + // Create the chooser Intent + Intent intent = Intent.createChooser(target, "Choose file"); + try { + mIitc.startActivityForResult(intent, this); + } catch (ActivityNotFoundException e) { + Toast.makeText(mIitc, "No activity to select a file found." + + "Please install a file browser of your choice!", Toast.LENGTH_LONG).show(); + } + } + + @Override + public void onActivityResult(int resultCode, Intent data) { + try { + if (resultCode == Activity.RESULT_OK && data != null) { + Uri uri = data.getData(); + File file = new File(uri.getPath()); + + mStreamOut.write( + (mFunctionName + "('" + URLEncoder.encode(file.getName(), "UTF-8") + "', '").getBytes()); + + Base64OutputStream encoder = + new Base64OutputStream(mStreamOut, Base64.NO_CLOSE | Base64.NO_WRAP | Base64.DEFAULT); + + FileInputStream fileinput = new FileInputStream(file); + int c; + while ((c = fileinput.read()) != -1) + { + encoder.write(c); + } + encoder.close(); + + mStreamOut.write("');".getBytes()); + } + + mStreamOut.close(); + } catch (IOException e) { + Log.w(e); + + // try to close stream, but ignore errors + try { + mStreamOut.close(); + } catch (IOException e1) { + } + } + } + } } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java index 939599bf..cd7aee85 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java @@ -224,4 +224,9 @@ public class IITC_JSInterface { } }); } + + @JavascriptInterface + public String getFileRequestUrlPrefix() { + return mIitc.getFileManager().getFileRequestPrefix(); + } }