What Is Two-Way Communication Between Quick Apps and Web Pages and How Can I Implement It?

Mayism
Mayism
Mar 25 · 5 min read

Background

  • Can an HTML5 web page use the device API of a quick app to obtain device information?
  • Can an HTML5 quick app integrate ad capabilities? …

There are a lot of similar questions along these lines, and I’ll give you a simple answer: Yes, you can. Of course, an HTML5 web page cannot call standard APIs of quick apps, but quick apps can. Can the information obtained by quick apps be passed to web pages? The answer is also yes. The quick app framework provides a two-way communication between quick apps and web pages. You can send a request from a web page to a quick app and, after receiving it, the quick app processes the request and returns data to the web page.

How to Use

Implementation on the Quick App Side

On the quick app side, you can send messages to or listen to messages from a web page.

  • postMessage(): Sends a message to a web page. The sample code is as follows:

this.$element(‘web’).postMessage(senddata);

  • onmessage event: Listens to messages sent from a web page. The web component defines the message event. During implementation, the onmessage event needs to be added to the web component. The sample code is as follows (see the red part):
<web class="web-page" src="{{webUrl}}" trustedurl="{{list}}" onpagestart="onPageStart"
useragent="default"
onmessage="onMessage"
fullscreendirection="{{fullscreenDirection}}"
jumppolicy="{{linkJumpPolicy}}"
multiwindow="{{openMultiwindow}}"
onpagefinish="onPageFinish"
ontitlereceive="onTitleReceive"
onerror="onError"
id="web"
allowthirdpartycookies="{{allowThirdPartyCookies}}">
</web>

Sample code of an onMessage handler of a response event is as follows:

onMessage(e) {
console.info('onmessage e = ' + e.message + ", url = " + e.url);

var msg=e.message;
if(msg==='xxx'){
//todo
}
},

Implementation on the HTML5 Web Page Side

l system.postMessage(): Sends a message to a quick app. The sample code is as follows:

system.postMessage("xxx");

l system.onmessage(): Receives a message from a quick app. The sample code is as follows:

system.onmessage = function(data) {
console.info("onmessage data="+data);
//todo
}

Note: The preceding code must be added to the script under the head tag in the HTML file of the web page.

Integrating HUAWEI Ads Kit into an HTML5 Quick App

The process is the same as that in Accessing HUAWEI Ads Publisher Service. The only difference lies in the logic of the ad display. After you call native ads APIs for a native quick app, the native ad is directly displayed on the xx.ux page. But for an HTML quick app, the native ad needs to be displayed on web pages, which means that the result of API calls is passed to xx.ux through two-way communication.

Rewarded ads in a quick app are full-screen ads, which are automatically displayed and do not require manual implementation. This can save you much work when accessing rewarded ads for an HTML5 quick app.

The following is the sample code for an HTML5 quick app to integrate Ads Kit. You can learn the principle of two-way web communication by referring to the code.

hello.ux

<template>
<div class="doc-page">
<web class="web-page" src="{{webUrl}}" trustedurl="{{list}}" onpagestart="onPageStart"
useragent="default"
onmessage="onMessage"
fullscreendirection="{{fullscreenDirection}}"
jumppolicy="{{linkJumpPolicy}}"
multiwindow="{{openMultiwindow}}"
onpagefinish="onPageFinish"
ontitlereceive="onTitleReceive"
onerror="onError"
id="web"
allowthirdpartycookies="{{allowThirdPartyCookies}}">
</web>
</div>
</template>

<style>
.doc-page {
flex-direction: column;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
}

.web-page {
width: 100%;
height: 100%;
}
</style>
<script>
import router from "@system.router"
import prompt from '@system.prompt'
import ad from "@service.ad"
let nativeAd
let rewardedVideoAd
export default {
props: ['websrc'],
data: {
native: {
adUnitId: 'testu7m3hc4gvm',
adData: {},
errStr: '',
},
rewarded: {
adUnitId: 'testx9dtjwj8hp',
isShow: 'false',
errStr: ''
},
title: "",

// TODO Replace the link to the H5 url
webUrl: "http://xxx/h5_ad_demo.html",
allowThirdPartyCookies: true,
fullscreenDirection: "landscape",
linkJumpPolicy: "default",
openMultiwindow: false,
list: ["new RegExp('https?.*')"],
},

onPageStart(e) {
console.info('pagestart: ' + e.url)
},
// Each page switch triggers
onPageFinish(e) {
console.info('pagefinish: ' + e.url, e.canBack, e.canForward)
},
onTitleReceive(e) {
this.title = e.title;
},
onError(e) {
console.info('pageError : ' + e.errorMsg)
},
onMessage(e) {
console.info('onmessage e = ' + e.message + ", url = " + e.url);
prompt.showToast({
message: e.message + ': ' + e.url
})
var msg=e.message;
if(msg==='requestNativeAd'){
if(this.isSupportAd()){
this.requestNativeAd();
}
}else if(msg==='requestRewardAd'){
if(this.isSupportAd()){
this.requestRewardedAd();
}
}else if(msg==='reqReportNativeAdShow'){
this.reportNativeShow();

}else if(msg==='reqReportNativeAdClick'){
this.reportNativeClick();
}
},

isSupportAd:function(){
let provider = ad.getProvider();
if(provider==='huawei'){
return true;
}
return false ;
},

requestNativeAd() {
console.info("requestNativeAd");
nativeAd = ad.createNativeAd({ adUnitId: this.native.adUnitId })
nativeAd.onLoad((data) => {
console.info('nativeAd data loaded: ' + JSON.stringify(data));
this.native.adData = data.adList[0];
if (this.native.adData) {
let nativeAdObj={"nativeAdData":data};
let nativeAdMsg=JSON.stringify(nativeAdObj);
console.info("requestNativeAd onload nativeAdMsg= "+nativeAdMsg);
let senddata={"message":nativeAdMsg};
this.$element('web').postMessage(senddata);
}


})
nativeAd.onError((e) => {
console.error('load ad error:' + JSON.stringify(e));
let nativeAdErrorObj={"nativeAdDataError":e};
let nativeAdErrorMsg=JSON.stringify(nativeAdErrorObj);
console.info("requestNativeAd onError nativeAdErrorMsg= "+nativeAdErrorMsg);
let errordata={"message":nativeAdErrorMsg};
this.$element('web').postMessage(errordata);
})

nativeAd.load()
},
reportNativeShow() {
nativeAd.reportAdShow({ 'adId': this.native.adData.adId })
},
reportNativeClick() {
nativeAd.reportAdClick({ 'adId': this.native.adData.adId })
},

requestRewardedAd() {
rewardedVideoAd = ad.createRewardedVideoAd({ adUnitId: this.rewarded.adUnitId });

/** Set the callback function for successful ad loading. Call the show method to display ads.*/
rewardedVideoAd.onLoad(() => {
console.info("rewarded video ad onLoad");
rewardedVideoAd.show();
})

rewardedVideoAd.offLoad(() => {
console.info("rewarded video ad offLoad");

})

/** Listen to rewarded video ad error events.*/
rewardedVideoAd.onError((e) => {
console.error('load rewarded video ad error:' + JSON.stringify(e));
this.rewarded.errStr = JSON.stringify(e)
})

/** Listen to rewarded video ad closing events.*/
rewardedVideoAd.onClose(() => {
console.info("rewarded video ad onClose");
})

rewardedVideoAd.load();
},
onDestroy() {
nativeAd && nativeAd.destroy()
rewardedVideoAd && rewardedVideoAd.destroy()
},

isCanForward() {
this.$element('web').canForward({
callback: function (e) {
if (e) {
this.$element('web').forward();
}
}.bind(this)
})
},
isCanBack() {
this.$element('web').canBack({
callback: function (e) {
if (e) {
this.$element('web').back();
} else {
router.back();
}
}.bind(this)
})
},

onShow: function () {
console.info(" onshow");
},
onHide: function () {
console.info(" onHide");
},
onBackPress() {
this.isCanBack();
return true
},

}
</script>

h5_ad_demo.html

<html>
<head>
<title>ad Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
table.dataintable {
margin-top:10px;
border-collapse:collapse;
border:1px solid #aaa;
width:100%;
}
table.dataintable th {
vertical-align:baseline;
padding:5px 15px 5px 6px;
background-color:#d5d5d5;
border:1px solid #aaa;
text-align:left;
}
table.dataintable td {
vertical-align:text-top;
padding:6px 15px 6px 6px;
background-color:#efefef;
border:1px solid #aaa;
}
</style>

<script language="javascript">

system.onmessage = function(data) {
console.info("onmessage data="+data);
setResult(data);
var adDataObject=JSON.parse(data);
if(adDataObject.nativeAdData){
var nativeAdList=adDataObject.nativeAdData.adList[0];
if(nativeAdList){
if (nativeAdList.imgUrlList) {
var imgSrc=nativeAdList.imgUrlList[0];
document.getElementById("adImage").src= imgSrc;
console.info('ad data adImgSrc: ' +imgSrc);
}
}
}
}

function reportNativeShow() {
system.postMessage("reqReportNativeAdShow");
}

function reportNativeAdClick() {
console.info("reportNativeAdClick");
system.postMessage("reqReportNativeAdClick");
}

function getNativeAd(){
system.postMessage("requestNativeAd");
}
function getRewardAd(){
system.postMessage("requestRewardAd");
}

function setResult(str) {
document.getElementById("nativeAdDataResult").innerHTML= str
}
function setResultnew(str) {
document.getElementById("resultnew").innerHTML= str
}

function onLoadSuc(){
console.info("onLoadSuc");
reportNativeShow();
}

function openNewWeb(){
system.go("https://www.huawei.com")
}

function openNewWindow(){
window.open("http://www.w3school.com.cn")
}


</script>

</head>
<body>
<p>
H5 ad demo
</p>
<p>
ResultNativeAd: <br/> <span id="nativeAdDataResult" style="height:100px;">(unknown)</span>
</p>
<p>
ResultRewardAd: <br/> <span id="resultnew" style="height:100px;">(unknown)</span>
</p>

<hr style="height:3px;border:none;border-top:3px double red;" />
<p><button onclick="getNativeAd()">Native Ad</button></p>
<hr style="height:3px;border:none;border-top:3px double red;" />

<p><button onclick="getRewardAd()">Reward Ad</button></p>
<hr style="height:3px;border:none;border-top:3px double red;" />
<p>
<img src="/i/eg_tulip.jpg" id="adImage" alt="test ad" onclick="reportNativeAdClick()" onload="onLoadSuc()"/>
<hr style="height:3px;border:none;border-top:3px double red;" />
</p>
</body>
</html>

Summary

In this way, you can find out the answer to the question asked at the beginning.

Reference:

Web component:

https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-component-web

Ads access for a quick app:

https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-access-ads-kit

Quick app materials:

https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-introduction

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store