WiFiとホットスポット開発-tcp接続リアルタイムログを表示

19094 ワード

私は長年Androidスマートデバイスの開発に従事し、携帯電話、MiFi、スマートドアロックなどの製品を作ったことがあります.携帯電話のほか、他の製品は後期のメンテナンスとバージョンの反復の過程で、デバイスのログを分析して問題を特定する必要があります.例えば、スマートドアロックは、故障したとき、いつもノートパソコンを持って、デバイスのusbデバッグスイッチを開けた後、問題の再現とログ分析をusb線接続デバイスで行います.もちろん、ログの取得方法は多種多様で、ネット上でアップロードすることもできます.しかし、必ず現場を見る必要があります.現場を見ると問題があります.ノートパソコンは持ち歩いているわけではありません.携帯電話は確かに持ち歩いています.そのため、携帯電話側でリアルタイムに設備のログを見ることができますか.答えは肯定的だ.MiFiとスマートドアロックはホットスポットを開放しているため、デバッグした携帯電話は設備のホットスポットに接続でき、グループネットワークを行った後、リアルタイムのログ表示を実現することができる.この方法では、データケーブルもノートパソコンも必要なく、usbデバッグスイッチもオンにする必要はありません.まず、サービス・エンド(プロビジョニング・エンド)について説明します.ここではスレッド・プールが使用されていることに注意してください.そのため、サービス・エンドは1対多の応答を行う基礎的な能力を備えています.
    /**
     * @     tcp  
     */
    public void startTCP() {
        if (runnableTcp != null) {
            isStart = false;
            runnableTcp = null;
        }
        try {
            runnableTcp = new TcpReceive();
            threadTcp = new Thread(runnableTcp);
            isStart = true;
            threadTcp.start();
        } catch (Exception e) {
            logd("  TCP  :" + e.getMessage());
        }

        try {
            mExe = Executors.newCachedThreadPool();//        
        } catch (Exception e) {
            logd("       :" + e);
        }
    }

    private class TcpReceive implements Runnable {
        Socket socket = null;
        ServerSocket server = null;

        public void run() {
            try {
                //server = new ServerSocket(53858);
                if (server == null) {
                    server = new ServerSocket();
                    server.setReuseAddress(true);
                    server.bind(new InetSocketAddress(53858));
                }
                allSockets = new HashSet();
                while (isRunning) {
                    if (!server.isClosed()) {
                        //logd("serverSocket "+server.hashCode()+"   53858   ...");
                        socket = server.accept();
                    }
                    if (socket != null) {
                        allSockets.add(socket);
                        //logd("  socket " + socket.hashCode() + "   ,  socket   :" + allSockets.size());
                        mExe.execute(new EchoThread(socket));
                    }

                }
            } catch (IOException e) {
                logd("serverSocket    "+e);
            }
        }
    }

    public class EchoThread extends Thread {
        Socket socket;
        PrintWriter out;        
        BufferedReader in;

        public EchoThread(Socket _socket){
            socket = _socket;
            try {
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            } catch (IOException e) {
                logd("PrintWriter BufferedReader  "+e); 
            }
        }

        public void run() {
            try {
                while (isStart) {               
                    if (socket == null || socket.isClosed() || !socket.isBound() || !socket.isConnected()) {
                        break;
                    }
                    String line = in.readLine();
                    String ip = socket.getInetAddress().toString();

                    if (ip.contains("/")) {
                        ip = ip.substring(1, ip.length());
                    }
                    if (line == null){
                        logd("line    ");
                        break;
                    }
                    String temp[] = line.split("/");
                    if(temp == null || temp.length <2 ||!temp[0].equals(TcpConfig._HEAD_)){
                        return;
                    }else{
                        line = temp[1];
                    }

                    if (!line.equals(TcpConfig.GET_DEVICE_INFO) && !line.contains(TcpConfig.RESTART_TEST_GET_RES)){
                        logd("Tcp  app     :" + line + ";app     ip :" + ip);
                    }
                    if (line.equals(TcpConfig.GET_REAL_TIME_LOGS)) {
                        isRealTimeLogs = true;
                        App.getInstance().setRealTimeLogQueque(mQueue);

                        String logs = null;
                        while (isRealTimeLogs) {
                            try {
                                logs = mQueue.take();
                                out.println(logs);
                                Thread.sleep(20);
                            } catch (Exception e) {
                                e.printStackTrace();
                                logd(e);
                            }
                        }

                        out.print("false,quit.");
                    }
                    if (!isCmds(line)) {
                        out.println("Request Error");
                    }
                    out.flush();
                    out.close();
                    socket.close();
                    allSockets.remove(socket);  
                }
            } catch (IOException e) {
                e.printStackTrace();
                logd("socket      :" + e);
            } finally {
                try {
                    if (in != null) {
                        // logd("BufferedReader  ,hashCode:" +  in.hashCode());
                        in.close();
                    }
                    if (out != null) {
                        // logd("PrintWriter  ,hashCode:" + out.hashCode());
                        out.close();
                    }
                    if (socket != null) {
                        // logd("socket "+socket.hashCode()+"   ");
                        socket.close();
                        allSockets.remove(socket);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

コードには、他のデバイス制御インタフェースが省略されています.リアルタイムログ表示インタフェースと、リアルタイム表示インタフェースを終了することに注意してください.
if (line.equals(TcpConfig.GET_REAL_TIME_LOGS)) {
    isRealTimeLogs = true;
    App.getInstance().setRealTimeLogQueque(mQueue);

    String logs = null;
    while (isRealTimeLogs) {
        try {
            logs = mQueue.take();
            out.println(logs);
            Thread.sleep(20);
        } catch (Exception e) {
            e.printStackTrace();
            logd(e);
        }
    }

    out.print("false,quit.");
}

if(line.equals(TcpConfig.CANCEL_REAL_TIME_LOGS)){
    isRealTimeLogs = false;
    mQueue.clear();
    App.getInstance().setRealTimeLogQueque(null);
    out.print(true);
}

実はキューからログの内容をループして対端に送信します.では、ログはどこでキューに参加しますか?私はログを記録する方法をApplicationに書きましたが、工事記録ログ全体が最終的にこの方法に進みます.では、ログを記録しながらそのキューに参加すればいいです.
    /**
     * @          Log  
     */
    public static void showTestInfo(final Object msg) {
        if (msg == null || msg.toString().isEmpty()) {
            return;
        }
        String appMsg = getDateToStringStyle("MM-dd HH:mm:ss,SSS", new Date()) + ":" + msg.toString();
        if (logger == null) {
            logger = Logger.getLogger(TGTConfig.TAG);
        }
        logger.warn(appMsg);

        if(mQueue != null){
            mQueue.add(appMsg);
        }
    }

このキューは、リアルタイムログの表示コマンドを受信したときに初期化され、リアルタイムログの表示を終了したときに空になります(ログはキューに参加しません):
private static PriorityBlockingQueue mQueue;

public void setRealTimeLogQueque(PriorityBlockingQueue queue){
        mQueue = queue;
}

サービス側はこのようにして、次にクライアントを見ます.
private void startRealTimeLog(){
        cmd = TcpConfig.GET_REAL_TIME_LOGS;
        new Thread(sendTcp).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                doloop();
            }
        }).start();
    }

    private void stopRealTimeLog(){
        cmd = TcpConfig.CANCEL_REAL_TIME_LOGS;
        new Thread(sendTcp).start();
    }

    private void doloop(){
        String res = null;
        while (isStart){
            try{
                res = mQueue.take();
                addIntoList(res);
                Thread.sleep(50);
            }catch (Exception e){
                e.printStackTrace();
                logd(e);
            }
        }
        logd("loop quit.");
    }

    private void addIntoList(String string){
        if (realTimeLogs.size() > MAX_LINE) {
            realTimeLogs.removeFirst();
        }
        realTimeLogs.add(string);
        uiHandler.removeMessages(MSG_REFRESH_UI);
        uiHandler.sendMessageDelayed(Message.obtain(uiHandler,MSG_REFRESH_UI,0,0,realTimeLogs),100);
    }

    Runnable sendTcp = new Runnable() {
        @Override
        public void run() {
            BufferedReader in = null;
            PrintWriter out = null;
            Socket socket = new Socket();
            try {
                socket.connect(new InetSocketAddress(TcpUtil.hostIP, TcpConfig.port), 10 * 1000);
                if (!cmd.isEmpty()) {
                    while (socket.isConnected() && !socket.isClosed()) {
                        try {
                            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                            out.println(TcpConfig._HEAD_ + "/" + cmd);
                            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                            String line = null;
                            while ((line = in.readLine()) != null) {
                                logd(line);
                                mQueue.add(line);
                            }
                            break;
                        } catch (Exception e) {
                            e.printStackTrace();
                            logd(e);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                logd(e);
            } finally {
                try {
                    if (in != null)
                        in.close();
                    if (socket != null)
                        socket.close();
                    if (out != null)
                        out.close();
                } catch (IOException e) {
                    logd(e);
                }
            }
        }
    };

実際には、1つのスレッドがサービス側から返されたデータをブロックして読み取り、もう1つのスレッドがキューからデータを繰り返してUIスレッドに送信してUIリフレッシュを行うほど複雑ではないことがわかります.