1. 程式人生 > >WebApp網頁真機除錯工具-(Android)

WebApp網頁真機除錯工具-(Android)

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

池裡養些魚蝦,坡上滿是山茶。

不見霧霾黃沙,只有朝陽晚霞。

牛羊伴著雞鴨,瓜田李下小麻。

孫兒承歡膝下,老伴陪與床榻。

縱是滿口假牙,卻也笑靨如花。

現在的移動端開發主要流行Hybrid開發方式,市面上也很多框架提供了前端訪問手機硬體相關的API,但是總有不能滿足的時候,所以,我們就自己做一個框架來封裝提供給js的各種介面(框架不是本文重點),那麼問題就來了,如何除錯呢?前期開發可以通過打樁的方式來模擬,但是要釋出上線必須要真槍實彈的除錯通過才行。於是就輸出了一個除錯網頁的DEMO(android/ios  app),只能是通過手動輸入網頁地址來檢視介面效果和測試介面的正確性,雖然團隊沒得微信那麼強大開發一個桌面除錯工具,但這體驗和效率也確實太差了。確實不能忍,所以就寫了個小玩意兒來解決這個問題。

思路:通過socket 長連線的的方式,在PC控制檯輸入除錯的網頁地址,就能立馬在手機上看到網頁的效果。

看看效果截圖:



要實現這個小玩意兒,需要一個簡單的後端程式,程式碼如下:

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,程式碼會更加簡單,重連這些也都有實現。

完整附件地址:請點我

相關推薦

WebApp網頁除錯工具-Android

待我年逾花甲,重新回到鄉下。 池裡養些魚蝦,坡上滿是山茶。 不見霧霾黃沙,只有朝陽晚霞。 牛羊伴著雞鴨,瓜田李下小麻。 孫兒承歡膝下,老伴陪與床榻。 縱是滿口假牙,卻也笑靨如花。 現在的移動端開發主要流行Hybrid開發方式,市面上也很多框架提供了前端訪問手機硬體相關的AP

微信網頁除錯

手機通過USB除錯連線PC,PC 的 Chrome 遠端除錯手機上的微信web 流程就幾步,網上都有 1、手機開啟開發者模式,開啟USB除錯。 2、USB用途設定為【僅限充電】 (可以測試,開啟除錯工具後。只要一切換到別的USB用途,馬上丟失連線)。 3、除錯微信裡開啟 debugx5.

網頁除錯之Browsersync簡介

以前的除錯方式 修改完專案檔案(html、js、css等)後儲存,在瀏覽器重新整理頁面檢視修改後的效果 本地開啟一個 tomcat 服務,修改檔案後儲存重新整理頁面,移動端或其他 pc 則需要輸入 ip + 檔案路徑進行除錯 傳統除錯頁面的缺點是每次修改完程式碼,需要在相關裝置上 F5 重新

windbg 雙除錯配置xp系統

進入虛擬機器C盤 修改boot.ini檔案屬性,然後 開啟boot.ini檔案,複製一下內容到boot.ini檔案 [boot loader] timeout=5 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS [operating syst

關於SQLite的免費視覺化工具Android

SQLiteStudio (推薦)開源 免費 單檔案 http://sqlitestudio.one.pl/更新及時,功能完善的sqlite2和sqlite3工具,檢視編碼支援utf8。支援匯出資料格式:csv、html、plain、sql、xml,可同時開啟多個數據庫檔案

Android新手入門20163--Android除錯

,引用必須註明出處! 軟體開發肯定是經常需要除錯的。前文已經說過,安卓虛擬機器是很慢的,因為CPU指令不同。所以最好,最省力的方法就是真機除錯。 需要的工具--Android手機。 先說明一些東西: 手機是網際網路公司必爭之地,在兲朝,幾乎所有的PC廠商,都想往手機裡面鑽。

cordova+vue Cordova的環境搭建android測試

nod arc jdk1.8 nload 安裝 acl archive 配置環境變量 install 一、安裝node.js   去官網下載node.js(官網地址:https://nodejs.org),按默認路徑安裝。   安裝完後在命令行輸入   $ npm //(測

Android Studio 連線除錯

 寫這篇文章主要是記錄下自己在Android 學習過程中使用android studio 碰到的一些問題以及如何解決這些問題,下面我們切入話題,我以小米5為例來介紹下怎麼在Android Studio 連線真機除錯。 【步驟一】 首先主要是對手機上的一些設定如下 1.設定手

Unity Frame Debugger連線Android除錯

當用Profiler分析到不是程式碼導致的效能問題,當前場景最大的效能瓶頸時渲染時,或者自己寫的Shader要除錯時,都可以用Frame Debugger進行除錯。 按下列步驟設定打包,既可以用Profiler又可以用Frame Debugger連線Android真機: ① 手機開啟開發者模式和USB除錯

告別 USB,用 wifi 進行 Android 除錯

--------------------- 本文來自 wdeo3601 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/captive_rainbow_/article/details/81012704?utm_source=copy 先看

移動端螢幕適配通俗易懂理解viewport-除錯

真機vivo x5pro 除錯,體驗 當設定元標籤時,彈出螢幕寬度是320(個人理解單位就是px) 因為這個標籤指定了理想視口寬度,為裝置出廠固定的裝置獨立畫素 解析度320(重點:它是固定的) 註釋掉 彈出螢幕寬度 是視口預設的980(個人理解單位就是px) css

使用除錯react-native步驟安卓

1、開啟 USB 除錯 2、檢查你的裝置是否能正確連線到 ADB(Android Debug Bridge),使用adb devices命令 $ adb devices List of devices attached emulator-5554 offline

除錯eclipse.java語言編寫的android程式

這裡用華為手機為例。 1、首先將你的手機用資料線連線電腦,並將USB除錯(開發者模式)開啟。 2、開啟eclipse-windows-show View-Others-Devices開啟,如圖: 3、這樣就把真機連線到eclipse了,右擊工程-Run as 如果你發現它

【開發工具】iOS除錯抓包工具Charles安裝及使用

支援原創,更多內容請關注: iOS開發過程中,經常需要用真機來測試和後臺的網路資料傳輸,需要一個趁手的抓包工具。在Windows下用的fidder很好用,但是由於它是在.Net框架之下的,所以在Mac下需要有一個替代品,就是Charles。 一、安裝 二、

android studio關於除錯DDMS中的data資料夾打不開的解決方法

由於做開發的時候想開啟檢視資料庫存放的內容,在eclipse中資料庫檔案預設就在/data/data/應用包名/databases/資料庫名,而用android studio開啟DDMS下面找時發現點

Android Studio除錯,vvivo手機安裝失敗

vivo手機真的很麻煩,首先要確定vivo賬號密碼,允許安裝後還一直失敗。記錄下解決方案 android studio中設定 把Enable Instant。。。的勾去掉 在工程目錄的gradle.p

Mac OS X 下開發 Android 程式時使用 USB 連除錯

本人很早一篇 Mac OS X 下開發 Android 程式時使用 WiFi ADB 連真機除錯,手機端需要連線  WiFi, Root 許可權開啟 ADB 埠,電腦上執行 adb connect 命令來讓 Mac 連線 Android 真機進行除錯,其實用不著那麼麻煩

藍芽除錯Android Wear App & 解除安裝除錯的App

可穿戴裝置啥啥的市場、展望、分析、豬和風口等等...啥啥的官話就不羅嗦了,改天再換XX角色噴噴,今天記錄一個技術貼備份。 一、環境 作業系統:Mac OS X 10.10.1 開發環境:Android Studio 1.0.2 (Mac版) 手錶裝置:Moto 360 手

android studio 第一個除錯

android 開發需要使用的模擬器來測試一下應用程式的正確性,通常做法是使用模擬器,但是模擬器這個東西,太吃資源了,並且卡的太厲害了,如果有條件的話,可以使用真機來模擬測試,晚上花了點時間,用真機測試了下,遇到一些問題,記錄下來,有需要的朋友參考一下, 第一個步驟:找

如何解決android studio :nothing to show 除錯找不到裝置 的問題

情況是這樣的:前幾分鐘還在手機執行的程式,做了簡單的介面修改,沒有改配置檔案點選run的時候就找不到外接裝置跟模擬器了。出現nothing to show 百度了一下。得到的答案是* noting to show 沒什麼可秀的???*【黑人問號臉】。 然