Как читать данные в BLOB-объекте в WebView на Android?
У меня есть сервер, который создает объект блоб в браузере, и я хочу загрузить его в WebView в приложении для Android. Я попытался перенаправить запрос на экземпляр браузера, а также с помощью диспетчера загрузки, чтобы сделать это, но ни один из них, похоже, не работает (даже если я открою ту же страницу в Chrome, операция загрузки там работает).
Я попробовал следующий код, он выдает ошибку:
Android.content.ActivityNotFoundException: не найдено действие для обработки Intent { act=android.intent.action.VIEW dat=blob:https%3A//111.111.111.111%3A8080/40b63131-63b1-4fa4-9451-c6297bbd111a"
редактировать
Android.content.ActivityNotFoundException: не найдена активность для обработки намерения {act = android.intent.action.VIEW dat = blob: http://digitalinsensu.com/0f0d6127-a0f1-44c3-af85-72f648258d6d
Код:
mWebView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype,long contentLength) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});
и это выбрасывает java.lang.IllegalArgumentException: может только загрузить ошибку HTTP/HTTPS URIs:
mWebView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype,long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
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);
}
});
Как я должен загружать BLOB-объекты? Любая помощь будет оценена.
2 ответа
Да, это должно быть возможно. В вашем случае URL выглядит так, как только blob:
префикс удаляется, а остальное URL-адрес декодируется:
блоб: HTTP://digitalinsensu.com/0f0d6127-a0f1-44c3-af85-72f648258d6d
Имейте в виду, что этот URL будет работать только в том случае, если на устройстве работает веб-сервер, который отвечает на запросы, что маловероятно в случае BLOB-адресов: URL-адресов. Если вы хотите сделать это, вам нужно удалить blob:
во-первых, используя Java String.replace(..)
или похожие. Чтобы декодировать URL, используйте что-то вроде URLDecoder.decode(url, "UTF-8");
смотрите здесь для деталей.
Проблема в том, что DownloadListener
действительно ожидает URI (например, http://server.com/file.pdf). Однако ссылка, по которой щелкает пользователь, не передает URI в этом формате. Переданный URL-адрес представляет собой большой двоичный объект, прикрепленный к DOM
браузера. В результате решение не будет работать как задумано.
У вас может быть другой вариант. Это зависит от того, как вы генерируете байты для BLOB-объекта. Вы упомянули, что вы делаете это в Javascript. Если так, я бы пропустил использование Blob и URL.createObjectURL
полностью и написать Javascript/Native interface
это позволит вам передавать байты кусками (например, n массивов по 255 байт) в код Java. Это снизит потребление памяти клиентом.
У меня есть идея о том, как создать интерфейс, но сначала мне нужно понять, как вы генерируете байты для большого двоичного объекта. Если вы можете опубликовать байтовый массив, я могу попробовать дальше.
Для получения полной информации об этой проверке здесь
Вам нужно перехватить обратный вызов для обработки кликов по URL, например:
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
shouldOverrideUrlLoading(view, Uri.parse(url));
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return shouldOverrideUrlLoading(view, request.getUrl());
}
// legacy callback
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return shouldOverrideUrlLoading(view, Uri.parse(url));
}
return super.shouldOverrideUrlLoading(view, url);
}
private boolean shouldOverrideUrlLoading(final WebView view, final Uri request) {
if(request.getScheme().equals("blob")) {
// do your special handling for blob urls here
return true;
}
}
});
В shouldOverrideUrlLoading()
Вы можете сделать свою специальную обработку.