Android 关于注入Js处理Android和H5 Js 交互问题

记录一个丑陋的BUG!!!

BUG说明:

项目对接ZegoGame 的H5游戏 需要对接游戏的H5.一些Android 和H5 交互需要相互效用....

噩梦开始了!!!

js 回调不通,后台一问三不知,产品不让我联系zego技术!!!!!日了狗了

问题说明:

参考截图

  • Android端的Js配置和H5的Js调用对不上(H5没按照文档写)

解决思路

Js 注入覆盖或者修改H5的Js方法

1:WebView 配置

核心方法

  • settings.setJavaScriptEnabled(true); 开启Js桥
  • webView.addJavascriptInterface(new GameJsBridge(this), "app"); 注册回调内容
  • onPageFinished () 页面加载完成
typescript 复制代码
private WebView initWebView() {
    webView.setBackgroundColor(Color.TRANSPARENT);
    //update webview settings
    WebSettings settings = webView.getSettings();
    settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    settings.setBuiltInZoomControls(true);
    settings.setJavaScriptEnabled(true);
    settings.setDatabaseEnabled(true);
    settings.setDomStorageEnabled(true);
    //set webview client
    webView.setWebChromeClient(new WebChromeClient());
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            Log.d(TAG, "onPageStarted");
        }
        @Override
        public void onPageFinished(WebView view, String url) {
            Log.d(TAG, "onPageFinished");
            webView.evaluateJavascript(
                    "(function() { " +
                            "   var originPostMessage = window.top.postMessage;" +
                            "   window.top.postMessage = function(data) { " +

                            "       var msg = (typeof data === 'string') ? data : JSON.stringify(data);" +

                            "       if(window.app && window.app.postMessage) {" +
                            "           window.app.postMessage(msg);" +
                            "       }" +

                            "       if(originPostMessage) {" +
                            "           originPostMessage.call(window.top, data, '*');" +
                            "       }" +

                            "   };" +
                            "})();",
                    null
            );

        }
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            String outUrl = request.getUrl().toString();
            view.loadUrl(outUrl);
            return true;
        }
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            Log.d(TAG, "onReceivedError: " + error);
        }
    });
    //add jsb
    webView.addJavascriptInterface(new GameJsBridge(this), "app");
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
  
    return webView;
}

1:Js回调桥配置

typescript 复制代码
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.JavascriptInterface;
import com.google.gson.Gson;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;

import es.dmoral.toasty.Toasty;

public class GameJsBridge {

    private static final String TAG = "Zego游戏";

    private final Context context;

    public GameJsBridge(@NotNull Context context) {
        this.context = context;
    }

    private JSONObject parseMsg(@NotNull String message) {
        try {
            return new JSONObject(message);
        } catch (JSONException e) {
            return null;
        }
    }

    @JavascriptInterface
    public void postMessage(String message) {
        Log.e(TAG, "postMessage: " + message);
        if (TextUtils.isEmpty(message)) return;
        try{

            JSONObject schemeInfo = parseMsg(message);
            if (schemeInfo == null) return;
            //'{"cid":"TO_CHARGE","params":{}
            String cid = schemeInfo.optString("cid");
            JSONObject params = schemeInfo.optJSONObject("params");
            if ("TO_CHARGE".equals(cid)) {
                // 支付
            
            } else if ("CLOSE_COCOS_VIEW".equals(cid)) {
                // 关闭全屏游戏
                if(context!=null&& context instanceof Activity)
                    ((Activity)context).finish();
            } else if ("NOTIFY_GAME_STATUS".equals(cid)) {
                if (params.optInt("status") == 4) {
                    // 🇺🇸en: When the game is settled, notify the client to refresh the balance displayed on the client
                    Toasty.normal(context, "complete").show();
                }
            }

        }catch (Exception e){

        }

    }

}

3.注入Js 代码

  • 在浏览器sources 中ctrl +shift+f 查找 GameJsBridge 中的postMessage

说明: H5 调用Js 调用的是

  • window.top.postMessage()
  • window.WTChannel.postMessage()

根据GameJsBridge 获取的是 cid 和 params

ini 复制代码
 
 String cid = schemeInfo.optString("cid");
 JSONObject params = schemeInfo.optJSONObject("params");
 

Js 代码注入 核心代码:

typescript 复制代码
public void onPageFinished(WebView view, String url) {
    Log.d(TAG, "onPageFinished");
    webView.evaluateJavascript(
            "(function() { " +
                    "   var originPostMessage = window.top.postMessage;" +
                    "   window.top.postMessage = function(data) { " +

                    "       var msg = (typeof data === 'string') ? data : JSON.stringify(data);" +

                    "       if(window.app && window.app.postMessage) {" +
                    "           window.app.postMessage(msg);" +
                    "       }" +

                    "       if(originPostMessage) {" +
                    "           originPostMessage.call(window.top, data, '*');" +
                    "       }" +

                    "   };" +
                    "})();",
            null
    );

}

总结

当H5页面为三方或者外包的代码,时不时就会出现这种情况,所以移动端要想和他们撕逼.最好具备查询这种问题的能力.

  • 定位能力
  • 注入修改能力
相关推荐
撩得Android一次心动10 分钟前
Jetpack Compose 知识点整理3【个人用】
android·笔记·学习·kotlin·android compose
Kapaseker35 分钟前
别再只会写 <T>:Kotlin 泛型的实战用法
android·kotlin
FlightYe1 小时前
音视频修炼之容器与协议(一):MP4和MOV的box剖析
android·linux·c++·ffmpeg·音视频
Vitaliy Kostrov(柯维远)3 小时前
客户端如何检查直播流:从流内标记到停止播放
android·运维·服务器·驱动开发·网络安全·系统架构·cdn
恋猫de小郭3 小时前
Dart 3.15 新特性:this 终于支持类型提升了
android·前端·flutter
ii_best4 小时前
ios手机开发安卓脚本开发软件[按键精灵教程]从「找最小值」到「Boss 最近刷新」再到「屏幕范围极值」
android·ios·智能手机·自动化·按键精灵
开开心心就好4 小时前
安卓PDF处理工具,免费无广告零弹窗
android·服务器·开发语言·算法·pdf·ocr
墨狂之逸才4 小时前
扫码枪响了,应用却没收到:一次 Android USB 线材问题排查
android
alexhilton16 小时前
Room Fts4:全文搜索替代 SQL LIKE
android·kotlin·android jetpack
hai_android21 小时前
把 Android App 打包成系统应用(System App)
android·kotlin·android jetpack