From 632e4b98b910672e50fcf77c3bd27ef4440e6943 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Thu, 21 Nov 2019 19:51:58 +0800 Subject: [PATCH] feat:add network plugin for Android --- .../main/java/pub/doric/DoricRegistry.java | 2 + .../java/pub/doric/plugin/ModalPlugin.java | 1 - .../java/pub/doric/plugin/NetworkPlugin.java | 120 ++++++++++++++++++ demo/index.ts | 1 + demo/src/NetworkDemo.ts | 34 +++++ demo/src/utils.ts | 14 +- js-framework/src/util/nativeModules.ts | 3 + 7 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 Android/doric/src/main/java/pub/doric/plugin/NetworkPlugin.java create mode 100644 demo/src/NetworkDemo.ts diff --git a/Android/doric/src/main/java/pub/doric/DoricRegistry.java b/Android/doric/src/main/java/pub/doric/DoricRegistry.java index afc03619..8560ce0f 100644 --- a/Android/doric/src/main/java/pub/doric/DoricRegistry.java +++ b/Android/doric/src/main/java/pub/doric/DoricRegistry.java @@ -17,6 +17,7 @@ package pub.doric; import android.text.TextUtils; +import pub.doric.plugin.NetworkPlugin; import pub.doric.plugin.ShaderPlugin; import pub.doric.shader.HLayoutNode; import pub.doric.shader.ImageNode; @@ -65,6 +66,7 @@ public class DoricRegistry { public DoricRegistry() { this.registerNativePlugin(ShaderPlugin.class); this.registerNativePlugin(ModalPlugin.class); + this.registerNativePlugin(NetworkPlugin.class); this.registerViewNode(RootNode.class); this.registerViewNode(TextNode.class); this.registerViewNode(ImageNode.class); diff --git a/Android/doric/src/main/java/pub/doric/plugin/ModalPlugin.java b/Android/doric/src/main/java/pub/doric/plugin/ModalPlugin.java index f18e86d7..3746964c 100644 --- a/Android/doric/src/main/java/pub/doric/plugin/ModalPlugin.java +++ b/Android/doric/src/main/java/pub/doric/plugin/ModalPlugin.java @@ -17,7 +17,6 @@ package pub.doric.plugin; import android.app.AlertDialog; import android.content.DialogInterface; -import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; diff --git a/Android/doric/src/main/java/pub/doric/plugin/NetworkPlugin.java b/Android/doric/src/main/java/pub/doric/plugin/NetworkPlugin.java new file mode 100644 index 00000000..e9d65fed --- /dev/null +++ b/Android/doric/src/main/java/pub/doric/plugin/NetworkPlugin.java @@ -0,0 +1,120 @@ +/* + * Copyright [2019] [Doric.Pub] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package pub.doric.plugin; + +import android.text.TextUtils; +import android.util.Log; + +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; +import com.github.pengfeizhou.jscore.JavaValue; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.internal.http.HttpMethod; +import pub.doric.DoricContext; +import pub.doric.extension.bridge.DoricMethod; +import pub.doric.extension.bridge.DoricPlugin; +import pub.doric.extension.bridge.DoricPromise; + +/** + * @Description: pub.doric.plugin + * @Author: pengfei.zhou + * @CreateDate: 2019-11-21 + */ +@DoricPlugin(name = "network") +public class NetworkPlugin extends DoricJavaPlugin { + private OkHttpClient okHttpClient = new OkHttpClient(); + + public NetworkPlugin(DoricContext doricContext) { + super(doricContext); + } + + @DoricMethod(name = "request") + public void request(JSDecoder decoder, final DoricPromise promise) { + try { + JSObject requestVal = decoder.decode().asObject(); + String url = requestVal.getProperty("url").asString().value(); + String method = requestVal.getProperty("method").asString().value(); + JSValue headerVal = requestVal.getProperty("headers"); + JSValue dataVal = requestVal.getProperty("data"); + JSValue timeoutVal = requestVal.getProperty("timeout"); + + Headers.Builder headersBuilder = new Headers.Builder(); + if (headerVal.isObject()) { + JSObject headerObject = headerVal.asObject(); + Set headerKeys = headerObject.propertySet(); + for (String key : headerKeys) { + headersBuilder.add(key, headerObject.getProperty(key).asString().value()); + } + } + Headers headers = headersBuilder.build(); + String contentType = headers.get("Content-Type"); + MediaType mediaType = MediaType.parse(TextUtils.isEmpty(contentType) ? "application/json; charset=utf-8" : contentType); + RequestBody requestBody = HttpMethod.permitsRequestBody(method) ? RequestBody.create(mediaType, dataVal.isString() ? dataVal.asString().value() : "") : null; + Request.Builder requestBuilder = new Request.Builder(); + requestBuilder.url(url) + .headers(headers) + .method(method, requestBody); + if (timeoutVal.isNumber() && okHttpClient.connectTimeoutMillis() != timeoutVal.asNumber().toLong()) { + okHttpClient = okHttpClient.newBuilder().connectTimeout(timeoutVal.asNumber().toLong(), TimeUnit.MILLISECONDS).build(); + } + okHttpClient.newCall(requestBuilder.build()).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + promise.reject(new JavaValue(e.getLocalizedMessage())); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + JSONBuilder header = new JSONBuilder(); + for (String key : response.headers().names()) { + header.put(key, response.headers().get(key)); + } + JSONObject jsonObject = new JSONBuilder() + .put("status", response.code()) + .put("headers", header.toJSONObject()) + .put("data", response.body() == null ? "" : response.body().string()) + .toJSONObject(); + promise.resolve(new JavaValue(jsonObject)); + } + }); + + } catch (Exception e) { + e.printStackTrace(); + promise.reject(new JavaValue(e.getLocalizedMessage())); + } + } + +} diff --git a/demo/index.ts b/demo/index.ts index dcba746f..51bfdae5 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -8,4 +8,5 @@ export default [ 'src/EffectsDemo', 'src/ImageDemo', 'src/ModalDemo', + 'src/NetworkDemo', ] \ No newline at end of file diff --git a/demo/src/NetworkDemo.ts b/demo/src/NetworkDemo.ts new file mode 100644 index 00000000..bc1adb39 --- /dev/null +++ b/demo/src/NetworkDemo.ts @@ -0,0 +1,34 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network } from "doric"; +import { title, label, colors } from "./utils"; + +@Entry +class NetworkDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + title("Network Demo"), + label('Click me').apply({ + width: 200, + height: 50, + bgColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + network(context).get('https://doric.pub').then( + e => { + modal(context).toast(JSON.stringify(e)) + } + ).catch(e => { + modal(context).toast('Catched:' + JSON.stringify(e)) + }) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/demo/src/utils.ts b/demo/src/utils.ts index 29f77355..a024952e 100644 --- a/demo/src/utils.ts +++ b/demo/src/utils.ts @@ -1,4 +1,4 @@ -import { Color, text, Stack, Text } from "doric"; +import { Color, text, Stack, Text, layoutConfig, LayoutSpec, gravity } from "doric"; export const colors = [ "#70a1ff", @@ -33,4 +33,16 @@ export function boxStr(str: string, idx = 0) { it.textColor = Color.WHITE it.bgColor = colors[idx || 0] }) +} + +export function title(str: string) { + return text({ + text: "Network Demo", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + bgColor: colors[1], + textAlignment: gravity().center(), + height: 50, + }) } \ No newline at end of file diff --git a/js-framework/src/util/nativeModules.ts b/js-framework/src/util/nativeModules.ts index 7b622b03..3c9c1cde 100644 --- a/js-framework/src/util/nativeModules.ts +++ b/js-framework/src/util/nativeModules.ts @@ -96,6 +96,9 @@ function transformRequest(request: IRequest) { } request.url = `${request.url}${url.indexOf('?') >= 0 ? '&' : '?'}${queryStrings.join('&')}` } + if (typeof request.data === 'object') { + request.data = JSON.stringify(request.data) + } return request } export function network(context: BridgeContext) {