【问题标题】:Java and chrome extension, natives messagesJava 和 chrome 扩展,本地消息
【发布时间】:2016-10-31 23:22:25
【问题描述】:

我尝试在我的 PC 中做一个调用 java 代码的 chrome 扩展。调用工作正常,代码执行,但我尝试将变量返回到 chrome 扩展但不起作用。我在控制台中看到监听器onDisconect 写了一条控制台消息,但监听器onMessage 没有。我不知道问题所在。

这是我在 chrome 扩展中的代码:

清单 JSON

{
    "name": "Prueba native message",
    "version": "1.0",
    "manifest_version": 2,
    "description": "Chrome extension interacting with Native Messaging and     localhost.",
    "app": {
    "background": {
        "scripts": ["background.js"]
    }
},
    "icons": {
    },
    "permissions": [
        "nativeMessaging"
    ]
}

background.js

var port = chrome.runtime.connectNative('com.app.native');

function message(msg) {
    console.warn("Received" + msg);
}

function disconect() {
    console.warn("Disconnected");
}

console.warn("se ha conectado");

port.onMessage.addListener(message);
port.onDisconnect.addListener(disconect);
port.postMessage({text: "Hello, my_application"});

console.warn("message send");

这里是我的本地文件。

.bat

cd C:\Users\pc\IdeaProjects\eDNI\out\production\code && java Main

Main.java

public class Main {
    public static void main(String argv[]) throws IOException {
        System.out.println("{\"m\":\"hi\"");
    }
}

在这段代码中,我只尝试向扩展返回一条简单的消息。

【问题讨论】:

    标签: javascript java google-chrome google-chrome-extension chrome-native-messaging


    【解决方案1】:

    本机消息传递协议

    Chrome 启动每个本机消息传递主机 一个单独的进程并使用标准输入与之通信 (stdin) 和标准输出 (stdout)。相同的格式用于发送 双向消息:每条消息都使用 JSON 序列化, UTF-8 编码 并且在本机中以 32 位消息长度开头 字节顺序。来自本机的单个消息的最大大小 消息主机为 1 MB,主要是为了保护 Chrome 免受行为不端 本机应用程序。发送到的消息的最大大小 本机消息传递主机为 4 GB。

    来源: Native Messaging Protocol

    前四个字节需要是消息的长度。您需要将消息长度(整数)转换为字节数组:

    选项1:使用java.nio.ByteBuffer

    public byte[] getBytes(int length) {
        ByteBuffer b = ByteBuffer.allocate(4);
        b.putInt(length);
        return b.array();
    }
    

    选项 2: 手动:

    public byte[] getBytes(int length) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (length & 0xFF);
        bytes[1] = (byte) ((length >> 8) & 0xFF);
        bytes[2] = (byte) ((length >> 16) & 0xFF);
        bytes[3] = (byte) ((length >> 24) & 0xFF);
        return bytes;
    }
    

    写出消息长度,然后以字节为单位写出消息内容。

    String message = "{\"m\":\"hi\"}";
    System.out.write(getBytes(message.length())); 
    System.out.write(message.getBytes("UTF-8"));
    System.out.flush();
    

    更新:

    您似乎还缺少需要在清单文件中指定的接口类型。

    添加这个:"type": "stdio"

    【讨论】:

    • 我试试这个,什么也没有,控制台说同样的,我尝试更改.js,现在是这样的: chrome.runtime.sendNativeMessage('com.app.native', { text : "你好" }, function(response) { console.log("Received " + response); });控制台中的消息是“Received undefined”
    • @MarcosPires 查看我的答案的更新。您的清单中缺少接口类型 stdio。您正在使用System.out,它等同于stdout
    • @Peter 如果你说要在本地文件的清单中包含type,我有,格式是:{ "name": "com.app.native", "description": "Your desctiption", "path": "C:/Users/PC/Desktop/native message/native_app/prueba.bat", "type": "stdio", "allowed_origins": [ "chrome-extension://dmclpldhhlhdmkmikdmgpcjpcnpikgpp/" ] } 抱歉之前没有包含。 System.out 我不明白你的意思,没关系还是我错了?
    • @MarcosPires 我认为问题是write 不会刷新缓冲区,而println 会自动刷新。尝试在末尾添加System.out.flush();
    • 我添加了System.out.flush(); 什么都没有,也许错误是我用.bat 脚本调用java 和java `System.out.write´return messages to script not to chrome?
    【解决方案2】:

    我在 chrome 上使用本地主机已经有一段时间了。以下是如何开发并注意前面关于将数据发送回字节数组的评论。这部分很关键。项目的本地主机和扩展部分以及文档也可以在这个 github 上找到

    分机+文档:https://github.com/esabilbulbul/ss-ext-barcode-web 本机主机(java):https://github.com/esabilbulbul/ss-app-barcode-nativehost-java 本机主机(cpp):https://github.com/esabilbulbul/ss-app-barcode-nativehost-cpp

    清单 json

    {
    "manifest_version": 2, "version": "1.0", "name": "Hello World 3", "icons":
    {
    "128":"icons/icon128.png", "48":"icons/icon48.png", "16":"icons/icon16.png"
    }, "page_action": {
    "default_icon":"/icons/icon16.png",
    "default_popup":"popup.html" },
    "content_scripts": [
        {
            "matches":[
    "http://localhost:8080/*/*",
    "http://localhost:8080/ss-web- client/SHIPSHUK/WEBSITE/pages/merchant/reports/posdekont/mybizstats.html"
    ], "js":["content.js"]
    } ],
    "background": {
    "scripts":["background.js"],
    "persistent": false },
    "permissions": [
    "nativeMessaging", "activeTab",
    "tabs", "http://localhost:8080/*/*"
    ] }
    "externally_connectable": {
    "matches": [ ],
    "http://localhost:8080/*/*"
    "ids":[ "fhbnbigbjcmhllmfccoomobllianhofe", "*"
    ] },

    我使用此代码从页面向扩展程序发送消息

    var editorExtensionId = 'fhbnbigbjcmhllmfccoomobllianhofe';
    //chrome.runtime.sendMessage({todo: "showPageAction", value: 'test'}); //window.postMessage({ type: "showPageAction", todo: "showPageAction", text: "Hello from the webpage!" }, "*");
    // Make a simple request:
    chrome.runtime.sendMessage(editorExtensionId, {todo: "showPageAction", value: 'test2'});

    Chrome 上的本地主机注册:您还需要为 chrome 注册本地主机。如果您使用的是 Windows,请使用 regadd,如果您使用的是 linux 或 mac,请在 chrome 下的 nativemessaginghosts 文件夹下创建一个 json 文件。在我的情况下,文件夹是 /Users/esabil/Library/Application Support/Google/Chrome/NativeMessagingHosts

    最后一部分是 NATIVE HOST APP。只要您使用 stdio,您就可以使用任何语言执行此操作。我用java和cpp做到了。这是我的java部分

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package nativehost;
    
    import java.io.IOException;
    
    /**
     *
     * @author esabil
     */
    public class main {
    
        /**
         * @param args the command line arguments
         * 
         * 
         * This is NATIVE MESSAGING HOST of Chrome Extension for Barcode Printing (SHIPSHUK)
         * 
         */
        public static void main(String[] args)
        {
            // TODO code application logic here
            //System.out.println("NativeHost app is starting");
            
            String sIncomingMsg = receiveMessage();
            
            String sOutgoingMsg = "{\"text\":\"java host\"}";
            
            sendMessage(sOutgoingMsg);
            
        }
    
        //Convert length from Bytes to int
        public static int getInt(byte[] bytes) 
        {
            return  (bytes[3] << 24) & 0xff000000|
                    (bytes[2] << 16)& 0x00ff0000|
                    (bytes[1] << 8) & 0x0000ff00|
                    (bytes[0] << 0) & 0x000000ff;
        }
    
        // Read an input from Chrome Extension
        static public String receiveMessage()
        {
    
            byte[] b = new byte[4];
    
            try
            {
                System.in.read(b);
                int size = getInt(b);
    
                byte[] msg = new byte[size];
                System.in.read(msg);
    
                // make sure to get message as UTF-8 format
                String msgStr = new String(msg, "UTF-8");
    
                return msgStr;
    
            }
            catch (IOException e)
            {
                e.printStackTrace();
                return null;
            }
    
        }
        
        public static byte[] getBytes(int length) 
        {
            byte[] bytes = new byte[4];
            bytes[0] = (byte) ( length      & 0xFF);
            bytes[1] = (byte) ((length>>8)  & 0xFF);
            bytes[2] = (byte) ((length>>16) & 0xFF);
            bytes[3] = (byte) ((length>>24) & 0xFF);
            return bytes;
        }
    
        static public void sendMessage(String pMsg)
        {
            try 
            {
                System.out.write(getBytes(pMsg.length()));
                
                byte[] bytes = pMsg.getBytes();
                
                System.out.write(bytes);
            } 
            catch (IOException ex) 
            {
                ex.printStackTrace();
            }
        }
    
    
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 2012-12-06
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多