WebApp网页真机调试工具-(Android)

待我年逾花甲,重新回到乡下。

池里养些鱼虾,坡上满是山茶。

不见雾霾黄沙,只有朝阳晚霞。

牛羊伴着鸡鸭,瓜田李下小麻。

孙儿承欢膝下,老伴陪与床榻。

纵是满口假牙,却也笑靥如花。

现在的移动端开发主要流行Hybrid开发方式,市面上也很多框架提供了前端访问手机硬件相关的API,但是总有不能满足的时候,所以,我们就自己做一个框架来封装提供给js的各种接口(框架不是本文重点),那么问题就来了,如何调试呢?前期开发可以通过打桩的方式来模拟,但是要发布上线必须要真枪实弹的调试通过才行。于是就输出了一个调试网页的DEMO(android/ios  app),只能是通过手动输入网页地址来查看界面效果和测试接口的正确性,虽然团队没得微信那么强大开发一个桌面调试工具,但这体验和效率也确实太差了。确实不能忍,所以就写了个小玩意儿来解决这个问题。

思路:通过socket 长连接的的方式,在PC控制台输入调试的网页地址,就能立马在手机上看到网页的效果。

看看效果截图:

WebApp网页真机调试工具-(Android)_第1张图片





















WebApp网页真机调试工具-(Android)_第2张图片














要实现这个小玩意儿,需要一个简单的后端程序,代码如下:

package com.lixue;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * 
 * @author lh
 * @date 2016/12/12 11:30
 */
public class AppServer {

	public static void main(String[] args) {
		new ServerThread().start();
	}
}

class ServerThread extends Thread {
	boolean flag = false;
	ServerSocket ss;

	public void run() {
		try {
			ss = new ServerSocket(9999);// 创建服务器,并开放9999端口
			System.out.println("Server Listening on 9999...");
			flag = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		Socket sc = null;
		DataOutputStream outputStream = null;
		Scanner scanner = null;
		while (flag) {
			try {
				// 监听服务器端口,一旦有数据发送过来,那么就将数据封装成socket对象
				// 如果没有数据发送过来,那么这时处于线程阻塞状态,不会向下继续执行
				sc = ss.accept();
				System.out.println(sc.getInetAddress() + " connect...");
				outputStream = new DataOutputStream(sc.getOutputStream());
				outputStream.writeUTF("connect successful");
				scanner = new Scanner(System.in);
				while (true) {
					String line = scanner.nextLine();
					System.out.println("你输入的是:" + line);
					outputStream.writeUTF(line);
				}

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (outputStream != null) {
						outputStream.close();
					}
					if (sc != null) {
						sc.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

Android端代码如下:
package com.lixue.debugwebapp;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.KeyEvent;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
 * @author lh
 * @version 1.0.0
 * @filename MainActivity
 * @description --------------------------------------------------------
 * @date 2016/12/12 12:00
 */
public class MainActivity extends AppCompatActivity {

    public static final int CONNECT = 99;
    public static final int SUCCESS = 100;
    public static final int ERROR = 101;

    public static final String KEY_CONNECT = "connect";
    public static final String KEY_SUCCESS = "success";
    public static final String KEY_ERROR = "error";

    public static final String ADDRESS = "192.168.191.1";
    public static final int PORT = 9999;
    private TextView tv;
    private WebView webView;
    private StringBuilder sb = new StringBuilder();
    private SocketThread socketThread = null;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            String str = null;
            switch (msg.what) {
                case CONNECT:
                    str = msg.getData().getString(KEY_CONNECT);
                    tv.append("\n" + str);
                    scrollToBottom();
                    break;
                case SUCCESS:
                    str = msg.getData().getString(KEY_SUCCESS);
                    tv.append("\n" + str);
                    scrollToBottom();
                    if(isUrl(str)) {
                        webView.loadUrl(str);
                    }else{
                        tv.append("\t\t\t不合法的url");
                    }
                    break;
                case ERROR:
                    str = msg.getData().getString(KEY_ERROR);
                    tv.append("\n" + str);
                    scrollToBottom();
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        connect();
    }

    @Override
    protected void onDestroy() {
        close();
        super.onDestroy();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(webView.canGoBack()){
            webView.goBack();
        }else{
            finish();
        }
        return true;
    }

    private void init() {
        tv = (TextView) this.findViewById(R.id.tv_url);
        tv.setMovementMethod(ScrollingMovementMethod.getInstance());
        webView = (WebView) this.findViewById(R.id.wv);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                webView.loadUrl(url);
                return true;
            }
        });
    }

    private void connect() {
        if (socketThread == null) {
            socketThread = new SocketThread(ADDRESS, PORT, handler);
            socketThread.start();
            tv.append("发起建立连接请求");
            tv.append("\n" + ADDRESS + ":" + PORT);
            scrollToBottom();
        }
    }

    private void close() {
        if (socketThread != null) {
            socketThread.closeThread();
            socketThread = null;
        }
    }


    /**
     * TV滚动到底部
     */
    private void scrollToBottom() {
        int offset = tv.getLineCount() * tv.getLineHeight();
        if (offset > tv.getHeight()) {
            tv.scrollTo(0, offset - tv.getHeight());
        }
    }

    private class SocketThread extends Thread {
        private String address;//ip
        private int port;//port >1023

        private Handler handler;
        private DataInputStream in;
        private Socket socket;
        private boolean flag = false;

        public SocketThread(String address, int port, Handler handler) {
            this.address = address;
            this.port = port;
            this.handler = handler;
        }

        @Override
        public void run() {
            try {
                socket = new Socket(address, port);
                in = new DataInputStream(socket.getInputStream());
                String content = in.readUTF();
                //连接成功发送消息
                sendMessage(KEY_CONNECT, content, CONNECT);
                while (!flag) {
                    content = in.readUTF();
                    //数据传输过程发送消息
                    sendMessage(KEY_SUCCESS, content, SUCCESS);
                }
            } catch (IOException e) {
                e.printStackTrace();
                //发送异常消息
                sendMessage(KEY_ERROR, e.getMessage(), ERROR);
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        public void sendMessage(String key, String value, int code) {
            Bundle bundle = new Bundle();
            bundle.putString(key, value);
            Message message = handler.obtainMessage();
            message.what = code;
            message.setData(bundle);
            handler.sendMessage(message);

        }

        public void closeThread() {
            flag = true;
        }
    }

    /**
     * 简单的判断一下是否是网址,严谨性可以自行完善
     * @param str
     * @return
     */
    public static boolean isUrl(String str) {
        boolean isUrl = false;
        if (str != null) {
            if (str.startsWith("http://") || str.startsWith("https://") || str.startsWith("ftp://")) {
                isUrl = true;
            }
        }
        return isUrl;
    }

}
好了,整体比较简单,这只是一个简单的DEMO,但是也应该可以满足网页真机调试的需求了,另外Android的界面相关优化如IP/Port等配置可以自行实现,DEMO打印了相关地址跳转、以及连接错误和异常等信息,如果需要打印输出更多的功能信息,大家可以自行优化。


最后怕很多小白不知道怎么用,总结下使用方式:

第一步:把服务端程序AppServer跑起来;

第二步:把Android代码中的Socket地址改成你自己电脑的地址;要是觉得改来改去不方便,可以自己做一个Android端的IP/Port配置界面;

第三步:连接成功后,在后端控制台输入要调试的URL地址敲上回车就可以了。服务端我用的是Eclipse,你可以用任意的IDE或者命令行只要你喜欢!!!

第四步:经过上述操作,在手机端就能实时显示后端输入的网页了。

最后,再次说明这只是一个DEMO,纯属笔者无聊花了一小时写的,要是用着不安逸可以自己修改完善,比如Socket重连啊这些。如果要求很高可以用WebSocket,代码会更加简单,重连这些也都有实现。


Android代码地址https://github.com/allmyson/DebugWebApp

完整附件地址:请点我。


你可能感兴趣的:(android)