Custom JavaFX WebView Protocol Handler

后端 未结 3 618
孤街浪徒
孤街浪徒 2020-12-18 10:43

I am trying to write my own protocol handler for a JavaFX application that uses webview to access a single website. What I have done so far

My custom URLStreamHandle

3条回答
  •  天命终不由人
    2020-12-18 11:11

    It might be that all you are missing is a setDoInput(true) or override getDoInput() and return true (that's what i did).

    If that does not help check out my working solution:

    MyURLStreamHandlerFactory:

    import java.net.URLStreamHandler;
    import java.net.URLStreamHandlerFactory;
    
    public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory
    {
    
        public URLStreamHandler createURLStreamHandler(String protocol)
        {
            if (protocol.equals("myapp"))
            {
                return new MyURLHandler();
            }
            return null;
        }
    
    }
    

    Register Factory:

    URL.setURLStreamHandlerFactory(new MyURLStreamHandlerFactory());
    

    MyURLHandler :

    import java.io.IOException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.net.URLStreamHandler;
    
    public class MyURLHandler extends URLStreamHandler
    {
    
        @Override
        protected URLConnection openConnection(URL url) throws IOException
        {
            return new MyURLConnection(url);
        }
    
    }
    

    MyURLConnection:

    import java.io.*;
    import java.net.SocketTimeoutException;
    import java.net.URL;
    import java.net.URLConnection;
    
    /**
     * Register a protocol handler for URLs like this: myapp:///pics/sland.gif
    */ public class MyURLConnection extends URLConnection { private byte[] data; @Override public void connect() throws IOException { if (connected) { return; } loadImage(); connected = true; } public String getHeaderField(String name) { if ("Content-Type".equalsIgnoreCase(name)) { return getContentType(); } else if ("Content-Length".equalsIgnoreCase(name)) { return "" + getContentLength(); } return null; } public String getContentType() { String fileName = getURL().getFile(); String ext = fileName.substring(fileName.lastIndexOf('.')); return "image/" + ext; // TODO: switch based on file-type } public int getContentLength() { return data.length; } public long getContentLengthLong() { return data.length; } public boolean getDoInput() { return true; } public InputStream getInputStream() throws IOException { connect(); return new ByteArrayInputStream(data); } private void loadImage() throws IOException { if (data != null) { return; } try { int timeout = this.getConnectTimeout(); long start = System.currentTimeMillis(); URL url = getURL(); String imgPath = url.toExternalForm(); imgPath = imgPath.startsWith("myapp://") ? imgPath.substring("myapp://".length()) : imgPath.substring("myapp:".length()); // attention: triple '/' is reduced to a single '/' // this is my own asynchronous image implementation // instead of this part (including the following loop) you could do your own (synchronous) loading logic MyImage img = MyApp.getImage(imgPath); do { if (img.isFailed()) { throw new IOException("Could not load image: " + getURL()); } else if (!img.hasData()) { long now = System.currentTimeMillis(); if (now - start > timeout) { throw new SocketTimeoutException(); } Thread.sleep(100); } } while (!img.hasData()); data = img.getData(); } catch (InterruptedException e) { e.printStackTrace(); } } public OutputStream getOutputStream() throws IOException { // this might be unnecessary - the whole method can probably be omitted for our purposes return new ByteArrayOutputStream(); } public java.security.Permission getPermission() throws IOException { return null; // we need no permissions to access this URL } }

    Some parts of MyURLConnection might not be necessary for it to work, but like this it works for me.

    Usage in JavaFX WebView:

    
    

    Note about permissions:

    I used an applet with AllPermissions for my test with the above code.

    In a Sandbox-Applet this won't work, as the setFactory permission is missing.

提交回复
热议问题