扩展 H5 容器

H5 容器组件提供丰富的扩展功能,为方便用户在更多的场景下使用 H5 容器,本文档通过示例来介绍以下 H5 容器扩展功能。

H5Plugin 获取 Activity 返回的结果

在刷脸、识别等场景中,都需要启动一个新的 Activity 以获取 Activity 返回的结果,但是在这种场景中,JSAPI 无法直接通过重写 H5Activity 来获取结果。因此在使用 H5 容器时,您需要通过以下方式来获取 Activity 返回的结果:

  1. 在自定义的 H5Plugin 中注册 OnH5ActivityResult 回调,示例如下:

    H5ActivityResultManager.getInstance().put(onH5ActivityResult);
    说明
    • put 方法不检查重复注册,开发者需自己处理防止重复注册。

    • 使用后,需要调用 remove 方法移除回调,一般建议在 H5Plugin 的 onRelease 方法中移除回调。示例如下:

    H5ActivityResultManager.getInstance().remove(onH5ActivityResult);
  2. startActivityForResult 的方式启动目的 Activity,如可以在自定义的 H5Plugin 的 handleEvent 方法中启动,示例如下:

    public boolean handleEvent(H5Event event, H5BridgeContext context) {
     if ("CustomJSAPI".equals(event.getAction())) {
         if (event.getActivity()!=null){
             Intent intent = new Intent(event.getActivity(), yourDestinationActivity.class);
             event.getActivity().startActivityForResult(intent,requestCode,bundle);
         }
         return true;
     }
     return false;
    }
    说明

    仅对 H5Activity 的 result 进行回调。

  3. OnH5ActivityResult 的回调方法中,将结果通过 H5BridgeContext 对象传递给前端。

    public interface OnH5ActivityResult {
         void onGetResult(int requestCode, int resultCode, Intent intent);
    }

自定义 H5 错误页

当您需要自定义 H5 错误页的时候,请按照以下步骤进行操作:

  1. 新建一个 HTML 格式的自定义错误页。

     <!doctype html>
     <html lang="zh-cn">
    
     <head>
       <meta charset="utf-8" />
       <meta name="viewport" content="width=device-width,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" />
       <meta name="format-detection" content="telephone=no" />
       <title>自定义错误</title>
     </head>
    
     <body>
         <p>这个页面是一个自定义错误页</p>
     </body>
    
     </html>
  2. 实现 H5ErrorPageView。在 APWebView 中设置刚才创建的错误页。

     public class H5ErrorPageViewImpl implements H5ErrorPageView {
         @Override
         public boolean enableShowErrorPage() {
             // true 表示启动自定义错误页
             return true;
         }
         @Override
         public void errorPageCallback(H5Page h5Page, APWebView view, String errorUrl, int statusCode, String errorMsg, String subErrorMsg) {
             // 获取错误页的 html,demo 中放到了 raw 中,也可以放在其他地方
             String html = H5ResourceManager.readRawFromResource(R.raw.custom_error, LauncherApplicationAgent.getInstance().getApplicationContext().getResources());
             // 将错误页设置给 webview
             view.loadDataWithBaseURL(errorUrl, html, "text/html", "utf-8", errorUrl);
         }
     }
  3. 注册 H5ErrorPageView。在打开 H5 容器之前,将自定义的 H5ErrorPageView 注册给容器。

    H5Utils.setProvider(H5ErrorPageView.class.getName(),new H5ErrorPageViewImpl());
说明

10.1.68.7 及以上版本的基线支持了新的 MPH5ErrorPageView ,方法名和使用方式与 H5ErrorPageView 一致,但是方法参数有扩展。

/**
 * 自定义网络错误页面接口
 */
public interface MPH5ErrorPageView {
    /**
     * @param h5Page      page 对象
     * @param view        webview 对象
     * @param errorUrl    错误地址
     * @param statusCode  错误码
     * @param errorMsg    错误描述
     * @param subErrorMsg 错误描述 sub
     * @param extInfo     扩展信息,请注意判空
     * @param extObj      扩展类,请注意判空
     * @return true 表示需要展示自定义页面,会走到下面 errorPageCallback 方法
     */
    boolean enableShowErrorPage(H5Page h5Page, APWebView view, String errorUrl, int statusCode, String errorMsg, String subErrorMsg, Bundle extInfo, Object extObj);
    /**
     * @param h5Page      page对象
     * @param view        webview 对象
     * @param errorUrl    错误地址
     * @param statusCode  错误码
     * @param errorMsg    错误描述
     * @param subErrorMsg 错误描述 sub
     * @param extInfo     扩展信息,请注意判空
     * @param extObj      扩展类,请注意判空
     */
    void errorPageCallback(H5Page h5Page, APWebView view, String errorUrl, int statusCode, String errorMsg, String subErrorMsg, Bundle extInfo, Object extObj);
}

开启沉浸式状态栏

若需开启沉浸式状态栏,可根据如下步骤实现:

说明
  • 此功能仅在 10.1.60 及以上基线版本中支持。

  • 此方法将设置所有 H5 容器打开的 H5 页面的状态栏颜色,如果对状态栏颜色设置有更复杂的需求,可实现 H5 容器 自定义标题栏

  • 状态栏颜色设置可在容器标题栏接口的 openTranslucentStatusBarSupport 方法中处理,也可在其他地方处理。

  1. H5 容器配置 中开启 TSBS

  2. 对于使用内置标题栏的开发者,可实现 H5TransStatusBarColorProvider 接口,并通过 H5Utils.setProvider 方法将实例设置给 H5 容器,代码示例如下:

     package com.mpaas.demo.nebula;
    
     import android.graphics.Color;
    
     import com.alipay.mobile.nebula.provider.H5TransStatusBarColorProvider;
    
     public class H5TransStatusBarColorProviderImpl implements H5TransStatusBarColorProvider {
         @Override
         public int getColor() {
             return Color.argb(70, 255, 255, 255);
         }
     }

添加第三方 JavaScriptInterface

接入方通常会遇到接入第三方页面必须要使用 JavaScriptInterface 的问题,可按照以下步骤来支持此场景:

  1. 实现插件以拦截三方页面加载事件。

  2. 获取 WebView 并注入 JavaScript 对象。

代码示例如下:

package com.mpaas.demo.nebula;

import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.alipay.mobile.h5container.api.H5BridgeContext;
import com.alipay.mobile.h5container.api.H5Event;
import com.alipay.mobile.h5container.api.H5EventFilter;
import com.alipay.mobile.h5container.api.H5Param;
import com.alipay.mobile.h5container.api.H5SimplePlugin;

public class TechFinSitePlugin extends H5SimplePlugin {

    @Override
    public void onPrepare(H5EventFilter filter) {
        super.onPrepare(filter);
        filter.addAction(CommonEvents.H5_PAGE_SHOULD_LOAD_URL);
    }

    @Override
    public boolean interceptEvent(H5Event event, H5BridgeContext context) {
        String action = event.getAction();
        if (CommonEvents.H5_PAGE_SHOULD_LOAD_URL.equals(action)) {
            JSONObject params = event.getParam();
            String url = params.getString(H5Param.LONG_URL);
            if (!TextUtils.isEmpty(url) && url.contains("tech.antfin.com")) {
                event.getH5page().getWebView().addJavascriptInterface(new TechFinJavaScriptInterface(), "techFinBridge");
            }
        }

        return false;
    }
}
说明

切勿在 interceptEvent 方法中返回 true ,否则将影响容器加载页面。

package com.mpaas.demo.nebula;

import android.webkit.JavascriptInterface;

public class TechFinJavaScriptInterface {

    @JavascriptInterface
    @com.uc.webview.export.JavascriptInterface
    public String whoAmI() {
        return "It is tech fin.";
    }
}
说明

系统内核和 UC 内核使用的注解类不同,必须要兼容这两个注解类。

为 H5 容器添加过场动画

要为 H5 容器添加过场动画,只需在项目的 res/anim 文件夹下添加动画资源即可。操作步骤如下:

  1. 在项目的 res 文件夹下新建 anim 文件夹,如有可跳过。

  2. 将过程动画的资源文件添加到 anim 文件夹。H5 容器根据资源文件的文件名自动识别资源文件,因此资源文件的文件名只能为 h5_slide_out_right.xmlh5_slide_out_left.xmlh5_slide_in_right.xmlh5_slide_in_left.xml。您可以参考以下示例,创建您自己的资源文件。

    • h5_slide_out_right.xml

      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
      <translate
        android:fromXDelta="0%"
        android:toXDelta="100%"
        android:duration="300" />
      </set>
    • h5_slide_out_left.xml

      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
      <translate
        android:fromXDelta="0%"
        android:toXDelta="-100%"
        android:duration="300" />
      </set>
    • h5_slide_in_right.xml

      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
      <translate
        android:fromXDelta="100%"
        android:toXDelta="0"
        android:duration="300" />
      </set>
    • h5_slide_in_left.xml

      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
      <translate
        android:fromXDelta="-100%"
        android:toXDelta="0%"
        android:duration="300" />
      </set>

为 H5 容器的 JSAPI 配置黑名单

指定域名调用容器 JSAPI 做权限管控时,可以通过配置黑名单的方式处理。具体步骤如下:

  1. 继承 H5JSApiPermissionProvider 类,重写 hasDomainPermission 方法。hasDomainPermission 方法两个入参分别为 actionurlaction 表示自定义 JSAPI 的事件名称,url 表示当前页面访问的域名地址。返回值为 boolean 类型。true 表示可以处理该事件,false 表示无权限处理该事件。以下为 Demo 代码,仅供参考。

    public class H5JSApiPermissionProviderImpl implements H5JSApiPermissionProvider {
         private static final List blackList = new ArrayList<String>();
         static {
         // 在黑名单列表中的 url 将无权限执行 JSAPI 等相关事件
         blackList.add("https://mcube-prod.cn-hangzhou.oss.aliyuncs.com/ONEX4B905F1032156-MUAT/20210728/0.0.0.1_all/nebula/fallback/www/index.html");
         }
    
         @override
         public boolean hasDomainPermission(String action, String url) {
             // 接入者可以根据 action 名称和 url 来判断是否有权限执行当前的 action。
             // action 就是定义的 JSAPI 事件,返回 true 代表可以处理该事件,返回 false 代表无权限处理该事件
             if (blackList.contains(url)) {
                 return false;
             }
             return true;
         }
         @override
         public boolean hasThisPermission(String permission, String url) {
             return true;
         }
    }
  2. 在框架初始化完成之后设置 Provider

    H5Utils.setProvider(H5JSApiPermissionProvider.class.getName(), new H5JSApiPermissionProviderImpl());