android: compat webviewexecutor to support arraybuffer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user