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

  • 定位能力
  • 注入修改能力
相关推荐
张风捷特烈31 分钟前
Flutter UI 解耦 - 天下大势,合久必分, 分久必合
android·前端·flutter
蓝速科技41 分钟前
蓝速科技丨甲级写字楼会议预约屏尺寸选型与空间适配指南
android·科技
zhangjin11204 小时前
解决Android Studio gradle下载超时和缓慢问题(二)
android·ide·android studio
xingxiliang11 小时前
深入浅出 Android CTS 视频测试:从环境搭建、用例设计到底层通信原理
android·音视频
我命由我1234511 小时前
Android 开发问题:为 PDFView 设置一个带有黑色边框的背景 drawable,但边框没有生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
雨白13 小时前
深入理解 Kotlin 协程 (八):拾遗补阙,探秘官方框架的调度细节与取消闭环
android·kotlin
海天鹰15 小时前
PHP上传文件
android·开发语言·php
2501_9159184116 小时前
详解iOS App上架至App Store的全流程步骤与注意事项
android·macos·ios·小程序·uni-app·cocoa·iphone
码农coding17 小时前
android12 SystemUI之StatusBar(二)
android
Lesile19 小时前
Interview#1 历史演进:MVC · MVP · MVVM · MVI架构详解
android·android jetpack