はじめに
AndroidのWebViewでblobURLをダウンロードできるようにする方法について解説。
- JavaScriptInterface.ktを作成し、Android側のダウンロード時の処理を記述
- download_hander.jsを作成し、javascript側の処理を記述
- WebView使用時に、上記2つをセット
という流れで作成を行う。
1. JavaScriptInterfaceの作成
class JavaScriptInterface(private val context: Context) {
@JavascriptInterface
fun base64ToFile(base64: String, mimeType: String, fileName: String) {
Log.d("base64ToFile", "base64:$base64")
// Base64ヘッダーを除去
val pureBase64 = base64.substringAfter(",")
// バイナリにデコード
val byteArray = Base64.decode(pureBase64, Base64.DEFAULT)
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, fileName)
put(MediaStore.Downloads.MIME_TYPE, mimeType)
put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
put(MediaStore.Downloads.IS_PENDING, 1)
}
val resolver = context.contentResolver
val uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
if (uri != null) {
resolver.openOutputStream(uri)?.use { outputStream ->
outputStream.write(byteArray)
}
// IS_PENDING → 0 にして公開状態にする
contentValues.clear()
contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
resolver.update(uri, contentValues, null, null)
}
}
}
- download_hander.jsの作成
下記に保存
app/
└─ src/
└─ main/
└─ assets/
└─ js/
└─ download_handler.js
コードは下記
(function(blobUrl) {
try {
var anchors = document.querySelectorAll('a[href="' + blobUrl + '"]');
var fileName = "file_" + Date.now() + ".bin";
if (anchors.length > 0) {
var downloadAttr = anchors[0].getAttribute("download");
if (downloadAttr) {
fileName = downloadAttr;
}
}
fetch(blobUrl)
.then(response => {
const contentType = response.headers.get("Content-Type") || "application/octet-stream";
return response.blob().then(blob => ({ blob, contentType }));
})
.then(({ blob, contentType }) => {
var reader = new FileReader();
reader.onloadend = function() {
android.base64ToFile(reader.result, contentType, fileName);
};
reader.readAsDataURL(blob);
})
.catch(error => {
console.error("fetchエラー:", error);
});
} catch (e) {
console.error("JS実行時エラー:", e);
}
})
最後に、download_hander.js
とJavaScriptInterface.kt
をWebViewにセットすれば良い。
WebView使用時に上記2つをセットするコードについては、こちらに記述。