1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-25 19:36:50 +01:00

Bangle.js: Improve file downloads - we can now at least get files downloaded

This commit is contained in:
Gordon Williams 2023-09-14 12:49:37 +01:00
parent e18a991b13
commit c647c2647f

View File

@ -3,12 +3,15 @@ package nodomain.freeyourgadget.gadgetbridge.devices.banglejs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_INTERNET_ACCESS; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_INTERNET_ACCESS;
import android.app.Activity; import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -39,6 +42,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
@ -64,6 +68,12 @@ public class AppsManagementActivity extends AbstractGBActivity {
private int deviceRxSeq = -1; private int deviceRxSeq = -1;
/// When a file chooser has been opened in the WebView, this is what should get called /// When a file chooser has been opened in the WebView, this is what should get called
private ValueCallback<Uri[]> fileChooserCallback; private ValueCallback<Uri[]> fileChooserCallback;
/// used by showSaveFileDialog for file data
private byte[] fileSaveData;
// Request code for creating a PDF document.
private static final int CHOOSE_FILE = 0;
private static final int CREATE_FILE = 1;
public AppsManagementActivity() { public AppsManagementActivity() {
} }
@ -145,7 +155,6 @@ public class AppsManagementActivity extends AbstractGBActivity {
LOG.info("WebView RX: " + data); LOG.info("WebView RX: " + data);
bangleTxData(data); bangleTxData(data);
} }
} }
// Called when data received from Bangle.js - push data to the WebView // Called when data received from Bangle.js - push data to the WebView
@ -171,6 +180,16 @@ public class AppsManagementActivity extends AbstractGBActivity {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent); LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
} }
public void showSaveFileDialog(String fileName, String mimeType, byte data[]) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (mimeType!=null) intent.setType(mimeType);
if (fileName!=null) intent.putExtra(Intent.EXTRA_TITLE, fileName);
fileSaveData = data;
startActivityForResult(intent, CREATE_FILE);
// see onActivityResult
}
private void initViews() { private void initViews() {
//https://stackoverflow.com/questions/4325639/android-calling-javascript-functions-in-webview //https://stackoverflow.com/questions/4325639/android-calling-javascript-functions-in-webview
webView = findViewById(R.id.webview); webView = findViewById(R.id.webview);
@ -232,8 +251,8 @@ public class AppsManagementActivity extends AbstractGBActivity {
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, selectionIntent); chooserIntent.putExtra(Intent.EXTRA_INTENT, selectionIntent);
startActivityForResult(chooserIntent, 0); startActivityForResult(chooserIntent, CHOOSE_FILE);
// see onActivityResult
return true; return true;
} }
@ -244,16 +263,26 @@ public class AppsManagementActivity extends AbstractGBActivity {
String contentDisposition, String mimetype, String contentDisposition, String mimetype,
long contentLength) { long contentLength) {
if (url == null) return; if (url == null) return;
// FIXME: When we get to this point we have no idea what the filename is
// maybe we should just add 'Android.downloadFile' and call that from the App Loader
if(url.startsWith("blob:")) {
LOG.error("WebView blob: download requested, but not supported");
// This should be possible with https://stackoverflow.com/a/48954970/1215872
// but having tried the XMLHttpRequest can't find the blob - I think because the blob ends
// up being created inside an iframe, and the data isn't accessible from the
// external one
} else if(url.startsWith("data:") && url.contains(";base64,")) {
int commaIdx = url.indexOf(";base64,");
if (commaIdx>=0) {
String b64 = url.substring(commaIdx + 8);
byte data[] = Base64.decode(b64, Base64.DEFAULT);
showSaveFileDialog(null, mimetype, data);
} else LOG.error("WebView data: download requested, but not base64");
} else { // just view in the web browser
Intent i = new Intent(Intent.ACTION_VIEW); Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url.replaceFirst("^blob:", ""))); i.setData(Uri.parse(url));
startActivity(i); startActivity(i);
}
/*DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); // fails with java.lang.IllegalArgumentException: Can not handle uri::
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "download");
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);*/
} }
}); });
} }
@ -261,7 +290,7 @@ public class AppsManagementActivity extends AbstractGBActivity {
@Override // for file chooser results @Override // for file chooser results
protected void onActivityResult(int requestCode, int resultCode, Intent intent) { protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent); super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == CHOOSE_FILE) { // onShowFileChooser
if (fileChooserCallback == null) return; if (fileChooserCallback == null) return;
Uri[] results = null; Uri[] results = null;
if (resultCode == Activity.RESULT_OK) if (resultCode == Activity.RESULT_OK)
@ -269,5 +298,22 @@ public class AppsManagementActivity extends AbstractGBActivity {
fileChooserCallback.onReceiveValue(results); fileChooserCallback.onReceiveValue(results);
fileChooserCallback = null; fileChooserCallback = null;
} }
if (requestCode == CREATE_FILE) { // showSaveFileDialog
OutputStream os = null;
try {
os = getContentResolver().openOutputStream(intent.getData());
os.write(fileSaveData);
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
} catch (IOException e) {
}
}
fileSaveData = null;
}
}
} }