GeckoView js交互实现

package com.scode.geckowebview1;

import static org.mozilla.geckoview.GeckoRuntimeSettings.ALLOW_ALL;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.webkit.WebMessagePort;
import android.widget.Toast;

import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.geckoview.ContentBlocking;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.GeckoSessionSettings;
import org.mozilla.geckoview.GeckoView;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.WebExtensionController;

public class MainActivity extends AppCompatActivity {
    GeckoView view_gecko = null;
    static GeckoRuntime runtime = null;
    GeckoSession session = null;
    private static WebExtension.Port mPort;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view_gecko = findViewById(R.id.view_gecko);
        
        //这个GeckoRuntimeSettings不支持 cors问题、禁用手势缩放没有效果
        GeckoRuntimeSettings.Builder builder = new GeckoRuntimeSettings.Builder()
                .allowInsecureConnections(ALLOW_ALL)
                .javaScriptEnabled(true)
                .doubleTapZoomingEnabled(false)
                .inputAutoZoomEnabled(false)
                .forceUserScalableEnabled(false)
                .aboutConfigEnabled(true)
                .webManifest(true)
                .consoleOutput(true);
        session = new GeckoSession();
        runtime = GeckoRuntime.create(this,builder.build());
        installExtension();
//        session.getSettings().setAllowJavascript(true);
//        session.getSettings().setDisplayMode(GeckoSessionSettings.DISPLAY_MODE_FULLSCREEN);
//        session.getSettings().setUserAgentMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE);
        session.open(runtime);
        view_gecko.setSession(session);
//        session.loadUri("https://www.whatismybrowser.com/");
//        session.loadUri("http://html5test.com/");
//        session.loadUri("https://liulanmi.com/labs/core.html");
        session.getSettings().setAllowJavascript(true);
        session.getPanZoomController().setIsLongpressEnabled(false);
//        session.loadUri("about:buildconfig");
        session.loadUri("http://47.102.202.2:8080/app/js1.html");
        findViewById(R.id.btn_run_js).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("method", "runJs('ok')");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                mPort.postMessage(jsonObject);
            }
        });
    }

    void installExtension() {
        runtime.getWebExtensionController()
                .ensureBuiltIn("resource://android/assets/messaging/", "messaging@example.com")
                .accept(
                        extension -> {
                            Log.i("MessageDelegate", "Extension installed: " + extension);
                            runOnUiThread(() -> {
                                extension.setMessageDelegate(mMessagingDelegate, "browser");
                            });
                        },
                        e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
                );
    }


    private final WebExtension.MessageDelegate mMessagingDelegate = new WebExtension.MessageDelegate() {
        @Nullable
        @Override
        public void onConnect(@NonNull WebExtension.Port port) {
            Log.e("MessageDelegate", "onConnect");
            mPort = port;
            mPort.setDelegate(mPortDelegate);
        }
    };


    private final WebExtension.PortDelegate mPortDelegate = new WebExtension.PortDelegate() {
        @Override
        public void onPortMessage(final @NonNull Object message,
                                  final @NonNull WebExtension.Port port) {
            Log.e("MessageDelegate", "from extension: "
                    + message);
            try {
                Toast.makeText(MainActivity.this, "收到js调用: " + message.toString(), Toast.LENGTH_LONG).show();
                JSONObject jsonObject = (JSONObject) message;
                String method = jsonObject.getString("method");
                if (method.contains("hasCamera")) {
                    JSONObject request = new JSONObject();
                    request.put("method", "androidView('hasCamera','0')");
                    mPort.postMessage(request);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnect(final @NonNull WebExtension.Port port) {
            Log.e("MessageDelegate:", "onDisconnect");
            if (port == mPort) {
                mPort = null;
            }
        }
    };

    public void evaluateJavascript(String javascriptString) {
        try {
            long id = System.currentTimeMillis();
            Log.e("evalJavascript:id:", id + "");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("action", "evalJavascript");
            jsonObject.put("data", javascriptString);
            jsonObject.put("id", id);
            Log.e("evalJavascript:", jsonObject.toString());
            mPort.postMessage(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

content.js

'use strict';
const port = browser.runtime.connectNative("browser");

let webview = {
    //关键对应@JavascriptInterface 注解方法
    raiseEvent: function(method,value) {
         browser.runtime.sendMessage({
                   method: method,
                   value: value
               });
    }
}

//关键 对应webview 注入对象
//  webView.addJavascriptInterface(new AndroidInterface(), "webview");
window.wrappedJSObject.webview = cloneInto(
    webview,
    window,
    { cloneFunctions: true });

//接收background.js 发送的消息
browser.runtime.onMessage.addListener((data, sender) => {
        let evalCallBack = {
            method: data.method
        }
        try {
            let result = window.eval(data.method);
            if (result) {
                evalCallBack.result = result;
            } else {
                evalCallBack.result = "";
            }
        } catch (e) {
            evalCallBack.result = e.toString();
            return Promise.resolve(evalCallBack);
        }
        return Promise.resolve(evalCallBack);
});



background.js

'use strict';
const port = browser.runtime.connectNative("browser");

//发送js请求到界面
async function sendMessageToTab(message) {
 try {
   let tabs = await browser.tabs.query({})
   return await browser.tabs.sendMessage(
     tabs[tabs.length - 1].id,
     message
   )
 } catch (e) {
   return e.toString();
 }
}

//监听app请求
port.onMessage.addListener(request => {
   sendMessageToTab(request).then((resp) => {
//结果回调
//       port.postMessage(resp);
     }).catch((e) => {
       post.postMessage(e)
     });
})

//接收 content.js 调用
browser.runtime.onMessage.addListener((data, sender) => {
   port.postMessage(data);
   return Promise.resolve('done');
})

manifest.xml

{
  "manifest_version": 2,
  "name": "Messaging",
  "description": "Uses the proxy API to block requests to specific hosts.",
  "version": "3.0",
  "browser_specific_settings": {
    "gecko": {
      "strict_min_version": "65.0",
      "id": "messaging@example.com"
    }
  },
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "content.js"
      ],
      "run_at": "document_start"
    }
  ],
  "background": {
    "scripts": [
      "background.js"
    ]
  },
  "permissions": [
    "nativeMessaging",
    "geckoViewAddons",
    "tabs",
    "<all_urls>"
  ],
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}

.eslintrc.js

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

module.exports = {
  env: {
    webextensions: true,
  },
};

使用geckoview版本

implementation("org.mozilla.geckoview:geckoview-omni-armeabi-v7a:111.0.20230309232128")

主要解决geckoview 通过插件方式实现js android端相互通信,

但cors问题无法解决 有知道大佬可以回复下

项目地址:GitHub - 993739033/GeckoWebView1: js demo

GeckoView 文档:GeckoRuntimeSettings

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值