android: compat webviewexecutor to support arraybuffer

This commit is contained in:
pengfei.zhou
2021-12-31 16:55:38 +08:00
committed by osborn
parent c67803b717
commit 8c57e5e500
19 changed files with 381 additions and 177 deletions

View File

@@ -17,6 +17,7 @@ package pub.doric.engine;
import com.github.pengfeizhou.jscore.ArchiveException;
import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSArrayBuffer;
import com.github.pengfeizhou.jscore.JSBoolean;
import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSNull;
@@ -127,6 +128,9 @@ public class DoricJSDecoder extends JSDecoder {
}
return jsArray;
}
if (this.value instanceof byte[]) {
return new JSArrayBuffer((byte[]) this.value);
}
return JS_NULL;
}
}

View File

@@ -109,14 +109,14 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
e.printStackTrace(new PrintWriter(stringWriter));
mDoricRegistry.onLog(Log.ERROR, stringWriter.toString());
//In case some unexpected errors happened
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mDoricRegistry.onLog(Log.WARN, "Use DoricWebViewJSExecutor");
mDoricJSE = new DoricWebViewJSExecutor(Doric.application());
loadBuiltinJS("doric-web.js");
} else {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// mDoricRegistry.onLog(Log.WARN, "Use DoricWebViewJSExecutor");
// mDoricJSE = new DoricWebViewJSExecutor(Doric.application());
// loadBuiltinJS("doric-web.js");
// } else {
mDoricRegistry.onLog(Log.WARN, "Use DoricWebShellJSExecutor");
mDoricJSE = new DoricWebShellJSExecutor(Doric.application());
}
// }
}
}

View File

@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Base64;
import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
@@ -43,6 +44,7 @@ import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -66,6 +68,8 @@ public class DoricWebShellJSExecutor implements IDoricJSE {
private WebView webView;
private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
private final Handler handler;
private static final Map<String, SoftReference<byte[]>> arrayBuffers = new HashMap<>();
private static final AtomicInteger arrayBufferId = new AtomicInteger();
private static Object unwrapJSObject(JSONObject jsonObject) {
String type = jsonObject.optString("type");
@@ -90,6 +94,9 @@ public class DoricWebShellJSExecutor implements IDoricJSE {
e.printStackTrace();
return JSONObject.NULL;
}
case "arrayBuffer":
String base64 = jsonObject.optString("value");
return Base64.decode(base64, Base64.NO_WRAP);
default:
return JSONObject.NULL;
}
@@ -127,6 +134,12 @@ public class DoricWebShellJSExecutor implements IDoricJSE {
e.printStackTrace();
}
}
if (javaValue.getType() == 6) {
byte[] data = javaValue.getByteData();
String id = String.valueOf(arrayBufferId.incrementAndGet());
arrayBuffers.put(id, new SoftReference<>(data));
return new JSONBuilder().put("type", "arrayBuffer").put("value", id).toJSONObject();
}
return WRAPPED_NULL;
}
@@ -142,6 +155,16 @@ public class DoricWebShellJSExecutor implements IDoricJSE {
readyFuture.set(true);
}
@JavascriptInterface
public String fetchArrayBuffer(String arrayBufferId) {
SoftReference<byte[]> ref = arrayBuffers.remove(arrayBufferId);
if (ref != null && ref.get() != null) {
byte[] data = ref.get();
return Base64.encodeToString(data, Base64.NO_WRAP);
}
return "";
}
@JavascriptInterface
public void log(String message) {
DoricLog.d(message);

View File

@@ -22,6 +22,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Base64;
import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
@@ -39,8 +40,10 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import pub.doric.BuildConfig;
import pub.doric.async.SettableFuture;
@@ -57,6 +60,8 @@ public class DoricWebViewJSExecutor implements IDoricJSE {
private WebView webView;
private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
private final Handler handler;
private static final Map<String, SoftReference<byte[]>> arrayBuffers = new HashMap<>();
private static final AtomicInteger arrayBufferId = new AtomicInteger();
private static Object unwrapJSObject(JSONObject jsonObject) {
String type = jsonObject.optString("type");
@@ -81,6 +86,9 @@ public class DoricWebViewJSExecutor implements IDoricJSE {
e.printStackTrace();
return JSONObject.NULL;
}
case "arrayBuffer":
String base64 = jsonObject.optString("value");
return Base64.decode(base64, Base64.NO_WRAP);
default:
return JSONObject.NULL;
}
@@ -118,6 +126,12 @@ public class DoricWebViewJSExecutor implements IDoricJSE {
e.printStackTrace();
}
}
if (javaValue.getType() == 6) {
byte[] data = javaValue.getByteData();
String id = String.valueOf(arrayBufferId.incrementAndGet());
arrayBuffers.put(id, new SoftReference<>(data));
return new JSONBuilder().put("type", "arrayBuffer").put("value", id).toJSONObject();
}
return WRAPPED_NULL;
}
@@ -132,9 +146,19 @@ public class DoricWebViewJSExecutor implements IDoricJSE {
DoricLog.d(message);
}
@JavascriptInterface
public String fetchArrayBuffer(String arrayBufferId) {
SoftReference<byte[]> ref = arrayBuffers.remove(arrayBufferId);
if (ref != null && ref.get() != null) {
byte[] data = ref.get();
return Base64.encodeToString(data, Base64.NO_WRAP);
}
return "";
}
@JavascriptInterface
public void returnNative(String result) {
DoricLog.d("return Native" + result);
DoricLog.d("return Native " + result);
if (returnFuture != null) {
returnFuture.set(result);
}

View File

@@ -52,6 +52,8 @@ import com.bumptech.glide.request.target.DrawableImageViewTarget;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.facebook.yoga.YogaNode;
import com.github.pengfeizhou.jscore.ArchiveException;
import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
@@ -394,7 +396,7 @@ public class ImageNode extends ViewNode<ImageView> {
}
@Override
protected void blend(ImageView view, String name, JSValue prop) {
protected void blend(final ImageView view, String name, JSValue prop) {
switch (name) {
case "image":
if (!prop.isObject()) {
@@ -522,13 +524,46 @@ public class ImageNode extends ViewNode<ImageView> {
if (!prop.isObject()) {
return;
}
int width = prop.asObject().getProperty("width").asNumber().toInt();
int height = prop.asObject().getProperty("height").asNumber().toInt();
byte[] pixels = prop.asObject().getProperty("pixels").asArrayBuffer().value();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
ByteBuffer byteBuffer = ByteBuffer.wrap(pixels);
bitmap.copyPixelsFromBuffer(byteBuffer);
view.setImageBitmap(bitmap);
final int width = prop.asObject().getProperty("width").asNumber().toInt();
final int height = prop.asObject().getProperty("height").asNumber().toInt();
JSValue pixelsValue = prop.asObject().getProperty("pixels");
if (pixelsValue.isArrayBuffer()) {
byte[] pixels = prop.asObject().getProperty("pixels").asArrayBuffer().value();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
ByteBuffer byteBuffer = ByteBuffer.wrap(pixels);
bitmap.copyPixelsFromBuffer(byteBuffer);
view.setImageBitmap(bitmap);
} else if (pixelsValue.isString()) {
String pixelsCallbackId = pixelsValue.asString().value();
callJSResponse(pixelsCallbackId).setCallback(new AsyncResult.Callback<JSDecoder>() {
@Override
public void onResult(JSDecoder result) {
try {
JSValue value = result.decode();
if (value.isArrayBuffer()) {
byte[] pixels = value.asArrayBuffer().value();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
ByteBuffer byteBuffer = ByteBuffer.wrap(pixels);
bitmap.copyPixelsFromBuffer(byteBuffer);
view.setImageBitmap(bitmap);
}
} catch (ArchiveException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable t) {
}
@Override
public void onFinish() {
}
});
}
break;
default:
super.blend(view, name, prop);