网络


1 ZZRHttp

1.1 概述

现代应用开发经常需要访问HTTP服务器。常用的Web编程框架包括:

它们虽然非常易用且流行,但目前在HarmonyOS上还无法使用。系统自带的HttpURLConnection,接口非常繁琐,加之多线程,会使程序变得十分臃肿。

ZZRHttp是一款可在HarmonyOS上使用的,轻量级Web编程框架。一方面它隐藏了网络访问的诸多细节,另一方面又提供了优雅的界面更新机制。

1.2 用法

1.2.1 网络权限

在.../entry/src/main/config.json文件的module中添加网络访问权限:

"reqPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

1.2.2 访问模式

HarmonyOS默认采用https模式访问网络,如果所请求网址是http开头的,则需要在.../entry/src/main/config.json文件的deviceConfig中添加如下设置:

"default": {
  "network": {
    "cleartextTraffic": true
  }
}

1.2.3 添加依赖

在.../entry/build.gradle文件的dependencies中添加ZZRHttp:

dependencies {
    implementation 'com.zzrv5.zzrhttp:ZZRHttp:1.0.1'
}

点右上角“Sync Now”同步。

1.2.4 访问网络

ZZRHttp.get(url, new ZZRCallBack.CallBackString() {
    @Override
    public void onFailure(int code, String errorMessage) {
        // HTTP访问失败,以下代码在主线程中执
        // 行,可以更新UI,但不要执行阻塞操作
        ...
    }
    @Override
    public void onResponse(String response) {
        // HTTP访问成功,以下代码在主线程中执
        // 行,可以更新UI,但不要执行阻塞操作
        ...
    }
});

1.3 方法

get(
    String url,
    ZZRCallBack callBack
);
get(
    String url,
    Map<String, String> paramsMap,
    ZZRCallBack callBack
);
get(
    String              url,
    Map<String, String> paramsMap,
    Map<String, String> headerMap,
    ZZRCallBack         callBack
);
post(
    String              url,
    ZZRCallBack         callBack
);
post(
    String              url,
    Map<String, String> paramsMap,
    ZZRCallBack         callBack
);
post(
    String              url,
    Map<String, String> paramsMap,
    Map<String, String> headerMap,
    ZZRCallBack         callBack
);
postJson(
    String              url,
    String              jsonStr,
    ZZRCallBack         callBack
);
postJson(
    String              url,
    String              jsonStr,
    Map<String, String> headerMap,
    ZZRCallBack         callBack
);

例程:HttpClient

...\HttpClient\entry\src\main\config.json

{
  ...
  "deviceConfig": {
    "default": {
      "network": {
        "cleartextTraffic": true
      }
    }
  },
  "module": {
    ...
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

...\HttpClient\entry\build.gradle

...
dependencies {
    ...
    implementation 'com.zzrv5.zzrhttp:ZZRHttp:1.0.1'
}
...

...\HttpClient\entry\src\main\resources\base\graphic\background_textfield.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid ohos:color="#ffffff"/>
    <stroke ohos:width="1vp" ohos:color="#00a2e8"/>
</shape>

...\HttpClient\entry\src\main\resources\base\graphic\background_button.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle">
    <corners ohos:radius="100"/>
    <solid ohos:color="#00a2e8"/>
</shape>

...\HttpClient\entry\src\main\resources\base\graphic\background_scrollview.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid ohos:color="#cef0ff"/>
    <stroke ohos:width="1vp" ohos:color="#00a2e8"/>
</shape>

...\HttpClient\entry\src\main\resources\base\graphic\background_text.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid ohos:color="#ffd8da"/>
    <stroke ohos:width="1vp" ohos:color="#ff0000"/>
</shape>

...\HttpClient\entry\src\main\resources\base\layout\ability_main.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:padding="20vp"
    ohos:orientation="vertical">

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <TextField
            ohos:id="$+id:tf"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:weight="1"
            ohos:padding="2vp"
            ohos:background_element="$graphic:background_textfield"
            ohos:hint="输入网址"
            ohos:text="https://www.baidu.com"
            ohos:text_size="20fp"/>

        <Button
            ohos:id="$+id:btn"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:left_padding="20vp"
            ohos:right_padding="20vp"
            ohos:top_padding="2vp"
            ohos:bottom_padding="4vp"
            ohos:left_margin="10vp"
            ohos:background_element="$graphic:background_button"
            ohos:text="Go"
            ohos:text_size="20fp"
            ohos:text_color="#ffffff"
            />

    </DirectionalLayout>

    <ScrollView
        ohos:height="match_parent"
        ohos:weight="1"
        ohos:width="match_parent"
        ohos:padding="2vp"
        ohos:top_margin="10vp"
        ohos:background_element="$graphic:background_scrollview"
        ohos:rebound_effect="true">

        <Text
            ohos:id="$+id:txtResponse"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="20fp"
            />

    </ScrollView>

    <Text
        ohos:id="$+id:txtStatus"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:padding="2vp"
        ohos:top_margin="10vp"
        ohos:background_element="$graphic:background_text"
        ohos:multiple_lines="true"
        ohos:text="就绪"
        ohos:text_size="20fp"
        ohos:text_color="#ff0000"
        />

</DirectionalLayout>

...\HttpClient\entry\src\main\java\com\minwei\httpclient\slice\MainAbilitySlice.java

public class MainAbilitySlice extends AbilitySlice {
    private TextField textField;
    private Button button;
    private Text txtResponse, txtStatus;

    @Override
    public void onStart(Intent intent) {
        ...
        textField = (TextField)findComponentById(ResourceTable.Id_tf);
        button = (Button)findComponentById(ResourceTable.Id_btn);
        txtResponse = (Text)findComponentById(ResourceTable.Id_txtResponse);
        txtStatus = (Text)findComponentById(ResourceTable.Id_txtStatus);

        button.setClickedListener(component -> {
            txtResponse.setText("");
            txtStatus.setText("正在请求网络,请稍候...");

            ZZRHttp.get(textField.getText(), new CallBackString() {
                @Override
                public void onFailure(int code, String errorMessage) {
                    txtStatus.setText(errorMessage);
                }
                @Override
                public void onResponse(String response) {
                    txtResponse.setText(response);
                    txtStatus.setText("就绪");
                }
            });
        });
    }
    ...
}

运行效果如下图所示:

1.4 访问远程API

聚合数据(https://www.juhe.cn)为网络开发者提供了丰富的远程API测试接口。无需自行编写服务器程序,即可验证测试基于HarmonyOS的各种网络应用。

1.4.1 老黄历接口

1.4.2 解析JSON字符串

常用JSON解析工具:Jackson、gson。

中央仓库(https://mvnrepository.com)
  JSON Libraries
    Jackson Databind
      2.12.4
        Gradle (Short):

implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.4'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.12.4'
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.4'

例程:Almanac

...\Almanac\entry\src\main\config.json

{
  ...
  "deviceConfig": {
    "default": {
      "network": {
        "cleartextTraffic": true
      }
    }
  },
  "module": {
    ...
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

...\Almanac\entry\build.gradle

...
dependencies {
    ...
    implementation 'com.zzrv5.zzrhttp:ZZRHttp:1.0.1'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.4'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.12.4'
    implementation 'com.fasterxml.jackson.core:jackson-core:2.12.4'
}
...

...\Almanac\entry\src\main\resources\base\layout\ability_main.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:padding="20vp"
    ohos:alignment="horizontal_center"
    ohos:orientation="vertical">

    <Text
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="今日黄历"
        ohos:text_size="24fp"
        />

    <Text
        ohos:height="2vp"
        ohos:width="match_parent"
        ohos:top_margin="10vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="阳历"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtYangli"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="阴历"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtYinli"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="五行"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtWuxing"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="冲煞"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtChongsha"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="彭祖百忌"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtBaiji"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="吉神宜趋"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtJishen"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text=""
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtYi"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text="凶神宜忌"
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtXiongshen"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="5vp"
        ohos:background_element="#808080"
        />

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <Text
            ohos:height="match_content"
            ohos:width="100vp"
            ohos:text=""
            ohos:text_size="18fp"
            ohos:text_color="#00a2e8"
            ohos:text_alignment="horizontal_center"
            />

        <Text
            ohos:id="$+id:txtJi"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="18fp"
            />

    </DirectionalLayout>

    <Text
        ohos:height="2vp"
        ohos:width="match_parent"
        ohos:top_margin="5vp"
        ohos:bottom_margin="10vp"
        ohos:background_element="#808080"
        />

    <ScrollView
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:rebound_effect="true">

        <Text
            ohos:id="$+id:txtStatus"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:multiple_lines="true"
            ohos:text_size="15fp"
            ohos:text_color="#ff0000"
            />

    </ScrollView>

</DirectionalLayout>

...\Almanac\entry\src\main\java\com\minwei\almanac\common\Almanac.java

public class Almanac {
    private String reason;
    private Result result;
    private int error_code;

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public Result getResult() {
        return result;
    }

    public void setResult(Result result) {
        this.result = result;
    }

    public int getError_code() {
        return error_code;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }

    public static class Result {
        private int id;
        private String yangli;
        private String yinli;
        private String wuxing;
        private String chongsha;
        private String baiji;
        private String jishen;
        private String yi;
        private String xiongshen;
        private String ji;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getYangli() {
            return yangli;
        }

        public void setYangli(String yangli) {
            this.yangli = yangli;
        }

        public String getYinli() {
            return yinli;
        }

        public void setYinli(String yinli) {
            this.yinli = yinli;
        }

        public String getWuxing() {
            return wuxing;
        }

        public void setWuxing(String wuxing) {
            this.wuxing = wuxing;
        }

        public String getChongsha() {
            return chongsha;
        }

        public void setChongsha(String chongsha) {
            this.chongsha = chongsha;
        }

        public String getBaiji() {
            return baiji;
        }

        public void setBaiji(String baiji) {
            this.baiji = baiji;
        }

        public String getJishen() {
            return jishen;
        }

        public void setJishen(String jishen) {
            this.jishen = jishen;
        }

        public String getYi() {
            return yi;
        }

        public void setYi(String yi) {
            this.yi = yi;
        }

        public String getXiongshen() {
            return xiongshen;
        }

        public void setXiongshen(String xiongshen) {
            this.xiongshen = xiongshen;
        }

        public String getJi() {
            return ji;
        }

        public void setJi(String ji) {
            this.ji = ji;
        }
    }
}

...\Almanac\entry\src\main\java\com\minwei\almanac\slice\MainAbilitySlice.java

public class MainAbilitySlice extends AbilitySlice {
    private Text txtYangli,   txtYinli,     txtWuxing,
                 txtChongsha, txtBaiji,     txtJishen,
                 txtYi,       txtXiongshen, txtJi,
                 txtStatus;

    @Override
    public void onStart(Intent intent) {
        ...
        txtYangli    = (Text)findComponentById(ResourceTable.Id_txtYangli);
        txtYinli     = (Text)findComponentById(ResourceTable.Id_txtYinli);
        txtWuxing    = (Text)findComponentById(ResourceTable.Id_txtWuxing);
        txtChongsha  = (Text)findComponentById(ResourceTable.Id_txtChongsha);
        txtBaiji     = (Text)findComponentById(ResourceTable.Id_txtBaiji);
        txtJishen    = (Text)findComponentById(ResourceTable.Id_txtJishen);
        txtYi        = (Text)findComponentById(ResourceTable.Id_txtYi);
        txtXiongshen = (Text)findComponentById(ResourceTable.Id_txtXiongshen);
        txtJi        = (Text)findComponentById(ResourceTable.Id_txtJi);
        txtStatus    = (Text)findComponentById(ResourceTable.Id_txtStatus);

        txtStatus.setText("正在请求网络,请稍候...");

        String url = "http://v.juhe.cn/laohuangli/d";
        Date time = Calendar.getInstance().getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String date = formatter.format(time);
        String key = "22f82c0c3cdd7aeb4e02e45cec27f419";
        url += "?date=" + date + "&key=" + key;

        ZZRHttp.get(url, new CallBackString() {
            @Override
            public void onFailure(int code, String errorMessage) {
                txtStatus.setText(errorMessage);
            }
            @Override
            public void onResponse(String response) {
                txtStatus.setText("");

                try {
                    Almanac almanac = new ObjectMapper()
                        .readValue(response, Almanac.class);
                    if (almanac.getError_code() != 0)
                        txtStatus.setText(almanac.getReason());
                    else {
                        Almanac.Result result = almanac.getResult();

                        txtYangli.setText(new SimpleDateFormat(
                            "yyyy年M月d日").format(formatter.parse(
                            result.getYangli(), new ParsePosition(0))));
                        txtYinli.setText(result.getYinli());
                        txtWuxing.setText(result.getWuxing()
                            .replaceAll(" ", ","));
                        txtChongsha.setText(result.getChongsha());
                        txtBaiji.setText(result.getBaiji()
                            .replaceAll(" ", ","));
                        txtJishen.setText(result.getJishen()
                            .replaceAll(" ", "、"));
                        txtYi.setText(result.getYi()
                            .replaceAll(" ", "、"));
                        txtXiongshen.setText(result.getXiongshen()
                            .replaceAll(" ", "、"));
                        txtJi.setText(result.getJi()
                            .replaceAll(" ", "、"));
                    }
                }
                catch (JsonProcessingException exception) {
                    txtStatus.setText(exception.toString());
                }
            }
        });
    }
    ...
}

运行效果如下图所示:

2 WebView

2.1 概述

在实际的应用开发中,经常需要在应用内部打开特定的网页,而不是用系统自带的浏览器打开网页。甚至很多公司的应用本身就只是打开一个特定的网页,比如掌阅等。这样开发的好处是,只需要编写极少量的代码就可以完成交互。

HarmonyOS的WebView组件为开发者提供了在应用中内嵌Web浏览器的功能。

2.2 基本用法

2.2.1 网络权限

在/entry/src/main/config.json文件的module中添加:

"reqPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

2.2.2 访问模式

在/entry/src/main/config.json文件的deviceConfig中添加:

"default": {
  "network": {
    "cleartextTraffic": true
  }
}

2.2.3 添加组件

<ohos.agp.components.webengine.WebView
    ohos:id="$+id:wv"
    ohos:height="match_parent"
    ohos:width="match_parent"/>

2.2.4 设置代理

webView.setWebAgent(new WebAgent() {
    @Override
    public boolean isNeedLoadUrl(WebView webView,
        ResourceRequest resourceRequest) {
        return super.isNeedLoadUrl(webView, resourceRequest);
    }
});

2.2.5 加载页面

webView.load(textField.getText());

例程:Basic

...\Basic\entry\src\main\config.json

{
  ...
  "deviceConfig": {
    "default": {
      "network": {
        "cleartextTraffic": true
      }
    }
  },
  "module": {
    ...
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

...\Basic\entry\src\main\resources\base\graphic\background_textfield.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid ohos:color="#ffffff"/>
    <stroke ohos:width="1vp" ohos:color="#00a2e8"/>
</shape>

...\Basic\entry\src\main\resources\base\graphic\background_button.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle">
    <corners ohos:radius="100"/>
    <solid ohos:color="#00a2e8"/>
</shape>

...\Basic\entry\src\main\resources\base\graphic\background_directionallayout.xml

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <stroke ohos:width="1vp" ohos:color="#00a2e8"/>
</shape>

...\Basic\entry\src\main\resources\base\layout\ability_main.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:padding="20vp"
    ohos:orientation="vertical">

    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="horizontal">

        <TextField
            ohos:id="$+id:tf"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:weight="1"
            ohos:padding="2vp"
            ohos:background_element="$graphic:background_textfield"
            ohos:hint="输入网址"
            ohos:text="https://www.baidu.com"
            ohos:text_size="20fp"/>

        <Button
            ohos:id="$+id:btn"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:left_padding="20vp"
            ohos:right_padding="20vp"
            ohos:top_padding="2vp"
            ohos:bottom_padding="4vp"
            ohos:left_margin="10vp"
            ohos:background_element="$graphic:background_button"
            ohos:text="Go"
            ohos:text_size="20fp"
            ohos:text_color="#ffffff"
            />

    </DirectionalLayout>

    <DirectionalLayout
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:padding="2vp"
        ohos:top_margin="10vp"
        ohos:background_element="$graphic:background_directionallayout">

        <ohos.agp.components.webengine.WebView
            ohos:id="$+id:wv"
            ohos:height="match_parent"
            ohos:width="match_parent"/>

    </DirectionalLayout>

</DirectionalLayout>

...\Basic\entry\src\main\java\com\minwei\basic\slice\MainAbilitySlice.java

public class MainAbilitySlice extends AbilitySlice {
    private TextField textField;
    private Button button;
    private WebView webView;

    @Override
    public void onStart(Intent intent) {
        ...
        textField = (TextField)findComponentById(ResourceTable.Id_tf);
        button = (Button)findComponentById(ResourceTable.Id_btn);
        webView = (WebView)findComponentById(ResourceTable.Id_wv);

        button.setClickedListener(component -> {
            webView.setWebAgent(new WebAgent() {
                @Override
                public boolean isNeedLoadUrl(WebView webView,
                    ResourceRequest resourceRequest) {
                    return super.isNeedLoadUrl(webView, resourceRequest);
                }
            });
            webView.load(textField.getText());
        });
    }
    ...
}

运行效果如下图所示:

2.3 高级用法

2.3.1 加载本地页面

本地页面放在:

.../entry/src/main/resources/rawfile/local.html

读取页面内容:

webView.setWebAgent(new WebAgent() {
    @Override
    public ResourceResponse processResourceRequest(
        WebView webView, ResourceRequest request) {
        Uri uri = request.getRequestUrl();
        if (!uri.getDecodedAuthority().equals("local"))
            return super.processResourceRequest(
                webView, request);

        String path = uri.getDecodedPath();
        if (TextTool.isNullOrEmpty(path))
            return super.processResourceRequest(
                webView, request);

        if (path.startsWith("/rawfile/")) {
            path = "entry/resources/rawfile/" +
                path.replace("/rawfile/", "");
            String mimeType = URLConnection
                .guessContentTypeFromName(path);

            try {
                Resource data = getResourceManager()
                    .getRawFileEntry(path).openRawFile();
                return new ResourceResponse(
                    mimeType, data, null);
            }
            catch (IOException exception) {
                return super.processResourceRequest(
                    webView, request);
            }
        }
        else if (path.startsWith("/file/")) {
            path = getContext().getFilesDir() +
                path.replace("/file/", "/");
            String mimeType = URLConnection
                .guessContentTypeFromName(path);

            try {
                InputStream data = new FileInputStream(
                    new File(path));
                return new ResourceResponse(
                    mimeType, data, null);
            }
            catch (FileNotFoundException exception) {
                return super.processResourceRequest(
                    webView, request);
            }
        }

        return super.processResourceRequest(webView, request);
    }
});

加载本地页面:

webView.load("https://local/rawfile/local.html");

2.3.2 与页面中的JavaScript代码交互

2.3.2.1 允许交互
webView.getWebConfig().setJavaScriptPermit(true);
2.3.2.2 页面调应用
2.3.2.3 应用调页面

例程:Advanced

...\Advanced\entry\src\main\resources\rawfile\local.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">

        <title>本地页面</title>

        <script type="text/javascript">
            function onClick() {
                var result = JsCallbackToApp.call("页面传递给应用的数据");
            }

            function add(a, b) {
                return a + b;
            }
        </script>
    </head>

	<body>
	    <center>
            <input type="button" value="页面向应用传递数据" onclick="onClick()" />
        </center>
    </body>
</html>

...\Advanced\entry\src\main\resources\base\layout\ability_main.xml

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">

    <ohos.agp.components.webengine.WebView
        ohos:id="$+id:wv"
        ohos:height="32vp"
        ohos:width="match_content"/>

    <Button
        ohos:id="$+id:btn"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:padding="$ohos:float:button_radius"
        ohos:top_margin="200vp"
        ohos:background_element="#ff7f27"
        ohos:text="应用向页面传递数据"
        ohos:text_size="20fp"
        ohos:text_color="#ffffff"
        />

</DirectionalLayout>

...\Advanced\entry\src\main\java\com\minwei\advanced\slice\MainAbilitySlice.java

public class MainAbilitySlice extends AbilitySlice {
    private WebView webView;
    private Button button;

    @Override
    public void onStart(Intent intent) {
        ...
        webView = (WebView)findComponentById(ResourceTable.Id_wv);
        button = (Button)findComponentById(ResourceTable.Id_btn);

        webView.setWebAgent(new WebAgent() {
            @Override
            public boolean isNeedLoadUrl(WebView webView,
                ResourceRequest resourceRequest) {
                return super.isNeedLoadUrl(webView, resourceRequest);
            }

            @Override
            public ResourceResponse processResourceRequest(
                WebView webView, ResourceRequest request) {
                Uri uri = request.getRequestUrl();
                if (!uri.getDecodedAuthority().equals("local"))
                    return super.processResourceRequest(
                        webView, request);

                String path = uri.getDecodedPath();
                if (TextTool.isNullOrEmpty(path))
                    return super.processResourceRequest(
                        webView, request);

                if (path.startsWith("/rawfile/")) {
                    path = "entry/resources/rawfile/" +
                        path.replace("/rawfile/", "");
                    String mimeType = URLConnection
                        .guessContentTypeFromName(path);

                    try {
                        Resource data = getResourceManager()
                            .getRawFileEntry(path).openRawFile();
                        return new ResourceResponse(
                            mimeType, data, null);
                    }
                    catch (IOException exception) {
                        return super.processResourceRequest(
                            webView, request);
                    }
                }
                else if (path.startsWith("/file/")) {
                    path = getFilesDir() + path.replace("/file/", "/");
                    String mimeType = URLConnection
                        .guessContentTypeFromName(path);

                    try {
                        InputStream data = new FileInputStream(
                            new File(path));
                        return new ResourceResponse(
                            mimeType, data, null);
                    }
                    catch (FileNotFoundException exception) {
                        return super.processResourceRequest(
                            webView, request);
                    }
                }

                return super.processResourceRequest(webView, request);
            }
        });

        webView.getWebConfig().setJavaScriptPermit(true);

        webView.addJsCallback("JsCallbackToApp", new JsCallback() {
            @Override
            public String onCallback(String msg) {
                new ToastDialog(getContext())
                    .setText(msg)
                    .setAlignment(LayoutAlignment.CENTER)
                    .show();
                return "RETURN_FROM_APP";
            }
        });

        button.setClickedListener(component -> {
            webView.executeJs("javascript:add(123,456)",
                new AsyncCallback<String>() {
                    @Override
                    public void onReceive(String msg) {
                        new ToastDialog(getContext())
                            .setText("123+456=" + msg)
                            .setAlignment(LayoutAlignment.CENTER)
                            .show();
                    }
                });
        });

        webView.load("https://local/rawfile/local.html");
    }
    ...
}

运行效果如下图所示:

 

更多精彩,敬请期待……


达内集团C++教学部 2021年9月22日