4.7 [HarmonyOS Development] Component WebView

Author: Han Ru

Company: Procedural Coffee (Beijing) Technology Co., LTD

Columnist for Hung Mun Bus

WebView provides the ability to integrate Web pages into applications.

instructions

  • Please use the real machine or emulator to run the WebView effect, the preview does not support WebView display.
  • The WebView function is supported only on real devices with the preset WebView capability. For details, see the actual device support. Smart wearables do not support WebView.

1. How to use WebView

The WebView is derived from the generic Component and can be used just like a normal Component.

A:

Create a WebView in the XML file in the Layout directory.

<ohos.agp.components.webengine.WebView
    ohos:id="$+id:webview"
    ohos:height="match_parent"
    ohos:width="match_parent">
</ohos.agp.components.webengine.WebView>
Copy the code

2. In the mainability.java file, load the Web page using the load method.

package com.example.hanruwebview.slice;

import com.example.hanruwebview.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.webengine.WebView;

public class MainAbilitySlice extends AbilitySlice {
    private static final String EXAMPLE_URL="https://www.harmonybus.net/";
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        / / load the WebView
        WebView webView = (WebView) findComponentById(ResourceTable.Id_webview1);
        webView.getWebConfig() .setJavaScriptPermit(true);  // Add this line if the page needs JavaScript. How to use JavaScript is described in detail below
        final String url = EXAMPLE_URL; // EXAMPLE_URL is defined by the developerwebView.load(url); }}Copy the code

Since we want to open the network and need network access, we need to authorize the network. Add the following authorization information to the config.json file:

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

The structure is as follows:

Here we open the homepage of Hongmeng Bus:

Method 2:

Create a WebView in ComponentContainer.

We will create a new XML Layout file in the Layout directory: layout_webview_demo.xml. We do not need to add any control, just add the ID attribute in the root Layout.

<? 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:id="$+id:directionallayout1"
    ohos:orientation="vertical">

</DirectionalLayout>
Copy the code

Then create a new AbilitySlice, SecondAbilitySlice. Java in the slice directory

package com.example.hanruwebview.slice;

import com.example.hanruwebview.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.webengine.WebView;

public class SecondAbilitySlice extends AbilitySlice {
    private static final String EXAMPLE_URL="https://www.baidu.com/";
    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_layout_webview_demo);


        // Method 2:
        WebView webView = new WebView(getContext());
        webView.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        webView.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
        webView.getWebConfig() .setJavaScriptPermit(true);  // Add this line if the page needs JavaScript. How to use JavaScript is described in detail belowDirectionalLayout directionalLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_directionallayout1); directionalLayout.addComponent(webView); }}Copy the code

2. Load the Web page.

        final String url = EXAMPLE_URL; // EXAMPLE_URL is defined by the developer
        webView.load(url);
Copy the code

Modify the entry to the program:

package com.example.hanruwebview;

import com.example.hanruwebview.slice.MainAbilitySlice;
import com.example.hanruwebview.slice.SecondAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;

public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
// super.setMainRoute(MainAbilitySlice.class.getName());
        super.setMainRoute(SecondAbilitySlice.class.getName()); }}Copy the code

Take a look at the effect: the effect can not see, the platform audit can not pass.

Two, customized url loading behavior

When a Web page is linked, the WebView opens the target URL by default. You can customize this behavior in the following ways.

1. Customize WebAgent objects.

private class ExampleWebAgent extends WebAgent {
    @Override
    public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) {
        Uri uri = request.getRequestUrl();
        if (EXAMPLE_URL.equals(uri.getDecodedHost())) {
            // This is handled by the WebView by default
            return false;
        }

        // Add developer custom logic
        return super.isNeedLoadUrl(webView, request); }}Copy the code

2. Set custom WebAgent to WebView.

webView.setWebAgent(new ExampleWebAgent());
Copy the code

3. Browsing history

1. Get the Navigator object using the getNavigator method.

Navigator navigator = webView.getNavigator();
Copy the code

2, use canGoBack() or canGoForward() to check if you can browse backwards or forwards. Use goBack() or goForward() to browse backwards or forwards.

if (navigator.canGoBack()) {
    navigator.goBack();
}
if (navigator.canGoForward()) {
    navigator.goForward();
}
Copy the code

Use JavaScript

You can set up JavaScript calls between your application and your page in the following way.

Enable JavaScript via WebConfig.

webView.getWebConfig().setJavaScriptPermit(true);
Copy the code

2. Select the calling mode according to actual needs.

  • Inject a callback object into the page content and invoke the object from within the page.
final String jsName = "JsCallbackToApp";
webview.addJsCallback(jsName, new JsCallback() {
    @Override
    public String onCallback(String msg) {
        // Add custom processing
        return "jsResult"; }});Copy the code

The injected object is called from within the page through JavaScript code.

function callToApp(a) {
    if (window.JsCallbackToApp && window.JsCallbackToApp.call) {
       var result = JsCallbackToApp.call("message from web"); }}Copy the code
  • Calls JavaScript methods within the page from within the application.
webview.executeJs("javascript:callFuncInWeb()".new AsyncCallback<String>() {
    @Override
    public void onReceive(String msg) {
        // Confirm the returned result here}});Copy the code

Observe the Web status

Use the setWebAgent method to set custom WebAgent objects to observe events such as page state changes:

webview.setWebAgent(new WebAgent() {
    @Override
    public void onLoadingPage(WebView webView, String url, PixelMap favicon) {
        super.onLoadingPage(webView, url, favicon);
        // Customizable processing when the page starts loading
    }

    @Override
    public void onPageLoaded(WebView webView, String url) {
        super.onPageLoaded(webView, url);
        // Customizable processing after page loading
    }

    @Override
    public void onLoadingContent(WebView webView, String url) {
        super.onLoadingContent(webView, url);
        // Custom processing when loading resources
    }

    @Override
    public void onError(WebView webView, ResourceRequest request, ResourceError error) {
        super.onError(webView, request, error);
        // Custom processing when an error occurs}});Copy the code

6. Observe and browse events

Set a custom BrowserAgent object with the setBrowserAgent method to observe JavaScript events, notifications, and more:

webview.setBrowserAgent(new BrowserAgent(this) {
    @Override
    public void onTitleUpdated(WebView webView, String title) {
        super.onTitleUpdated(webView, title);
        // Customizable handling of title changes
    }

    @Override
    public void onProgressUpdated(WebView webView, int newProgress) {
        super.onProgressUpdated(webView, newProgress);
        // Customizable processing when loading progress changes}});Copy the code

Load resource files or local files

For security reasons, the WebView does not support directly loading resource files or local files through the File protocol. If the application needs to implement related services, see the following methods.

A:Through the processResourceRequest methodAccess to the file

Set a custom WebAgent object by setWebAgent method and override processResourceRequest method.

webview.setWebAgent(new WebAgent() {
    @Override
    public ResourceResponse processResourceRequest(WebView webView, ResourceRequest request) {
        final String authority = "example.com";
        final String rawFile = "/rawfile/";
        final String local = "/local/";
        Uri requestUri = request.getRequestUrl();
        if (authority.equals(requestUri.getDecodedAuthority())) {
            String path = requestUri.getDecodedPath();
            if (TextTool.isNullOrEmpty(path)) {
                return super.processResourceRequest(webView, request);
            }
            if (path.startsWith(rawFile)) {
                // Access resource files according to custom rules
                String rawFilePath = "entry/resources/rawfile/" + path.replace(rawFile, "");
                String mimeType = URLConnection.guessContentTypeFromName(rawFilePath);
                try {
                    Resource resource = getResourceManager().getRawFileEntry(rawFilePath).openRawFile();
                    ResourceResponse response = new ResourceResponse(mimeType, resource, null);
                    return response;
                } catch (IOException e) {
                    HiLog.info(TAG, "open raw file failed"); }}if (path.startsWith(local)) {
                // Access local files according to custom rules
                String localFile = getContext().getFilesDir() + path.replace(local, "/");
                HiLog.info(TAG, "open local file " + localFile);
                File file = new File(localFile);
                if(! file.exists()) { HiLog.info(TAG,"file not exists");
                    return super.processResourceRequest(webView, request);
                }
                String mimeType = URLConnection.guessContentTypeFromName(localFile);
                try {
                    InputStream inputStream = new FileInputStream(file);
                    ResourceResponse response = new ResourceResponse(mimeType, inputStream, null);
                    return response;
                } catch (IOException e) {
                    HiLog.info(TAG, "open local file failed"); }}}return super.processResourceRequest(webView, request); }});Copy the code

2. Load resource files or local files.

/ / load the resource files resources/rawfile/example. The HTML
webView.load("https://example.com/rawfile/example.html");

/ / load the local file/data/data/com. Example. Dataability/files/example. HTML
webView.load("https://example.com/local/example.html");
Copy the code

** Use Data Ability to access files

1. Create Data Ability.

public class ExampleDataAbility extends Ability {
    private static final String PLACEHOLDER_RAW_FILE = "/rawfile/";
    private static final String PLACEHOLDER_LOCAL_FILE = "/local/";
    private static final String ENTRY_PATH_PREFIX = "entry/resources";

    @Override
    public RawFileDescriptor openRawFile(Uri uri, String mode) throws FileNotFoundException {
        final int splitChar = '/';
        if (uri == null) {
            throw new FileNotFoundException("Invalid Uri");
        }

        // path will be like /com.example.dataability/rawfile/example.html
        String path = uri.getEncodedPath();
        final int splitIndex = path.indexOf(splitChar, 1);
        if (splitIndex < 0) {
            throw new FileNotFoundException("Invalid Uri " + uri);
        }

        String targetPath = path.substring(splitIndex);
        if (targetPath.startsWith(PLACEHOLDER_RAW_FILE)) {
            // Access resource files according to custom rules
            try {
                return getResourceManager().getRawFileEntry(ENTRY_PATH_PREFIX + targetPath).openRawFileDescriptor();
            } catch (IOException e) {
                throw new FileNotFoundException("Not found support raw file at "+ uri); }}else if (targetPath.startsWith(PLACEHOLDER_LOCAL_FILE)) {
            // Access local files according to custom rules
            File file = new File(getContext().getFilesDir(), targetPath.replace(PLACEHOLDER_LOCAL_FILE, ""));
            if(! file.exists()) {throw new FileNotFoundException("Not found support local file at " + uri);
            }
            return getRawFileDescriptor(file, uri);
        } else {
            throw new FileNotFoundException("Not found support file at "+ uri); }}private RawFileDescriptor getRawFileDescriptor(File file, Uri uri) throws FileNotFoundException {
        try {
            final FileDescriptor fileDescriptor = new FileInputStream(file).getFD();
            return new RawFileDescriptor() {
                @Override
                public FileDescriptor getFileDescriptor(a) {
                    return fileDescriptor;
                }

                @Override
                public long getFileSize(a) {
                    return -1;
                }

                @Override
                public long getStartPosition(a) {
                    return 0;
                }

                @Override
                public void close(a) throws IOException {}}; }catch (IOException e) {
            throw new FileNotFoundException("Not found support local file at "+ uri); }}}Copy the code

2. Register Data Ability in config.json.

{
"name": "com.example.webview.ExampleDataAbility"."type": "data"."uri": "dataability://com.example.dataability"."metaData": {
    "customizeData": [{"name": "com.example.provider"."extra": "$profile:path"}}}]Copy the code

Add path.xml to the resources/base/profile directory:

<paths>
    <root-path name="root" path="/" />
</paths>
Copy the code

3. Configure support for access to Data Ability resources.

webConfig.setDataAbilityPermit(true);
Copy the code

4. Load resource files or local files through dataAbility protocol.

/ / load the resource files resources/rawfile/example. The HTML
webView.load("dataability://com.example.dataability/rawfile/example.html");

/ / load the local file/data/data/com. Example. Dataability/files/example. HTML
webView.load("dataability://com.example.dataability/local/example.html");
Copy the code

More:

1. Community: Hongmeng Bus www.harmonybus.net/

2. Official account: HarmonyBus

3, technical exchange QQ group: 714518656

4. Video lesson: www.chengxuka.com