1 Star 3 Fork 0

ScenarioSamples/Web

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

Web场景Demo案例

介绍

本示例共介绍了五种Web相关的使用场景。为开发者提供了Web页面请求拦截加载、PDF预览以及下载、Web页面与应用侧交互等功能,方便开发者开发类似场景。

效果预览

Web用户权限校验以及应用广告

输入图片说明

PDF文件浏览以及下载

输入图片说明

Web页面手机充值

输入图片说明

Web页面实名认证

输入图片说明

Web页面长按菜单

输入图片说明

使用说明

场景1 :Web用户权限校验以及应用广告:

  1. 点击对应的web页浏览信息,跳转并加载本地对应的web信息页。

  2. Web信息页会对请求拦截,加载本地资源以及只加载允许加载的信息页。

  3. 信息页内有应用广告,点击拉起应用详情进行下载或打开应用。

场景2 :PDF文件浏览以及下载

  1. 点击选择要浏览的本地文件,会拉起文件管理,并展示后缀为pdf的文件,选择后使用Web加载浏览。
  2. 在浏览网络PDF文件中,可点击PDF下载图标或下载按钮实现网络图片下载至文件管理中。

场景3 :Web页面手机充值

  1. 点击Web页面联系人图标,拉起手机联系人并进行展示。
  2. 选择联系人后,会自动填充对应的手机号,无须手动输入手机号进行充值。

场景4 :Web页面实名认证

  1. 点击Web页面的身份证正面照以及身份证反面照,拉起图库进行选择图片或拍照。
  2. 选择图片或完成拍照后,将图片在HTML的img标签显示。

场景5 : Web页面长按菜单

  1. 长按Web页面元素,会在元素显示菜单弹窗。
  2. 选择对应的菜单进行复制、拉起应用等操作。

实现思路

Js桥接交互

前端页面与ArkTs通过Js桥接交互,在后续场景中均有使用,故先介绍其实现。

1.实现桥接代码,便于js调用ArkTs代码。

// 桥接代码
export const code = `
  const JSBridgeMap = {};
  let callID = 0;

  function JSBridgeCallback (id, params){
    JSBridgeMap[id](params);
    JSBridgeMap[id] = null;
    delete JSBridgeMap[id];
  }
  // js侧通过window.ohosCallNative.callNative(methodname...)来进行调用
  window.ohosCallNative = {
    callNative(method, params, callback){
      const id = callID++;
      const paramsObj = {
          callID: id,
          data: params || null
      }
      JSBridgeMap[id] = callback || (() => {});
      JSBridgeHandle.call(method, JSON.stringify(params
      Obj));
    }
  }
`;

2.在前端页面的onPageBegin阶段时初始化js桥接代码以及设置javaScriptProxy属性来实现js调用方法。

Web({ src: this.webUrl, controller: this.webviewController })
    .onPageBegin(() => {
        // 通过controller的runJavaScript(code)进行初始化
        this.jsBridge.initJsBridge();
    })
    .javaScriptProxy(this.jsBridge.javaScriptProxy)
// 与js桥接代码中的JSBridgeHandle.call进行关联,调用JsBridge对象的call方法
get javaScriptProxy(): JavaScriptItem {
  let result: JavaScriptItem = {
    object: {
      call: this.call
    },
    name: "JSBridgeHandle",
    methodList: ['call'],
    controller: this.controller
  }
  return result;
}

3.实现call方法,根据调用的方法名触发对应的方法进行处理。详细代码见JsBridge.ets。

call = (func: string, params: string): void => {
  const paramsObject: ParamsItem = JSON.parse(params);
  let result: Promise<string> = new Promise((resolve) => resolve(''));
  switch (func) {
  	case methodname:
        function()
        break;
  }
}

4.前端页面js调用示例。

// Invoke ArkTS call and use the data.
function chooseContact() {
  window.ohosCallNative.callNative('chooseContact', {}, (data) => {
    const phone = data.split('_')[0];
    const name = data.split('_')[1];
    const result = splitPhone(phone);
    document.getElementById('phone_tip').innerHTML = name;
    document.getElementById('phone').value = result;
    window.ohosCallNative.callNative('changeTel', { tel: result });
  })
}

场景1 :Web用户权限校验以及应用广告

1.Web用户权限校验以及应用广告场景。该场景演示跨域加载页面,通过设置onInterceptRequest属性,对请求进行拦截并替换加载本地资源。

Web({ src: this.webUrl, controller: this.webviewController })
    .height($r('app.float.web_height'))
    .onInterceptRequest((event) => {
        if (!event) {
            return;
        }
        let response = new WebResourceResponse();
        // 在reponse中设置本地资源,并返回
        response.set...
        return response
    })

2.Web应用广告是通过js方法调用方法实现的,实现原理详解 Js桥接交互;调用loadAppDetail方法来加载应用详情。

// 应用侧方法
export function loadAppDetail(context: common.UIAbilityContext) {
  try {
    const request: Want = {
      parameters: {
        // 此处填入要加载的应用包名,例如: bundleName: "com.huawei.hmsapp.appgallery"
        bundleName: 'com.huawei.hmsapp.appgallery'
      }
    };
    productViewManager.loadProduct(context, request);
  } catch (err) {
    Logger.error('TAG', `loadProduct failed.code is ${err.code}, message is ${err.message}`);
  }
}

// 前端侧js方法
function appAdv() {
    window.ohosCallNative.callNative('appAdvertise', {})
}

场景2 :PDF文件浏览以及下载

1.在浏览本地文件中,Web组件开启文档对象模型存储接口domStorageAccess,实现能正常加载PDF文件。实现selectFile方法,从本地文件管理中选择pdf文件,返回url文件路径后,通过webController的loadUrl进行加载。***注:***隐藏PDF操作按钮栏时, 需要在链接后面加#toolbar=0&navpanes=0

Web({ src: uri, controller: this.controller })
    .domStorageAccess(true)

// 从文件管理选择pdf文件
export async function selectFile(context: common.Context) {
  let documentPicker = new picker.DocumentViewPicker(context);
  let documentSelectOptions = new picker.DocumentSelectOptions();
  documentSelectOptions.maxSelectNumber = 1
  // 目前只支持pdf文件
  documentSelectOptions.fileSuffixFilters = ['.pdf']
  return documentPicker.select(documentSelectOptions);
}
  1. 在浏览网络PDF文件中,设置webview.WebviewController.setDownLoad以及webview.WebviewController.startDownLoad来实现点击下载图标以及下载按钮下载网络PDF文件。
Web({ src: CommonConstants.REMOTE_URL, controller: this.controller })
    // 给下载图标设置下载事件,点击即触发
    .onPageBegin(() => {
        setDownLoad(this.controller, this.delegate)
    })
    .domStorageAccess(true)

// 给下载图标设置下载事件
export function setDownLoad(controller: webview.WebviewController, delegate: webview.WebDownloadDelegate) {
  setBeforeDownload(delegate);
  // 与PDF文件下载图标绑定, 点击触发下载事件
  controller.setDownloadDelegate(delegate);
}

// 下载前事件处理
function setBeforeDownload(delegate: webview.WebDownloadDelegate) {
  delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
    let filePath = getContext().cacheDir + webDownloadItem.getSuggestedFileName();
    // 将文件下载至沙箱,沙箱路径为sanPath
    webDownloadItem.start(filePath);
    // 选择文件管理目录, 将沙箱文件拷贝至选择的文件管理目录中
    saveFile(webDownloadItem.getSuggestedFileName(), filePath);
  })
}

// 启动下载
export function startDownLoad(uri: string, controller: webview.WebviewController,
  delegate: webview.WebDownloadDelegate) {
  setBeforeDownload(delegate);
  controller.startDownload(uri)
}

场景3 :Web页面手机充值

  1. Web页面调用通讯录获取手机号是通过Js调用实现的,实现原理详见 Js桥接交互。使用chooseContact方法来选择手机号。
// 前端js方法
function chooseContact() {
  window.ohosCallNative.callNative('chooseContact', {}, (data) => {
    const phone = data.split('_')[0];
    const name = data.split('_')[1];
    const result = splitPhone(phone);
    document.getElementById('phone_tip').innerHTML = name;
    document.getElementById('phone').value = result;
    window.ohosCallNative.callNative('changeTel', { tel: result });
  })
}

// 应用侧实现方法
static chooseContact = (): Promise<string> => {
  let phone = '';
  let name = '';
  return new Promise((resolve) => {
    let promise = contact.selectContacts();
    promise.then((info: Array<contact.Contact>) => {
      resolve(phone + '_' + name);
    }).catch((err: object | string) => {
      // error日志
    });
  })
}

场景4 :Web页面实名认证

1.添加Web组件,设置onShowFileSelector属性,接收HTML页面中input的点击事件。在onShowFileSelector中调用selectImages接口,拉起图库进行选择或拍照,并通过callback回调方法获得照片的uri。然后将uri放在FileSelectorResult中,通过event参数返回给HTML页面。

Web({ src: this.webUrl, controller: this.webviewController })
  .onShowFileSelector((event: FileResult) => { // event表示文件选择事件,其中result可以存储选择的图片/文件片路径,fileSelector可以设置文件选择器的部分属性
    CameraOperations.selectImages(1).then((urls: string[]) => {
      event?.result.handleFileList(urls)
    })
    // 当返回值为true时,用户可以调用系统提供的弹窗能力。当回调返回false时,绘制的自定义弹窗无效。
    return true;
  })
  1. 实现selectImages方法,拉起图库进行选择或拍照。
static async selectImages(maxSelectNumber = 5) {
  const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); // 创建图片-音频类型文件-预览的图库选项实例
  // 选择媒体文件类型和选择媒体文件的最大数目
  photoSelectOptions.recommendationOptions = {
    recommendationType: photoAccessHelper.RecommendationType.ID_CARD
  }
  photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 选择媒体文件类型为Image
  photoSelectOptions.maxSelectNumber = maxSelectNumber; // 选择媒体文件的最大数目
  // 创建图库选择器实例,调用photoViewPicker.select()接口拉起图库界面进行文件选择,文件选择成功后,返回photoSelectResult结果集。
  const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
  let photoSelectResult = await photoViewPicker.select(photoSelectOptions)
  // select返回的uri权限是只读权限,需要将uri写入全局变量@State中即可进行读取文件数据操作。
  return photoSelectResult.photoUris;
}

场景5 : Web页面长按菜单

1.设置Web组件onContextMenuShow属性,获取Web页面元素的状态标识;设置bindPopup属性,为Web组件设置Popup弹窗。

Web({ src: this.webUrl, controller: this.webviewController })
    .onContextMenuShow((event) => {
        if (event) {
            // 对长按元素进行状态标识以及获取长按位置
        }
    })// 根据分类的状态标识进行相应操作
    .bindPopup(this.showMenu, PopupOptions)
  1. 自定义menuBuilder,实现不同的元素要执行的操作。
  @Builder
  menuBuilder() {
    // 以垂直列表形式显示的菜单。
    Menu() {
      ForEach(this.holdMenuItemKeys, (holdMenuItemKey: number) => {
        ForEach(this.holdMenuItemMap.get(holdMenuItemKey), (holdMenuItem: HoldMenuItem) => {
          this.menuItemBuilder(holdMenuItem.content, holdMenuItem.func)
        })
      })
    }
  }

工程解构&模块类型

entry                                          // hap类型, 场景页面代码所在模块
    | ---pages
    | | ---MainPage.ets                           // 场景分类主页
    | ---views
    | | ---holdingMenu                            // web页面长按菜单页面
    | | ---identityVerification                   // web页面实名认证
    | | ---news                                   // Web用户权限校验以及应用广告
    | | ---pdfFileReadAndDownload                 // PDF文件预览以及下载
    | | ---selectContact // Web页面手机充值
InteractWebAndApp // har模块,web前端页与应用侧交互实现
LoadWebPage // har模块,web前端页加载以及公共实现

参考资料

Web组件

一份简单的问卷反馈

亲爱的Harmony Next开发者,您好!
为了协助您高效开发,提高鸿蒙场景化示例的质量,希望您在浏览或使用后抽空填写一份简单的问卷,我们将会收集您的宝贵意见进行优化

点击此处填写问卷

空文件

简介

取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/scenario-samples/web.git
git@gitee.com:scenario-samples/web.git
scenario-samples
web
Web
master

搜索帮助