From af54b6483e3a47ee7f5a44a3faa946d0bbfd44cd Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Wed, 7 Feb 2024 00:05:07 +0000 Subject: [PATCH] Some success exporting and importing apps on android. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4826 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- core/client.js | 9 +-- .../unprompted/tildefriends/MainActivity.java | 70 +++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/core/client.js b/core/client.js index 6ffc0ed3..3233adad 100644 --- a/core/client.js +++ b/core/client.js @@ -1042,11 +1042,11 @@ async function appExport() { zip.file(`${name}/${file}`, gFiles[file].buffer ?? gFiles[file].doc.doc.toString()); } let content = await zip.generateAsync({ - type: 'blob', + type: 'base64', compression: 'DEFLATE', }); let a = document.createElement('a'); - a.href = URL.createObjectURL(content); + a.href = `data:application/zip;base64,${content}`; a.download = `${owner}_${name}.zip`; a.click(); } @@ -1079,10 +1079,11 @@ async function appImport() { try { for (let file of input.files) { if (file.type != 'application/zip') { - console.log('This does not look like a .zip.'); + console.log(`This does not look like a .zip (${file.type}).`); continue; } - let buffer = await file.arrayBuffer(); + let buffer = new Uint8Array(await file.arrayBuffer()); + console.log('ZIP', file.name, file.type, buffer, buffer?.byteLength, buffer?.length); let zip = new JsZip(); await zip.loadAsync(buffer); let app_object; diff --git a/src/android/com/unprompted/tildefriends/MainActivity.java b/src/android/com/unprompted/tildefriends/MainActivity.java index 5e1daf9e..64c94320 100644 --- a/src/android/com/unprompted/tildefriends/MainActivity.java +++ b/src/android/com/unprompted/tildefriends/MainActivity.java @@ -2,30 +2,39 @@ package com.unprompted.tildefriends; import android.app.Activity; import android.app.AlertDialog; +import android.app.DownloadManager; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.CountDownTimer; +import android.os.Environment; import android.os.StrictMode; import android.os.SystemClock; import android.os.strictmode.Violation; +import android.util.Base64; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.Window; +import android.webkit.CookieManager; +import android.webkit.DownloadListener; import android.webkit.JsResult; +import android.webkit.URLUtil; +import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.TextView; +import android.widget.Toast; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.OutputStream; import java.io.FileReader; import java.io.InputStream; import java.lang.Process; @@ -44,6 +53,9 @@ public class MainActivity extends Activity { Process process; Thread thread; + private ValueCallback upload_message; + private final static int FILECHOOSER_RESULT = 1; + @Override protected void onCreate(Bundle savedInstanceState) { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() @@ -134,6 +146,38 @@ public class MainActivity extends Activity { web_view.getSettings().setDatabaseEnabled(true); web_view.getSettings().setDomStorageEnabled(true); + web_view.setDownloadListener(new DownloadListener() { + public void onDownloadStart(String url, String userAgent, String content_disposition, String mime_type, long content_length) { + Log.w("tildefriends", "Let's download: " + url + " (" + content_disposition + ")"); + String file_name = URLUtil.guessFileName(url, content_disposition, mime_type); + if (url.startsWith("data:") && url.indexOf(',') != -1) { + String b64 = url.substring(url.indexOf(',') + 1); + byte[] data = Base64.decode(b64, Base64.DEFAULT); + Log.w("tildefriends", "Downloaded " + data.length + " bytes."); + File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + try (OutputStream stream = new FileOutputStream(new File(path, file_name))) { + stream.write(data); + } catch (java.io.IOException e) { + Log.w("tildefriends", "IOException: " + e.toString()); + } + Toast.makeText(getApplicationContext(), "Downloaded File", Toast.LENGTH_LONG).show(); + } else { + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); + request.setMimeType(mime_type); + String cookies = CookieManager.getInstance().getCookie(url); + request.addRequestHeader("cookie", cookies); + request.addRequestHeader("User-Agent", userAgent); + request.setDescription("Downloading file..."); + request.setTitle(file_name); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(url, content_disposition, mime_type)); + DownloadManager dm = (DownloadManager)getSystemService(DOWNLOAD_SERVICE); + dm.enqueue(request); + Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show(); + } + } + }); + web_view.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { @@ -159,6 +203,21 @@ public class MainActivity extends Activity { return true; } + /* + ** https://stackoverflow.com/questions/5907369/file-upload-in-webview + ** https://stackoverflow.com/questions/8586691/how-to-open-file-save-dialog-in-android + */ + + @Override + public boolean onShowFileChooser(WebView view, ValueCallback message, WebChromeClient.FileChooserParams params) { + upload_message = message; + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + MainActivity.this.startActivityForResult(Intent.createChooser(intent, "File Chooser"), MainActivity.FILECHOOSER_RESULT); + return true; + } + @Override public boolean onConsoleMessage(android.webkit.ConsoleMessage consoleMessage) { Log.d("tildefriends", consoleMessage.message() + " -- From line " + consoleMessage.lineNumber() + " of " + consoleMessage.sourceId()); @@ -213,6 +272,17 @@ public class MainActivity extends Activity { web_view.restoreState(savedInstanceState); } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == FILECHOOSER_RESULT) { + if (upload_message == null) { + return; + } + upload_message.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent)); + upload_message = null; + } + } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && web_view.canGoBack()) {