背景
阳光沙滩客户端展示文章是webview实现的,有部分功能可以直接vue完成,有部分功能可以由原生独立完成。 目前打赏功能通过原生端做的。接下来涉及到Android如何和web通信的例子。
原生打赏实现
先看看我们效果。
上面是我开发的阳光沙滩Android客户效果图。
流程是:
1:web点击打赏
,通知原生
2:原生接受通知,显示打赏弹窗ui
3:选择打赏sob,最大128,可以重复打赏,大家可以试试。
4:点击打赏后,原生调用接口,post打赏信息,完成之后,通知webview刷新打赏数据
。
这里涉及2个流程,webview通知原生
,原生通知webview
。
很多同学可能没这样的开发经历,或者没试过这样通信,以及你面试的时候可能会被问,如何和webview通信?
今天就分享我开发过程中,遇到的问题,和如何实现。
Web端发送消息给Android
发送方,webview。其实就是我们写的vue嘛。
<div class="btn-reward-box" @click="displayReward">
<el-button type="danger" round > 打 赏 </el-button>
</div>
//displayReward是一个方法,也就是点击调用这个方法。
displayReward() {
//通信协议,是一个json
var msg = "{\"protocol\":101,\n" +
"\"data\":{\n" +
"\"articleId\":\"aid\"\n" +
"}\n" +
"}";
//把文章id填进去
let newMsg = msg.replace("aid", this.aid);
try{
//DebugApp对象调用nativeDisplayReward方法
DebugApp.nativeDisplayReward(newMsg);
}catch (e) {
console.log("app未注入");
}
},
DebugApp
调用nativeDisplayReward
直接写这行代码,不需要任何定义,就这样。
客户端:Android
javaScriptEnabled = true
//注入对象DebugApp
vb.webView.addJavascriptInterface(mAndroidJs, "DebugApp")
具体对象实现
package com.android.debug.model.bean;
import android.webkit.JavascriptInterface;
import sj.mblog.LL;
public class AndroidtoJs extends Object {
private CallBack mCallBack;
public AndroidtoJs(CallBack callBack) {
mCallBack = callBack;
}
// 被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void nativeDisplayReward(String msg) {
LL.d("web$msg");
if (mCallBack != null) {
mCallBack.recMsg(msg);
}
}
public interface CallBack {
void recMsg(String msg);
}
}
看我们activity实现。
private val mAndroidJs = AndroidtoJs { msg ->
//在这里拿的我们的json,转bean(这里就接收 )
val priceInfo = GsonUtils.getInstance().convert(msg, WebMsgPrice::class.java)
//显示打赏
···
点击之后打赏接口
····
}
就这么简单,web通知原生。
原生通知webview
上面的AndroidtoJs中收到打开打赏的信息,我们弹窗,如果点击打赏,成功了,我们需要通知web更新打赏列表。
先看原生:
override fun startObserve() {
viewModel.sendPriceMsg.observe(this) {
//通知webview,更新打赏列表
//nativeCallUpdateReward,这是我们在web中定义的方法。
callJs("nativeCallUpdateReward", "")
}
}
private fun callJs(name: String, args: String) {
val url = "javascript:$name('$args')"
vb.webView.loadUrl(url)
}
原生没有了。就这样,如果有参数,可以传递""。
看web的实现:
在方法中先定义好一个更新打赏的方法
methods:{
nativeCallUpdateReward(){
console.log("更新打赏数据");
let that = this;
api.getSobArticlePrice(this.aid).then(resp => {
//更新打赏。。。。。。
},
}
mounted(){
//页面挂载注册方法
window.nativeCallUpdateReward = this.nativeCallUpdateReward;
}
完了~~~
这样就实现了相互通信。
当然,还有其他方法,大家也可以尝试的~
文章的web加载我已经公开了,如果要用直接看这个文章:https://www.sunofbeach.net/a/1495002988458078210
2022年02月24日14:29:58:特别提示: 原生这边的通信协议: 1:收到打赏调起通知
webview打开js支持
javaScriptEnabled = true
//注入对象DebugApp
webView.addJavascriptInterface(mAndroidJs, "DebugApp")
mAndroidJs对象中通信方法定义:
通信对象:
public class AndroidtoJs extends Object {
private CallBack mCallBack;
public AndroidtoJs(CallBack callBack) {
mCallBack = callBack;
}
// 被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
public void nativeDisplayReward(String msg) {
LL.d("web$msg");
if (mCallBack != null) {
mCallBack.recMsg(msg);
}
}
public interface CallBack {
void recMsg(String msg);
}
}
通信方法:nativeDisplayReward
名字贴过去就行了,一定是这个,不能是其他,而且这个AndroidtoJs必须keep,不能被混淆的!
整个接受打赏按钮的响应协议就这么多代码了。
2:更新打赏列表 原生通知webview,更新,其实是原生:通知web调用一次加载打赏列表的接口。
通知更简单了:
override fun startObserve() {
viewModel.sendPriceMsg.observe(this) {
//当我们打赏成功了,通知webview,更新打赏列表
//nativeCallUpdateReward,这是我们在web中定义的方法。
callJs("nativeCallUpdateReward", "")
}
}
private fun callJs(name: String, args: String) {
//构造一个js通知,load一下就好了。
val url = "javascript:$name('$args')"
webView.loadUrl(url)
}
2022年2月24日21:52:21,更新支持文章显示评论入口,点击后通过原生实现评论。
协议:1
点击评论后,通知客户端,客户端接收显示评论
AndroidtoJs类中增加
/**
* 唤起原生评论弹窗
*
* @param msg let msg = "{\"protocol\":102,\n" +
* "\"data\":{\n" +
* "\"articleId\":\"aid\"\n" +
* "}\n" +
* "}";
*/
@JavascriptInterface
public void nativeDisplayComments(String msg) {
LL.d("web: " + msg);
if (mCallBack != null) {
mCallBack.recMsg(msg);
}
}
当收到102的情况下,就是拉起原生评论,然后里面有文章id,评论的接口需要用到。
协议2:
当评论成功后,客户端需要通知web更新评论数据
//通知webview,更新评论列表
callJs("nativeCallUpdateComments", "")
private fun callJs(name: String, args: String) {
val url = "javascript:$name('$args')"
vb.webView.loadUrl(url)
}
2022年02月25日09:36:00:更新,原生方法给错了,应该是nativeDisplayComments
TODO
回复评论功能,看心情开发~??心情好啊。
2022年2月26日11:44:41更新:评论回复功能。
协议:
点击父评论回复
,或者子评论回复
,都跑这个协议 nativeDisplayReplyComments
@JavascriptInterface
public void nativeDisplayReplyComments(String msg) {
LL.d("web: " + msg);
//msg中包含了返回的 协议,103回复评论,里面有回复评论需要的参数
if (mCallBack != null) {
mCallBack.recMsg(msg);
}
}
协议:点赞
,code:104
,包含点赞需要的参数
@JavascriptInterface
public void nativeArticleThumb(String msg) {
LL.d("web: " + msg);
if (mCallBack != null) {
mCallBack.recMsg(msg);
}
}
总结
文章交互和通信协议,到此告一段落。
至于如何评论,如何回复评论,是客户端自己做的ui,大家可以各种实现。
点赞同理~~
后续计划:开发问答模块,看心情吧。