Android之浏览器作为客户端访问手机socket作为服务端下载图片和网页和APK

1 需求

在同一局域网内,手机(PC端)浏览器作为客户端,然后手机app里面通过socket写服务代码,然后浏览器访问手机服务端的网页和图片和css文件和下载APK 

 

 

2 代码实现

创建服务线程代码

 var serverSocket: ServerSocket? = null
    var run = true
    inner class HttpServerThread : Runnable {
        var TAG = javaClass.name
        var context : Context?= null

        constructor(context : Context){
            this.context = context
        }
        override fun run() {
            Log.i(TAG, "await start")
            try {
                //Android9.0以下开启了热点服务器的IP值是192.168.43.1,如果Android版本大于9.0 IP服务器地址会随机变
                serverSocket = ServerSocket(SocketContants.HTTP_SERVER_PORT)
//            serverSocket = ServerSocket(SocketContants.HTTP_SERVER_PORT, 10, InetAddress.
//            ("192.168.43.1"))
            } catch (e: IOException) {
                Log.i(TAG, "has error")
                e.printStackTrace()
            }
            if (serverSocket == null) {
                Log.i(TAG, "serverSocket == null")
                return;
            }
            while (run) {
                Log.i(TAG, "while (true) start")
                var socket: Socket? = null
                var input: InputStream? = null
                var output: OutputStream? = null
                try { //接收了客户端发来的请求,否则一致是等待状态
                    Log.i(TAG, "serverSocket.accept() start")
                    socket = serverSocket!!.accept()
                    Log.i(TAG, "serverSocket.accept() after")
                    input = socket.getInputStream()
                    output = socket.getOutputStream()
                    // create Request object and parse
                    val request = Request(input)
                    request.parse() //从请求中读取内容
                    Log.i(TAG, "shutdown.req=" + request.uri)
                    val response = Response(output, context)
                    response.setRequest(request)
                    response.sendDataToClient()
                    socket.close()
                } catch (e: Exception) {
                    e.printStackTrace()
                    Log.i(TAG, "Exception has error ")
                }
            }
        }
    }

开启服务代码

Thread(context?.let { HttpServerThread(it) }).start()

在onDestroy里面关闭服务代码

        //关闭socket
        if (serverSocket != null) {
            Log.i(TAG, "serverSocket != null and close")
            serverSocket!!.close()
        }
        run = false
Request.java代码


import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

public class Request {
    public static final String TAG = "Request";
    private static final int SIZE = 2048;
    private InputStream input;
    private String uri;

    public Request(InputStream input) {
        this.input = input;
    }

    public void parse() {
        StringBuffer request = new StringBuffer(SIZE);
        int i;
        byte[] buffer = new byte[SIZE];
        try {
            i = input.read(buffer); //将从输入流取2048长度的内容存到buffer字节数组中,如果内容不到2048,数组其他空间剩余空着
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        Log.i(TAG, "************Http-request*****************");
        Log.i(TAG, request.toString());
        uri = parseUri(request.toString().replace('/', '\\'));
        Log.i(TAG, "uri is:" + uri);
    }

    private String parseUri(String requestString) {
        int index1, index2;
        index1 = requestString.indexOf(' ');
        Log.i(TAG, "index1 is:" + index1);
        /*
         * http请求行的结构:方法 统一资源标识符(URI) 协议/版本(它们之间以空格分隔)
         * 例如:POST //examples/default.jsp HTTP/1.1
         */
        if (index1 != -1) {// index1 == -1表示没找到
            index2 = requestString.indexOf(' ', index1 + 1);//从index+1位置开始寻找‘ ’
            Log.i(TAG, "index2 is:" + index2);
            if (index2 > index1)
                return requestString.substring(index1 + 1, index2);
        }
        return null;
    }

    public String getUri() {
        return uri;
    }
}
Response.java代码

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;



import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Response {

    public static final String TAG = "Response";
    private static final int BUFFER_SIZE = 1024;
    public Context conext;
    Request request;
    OutputStream output;
    DataOutputStream sout;

    public Response(OutputStream output, Context conext) {
        this.output = output;
        sout = new DataOutputStream(output);
        this.conext = conext;
    }

    public Response(OutputStream output) {
        this.output = output;
        sout = new DataOutputStream(output);
    }

    public void setRequest(Request request) {
        this.request = request;
    }

    public void sendDataToClient() {
        String url = request.getUri();
        Log.i(TAG, "url is:" + url);
        if (url != null && "\\".equals(url)) {
            //发送apk
//            sendAPK(Constants.APK_NAME);
            sendHtml();
//            sendImage();
        } else if (url != null && url.contains("png")){
            sendImage();
        } else if (url != null && url.contains("css")){
            String cssName = getRequestFileName(url);
            Log.i(TAG, "css Name is" + cssName);
            sendCss(cssName);
        } else if (url != null && url.contains("apk")) {
            sendAPK(Constants.APK_NAME);
        }
    }

    /**
     * 解析url url is:\192.168.43.1:9999\download.css url is:\  url is:\192.168.43.1:9999\ic_launcher_round.png
     */
    public String getRequestFileName(String url) {
        if (TextUtils.isEmpty(url)) {
            return null;
        }
        String ss = "\\\\";
        String[] paths = url.split(ss);
        if (paths == null || paths.length == 0) {
            Log.i(TAG, "paths is null");
            return "";
        }
        String name = paths[paths.length - 1];
        Log.i(TAG, "getNameByImagePath name is:" + name);
        return name;
    }

    public void sendHtml() {
        try {
            String line="HTTP/1.1 200 OK \r\n";
            Log.i(TAG,"line="+line);
            sout.write(line.getBytes());//用字节传输,不能用字符,浏览器无法解析
            byte[] buff = new byte[1024];
            conext.getAssets().open("share/download.html").read(buff);
            String header="Content-Type: text/html; charset=utf-8 \r\n"
                    +"Content-length: "+ buff.length +" \r\n\r\n";
            Log.i(TAG,"header="+header);
            sout.writeBytes(header);
            sout.write(buff);
            sout.flush();
            sout.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sout != null)
                try {
                    sout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    public void sendCss(String fileName) {
        try {
            String line="HTTP/1.1 200 OK \r\n";
            Log.i(TAG,"line="+line);
            sout.write(line.getBytes());//用字节传输,不能用字符,浏览器无法解析
            byte[] buff = new byte[1024 * 100];
            conext.getAssets().open("share/" + fileName).read(buff);
            String header="Content-Type: text/css; charset=utf-8 \r\n"
                    +"Content-length: "+ buff.length +" \r\n\r\n";
            Log.i(TAG,"header="+header);
            sout.writeBytes(header);
            sout.write(buff);
            sout.flush();
            sout.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sout != null)
                try {
                    sout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    public void sendImage() {
        try {
            String line="HTTP/1.1 200 OK \r\n";
            Log.i(TAG,"line="+line);
            sout.write(line.getBytes());//用字节传输,不能用字符,浏览器无法解析
            byte[] buff = new byte[1024 * 100];
            conext.getAssets().open("share/ic_launcher_round.png").read(buff);
            String header="Content-Type: image/jpeg; charset=utf-8 \r\n"
                    +"Content-length: "+ buff.length +" \r\n\r\n";
            Log.i(TAG,"header="+header);
            sout.writeBytes(header);
            sout.write(buff);
            sout.flush();
            sout.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sout != null)
                try {
                    sout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    public void sendAPK(String fileName)  {

        FileInputStream fis = null;
        try {
            Log.i(TAG, "request.getUri() is:" + request.getUri());
            String apkPath = SPHelper.getInstance().getString(SpConstants.CURRENT_APK_PATH, "");
            Log.i(TAG, "apkPath is:" + apkPath);
            if (TextUtils.isEmpty(apkPath)) {
                sendHtml();
                return;
            }
            File file = new File(apkPath);
//            File file = new File("/storage/emulated/0/my.html");
            Log.i(TAG, "*************Http-response****************");
            if (file != null && file.exists()) {
                String line="HTTP/1.1 200 OK \r\n";
                Log.i(TAG,"line="+line);
                //sout.writeChars(line);
                sout.write(line.getBytes());//用字节传输,不能用字符,浏览器无法解析
//                String header="Content-Type: application/vnd.android.package-archive; charset=utf-8 \r\n"
                String header="Content-Type: application/octet-stream; charset=utf-8 \r\n"
                        + "Content-Disposition: attachment; filename=" + fileName+ "\r\n"
                        + "Content-length: "+file.length()+" \r\n\r\n";
                Log.i(TAG,"header="+header);
                sout.writeBytes(header);
                fis = new FileInputStream(file);
                /**
                byte[] bytes = new byte[BUFFER_SIZE];
                int ch = fis.read(bytes, 0, BUFFER_SIZE);;
                while (ch!=-1) { //ch==-1表示读到末尾了
                    sout.write(bytes, 0, ch); //写出到浏览器
                    Log.i(TAG, "ch is:" + ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);//再读会接上一次读的位置往下读,如果读到末尾就会返回-1,终止输出
                } **/
                byte[] buff = new byte[1024];
                int size;
                while ((size = fis.read(buff)) != -1) {
                    Log.i(TAG, "size is:" + size);
                    sout.write(buff, 0, size);
                }
                sout.flush();
                sout.close();
                fis.close();
            } else {
                // file not found
                String errorMessage = "HTTP/1.1 404 File Not Found \r\n"
                        + "Content-Type: text/html \r\n"
                        + "Content-Length: 23 \r\n"
                        + "\r\n"
                        + "<h1>File Not Found</h1>";
                System.out.println(errorMessage);
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            Log.i(TAG, "sendAPK apk has error");
            e.printStackTrace();
        } finally {
            Log.i(TAG, "finally here.............");
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (sout != null) {
                try {
                    sout.flush();
                    sout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

这个APK的路径是当前APK在手机里面的路径,然后css和html和image图片放在assets目录下的share目录

******\app\src\main\assets\share\

猜你喜欢

转载自blog.csdn.net/u011068702/article/details/106321367