23-ESP8266 SDK開發基礎入門篇--編寫Android TCP客戶端 , 加入消息處理

http://www.javashuo.com/article/p-sqrbiaas-bg.htmlhtml

 

 

先作接收消息數組

 

 

 

 

 

 

 

 而後接着緩存

 

 

 

 

 

 

 

 

 

public class MainActivity extends AppCompatActivity {

    EditText editTextActivityMain1,editTextActivityMain2;//定義兩個EditText變量,變量名字我通常設置的和先前頁面裏面的同樣
    Button buttonActivityMain1;//鏈接按鈕

    Socket socket;//定義一個Socket
    MyHandler myHandler;
    private OutputStream outputStream;//TCP發送數據使用
    private InputStream inputStream;//TCP接收數據使用

    byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        //獲取控件
        editTextActivityMain1 = findViewById(R.id.editTextActivityMain1);
        editTextActivityMain2 = findViewById(R.id.editTextActivityMain2);
        buttonActivityMain1 = findViewById(R.id.buttonActivityMain1);
        buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接"

        //鏈接按鈕點擊事件
        buttonActivityMain1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonActivityMain1.getText().toString() == "鏈接"){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //這裏面寫具體的程序
                            try {
                                socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器
                                if (socket.isConnected()){//若是鏈接上TCP服務器
                                    Log.e("MainActivity", "isConnected");
                                    Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                                    msg.what = 1;//設置消息變量的 what 變量值 爲1
                                    myHandler.sendMessage(msg);//插入消息隊列

                                    outputStream = socket.getOutputStream();//獲取輸出數據流
                                    inputStream = socket.getInputStream();//獲取輸入數據流
                                    TcpClientReceive();//加載接收函數
                                }
                            }
                            catch (Exception e){
                                Log.e("MainActivity", e.toString());
                            }
                        }
                    }).start();
                }
                else {
                    try{ socket.close(); }catch (Exception e){} //關閉鏈接
                    try{ inputStream.close(); }catch (Exception e){} //關閉數據流
                    buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
                }
            }
        });
    }

    //TCP客戶端接收數據
    public void TcpClientReceive(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面
                    try{
                        int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1

                        if(TcpReceiveDataLen!=-1){
                            byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組
                            System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 2;//設置消息變量
                            msg.obj = Buffer;//obj 能夠接收任意類型的變量
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                        else{//斷開了鏈接
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 9;//設置消息變量
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                    }catch (Exception e){//接收數據有錯誤
                        Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                        msg.what = 9;//設置消息變量
                        myHandler.sendMessage(msg);//插入消息隊列
                    }
                }
            }
        }).start();
    }



    //Handler
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1){//接收到消息變量的 what 變量值 爲1
                buttonActivityMain1.setText("斷開");//按鈕顯示斷開
            }
            else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2
                try{
                    byte[] TcpReadData = (byte[])msg.obj;//接收消息
                    Log.e("MainActivity", new String(TcpReadData) );//打印消息
                }catch (Exception e){}

            }
            else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9
                try{ socket.close(); }catch (Exception e){} //關閉鏈接
                try{ inputStream.close(); }catch (Exception e){} //關閉鏈接
                buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
            }
        }
    }
}

 

測試Android 接收數據服務器

 

 

 測試服務器忽然故障app

 

 

 

 

 

 

稍等,,我仍是直接打印一下日誌比較好socket

 

 

 

 ................有BUGide

 

 

 加上break;函數

 

再測試測試

 

 

 

public class MainActivity extends AppCompatActivity {

    EditText editTextActivityMain1,editTextActivityMain2;//定義兩個EditText變量,變量名字我通常設置的和先前頁面裏面的同樣
    Button buttonActivityMain1;//鏈接按鈕

    Socket socket;//定義一個Socket
    MyHandler myHandler;
    private OutputStream outputStream;//TCP發送數據使用
    private InputStream inputStream;//TCP接收數據使用

    byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        //獲取控件
        editTextActivityMain1 = findViewById(R.id.editTextActivityMain1);
        editTextActivityMain2 = findViewById(R.id.editTextActivityMain2);
        buttonActivityMain1 = findViewById(R.id.buttonActivityMain1);
        buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接"

        //鏈接按鈕點擊事件
        buttonActivityMain1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonActivityMain1.getText().toString() == "鏈接"){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //這裏面寫具體的程序
                            try {
                                socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器
                                if (socket.isConnected()){//若是鏈接上TCP服務器
                                    Log.e("MainActivity", "isConnected");
                                    Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                                    msg.what = 1;//設置消息變量的 what 變量值 爲1
                                    myHandler.sendMessage(msg);//插入消息隊列

                                    outputStream = socket.getOutputStream();//獲取輸出數據流
                                    inputStream = socket.getInputStream();//獲取輸入數據流
                                    TcpClientReceive();//加載接收函數
                                }
                            }
                            catch (Exception e){
                                Log.e("MainActivity", e.toString());
                            }
                        }
                    }).start();
                }
                else {
                    try{ socket.close(); }catch (Exception e){} //關閉鏈接
                    try{ inputStream.close(); }catch (Exception e){} //關閉數據流
                    buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
                }
            }
        });
    }

    //TCP客戶端接收數據
    public void TcpClientReceive(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面
                    try{
                        int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1

                        if(TcpReceiveDataLen!=-1){
                            byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組
                            System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 2;//設置消息變量
                            msg.obj = Buffer;//obj 能夠接收任意類型的變量
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                        else{//斷開了鏈接
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 9;//設置消息變量
                            myHandler.sendMessage(msg);//插入消息隊列
                            break;
                        }
                    }catch (Exception e){//接收數據有錯誤
                        Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                        msg.what = 9;//設置消息變量
                        myHandler.sendMessage(msg);//插入消息隊列
                        break;
                    }
                }
            }
        }).start();
    }



    //Handler
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1){//接收到消息變量的 what 變量值 爲1
                buttonActivityMain1.setText("斷開");//按鈕顯示斷開
            }
            else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2
                try{
                    byte[] TcpReadData = (byte[])msg.obj;//接收消息
                    Log.e("MainActivity", new String(TcpReadData) );//打印消息
                }catch (Exception e){}

            }
            else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9
                try{ socket.close(); }catch (Exception e){} //關閉鏈接
                try{ inputStream.close(); }catch (Exception e){} //關閉鏈接
                buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
                Log.e("MainActivity", "和服務器斷開鏈接!!!" );//打印消息
            }
        }
    }
}

 

如今作一下發送和接收數據的頁面字體

 

 

 點擊這個,改成百分比

 

 

拖到50%

 

 

 

 

我更改了背景色,和顯示字體的顏色

 

 

 

 

 

 

 

 

 

 

 

如今把接收的數據顯示出來

 

 

 

 

 測試

 

 

 

 

如今作一個顯示16進制和字符串切換的

 

 

 

 其實咱接收過來的就是16進制,咱須要把16進制轉化爲16進制字符串

/**
     * 16進制byte轉16進制String--用空格隔開
     * @param bytes
     * @return
     */
    public static String byteToHexStr(byte[] bytes)
    {    
        String str_msg = "";
        for (int i = 0; i < bytes.length; i++){    
            str_msg = str_msg + String.format("%02X",bytes[i])+" ";
        }    
        return str_msg;    
    }  

 

 

 測試

 

    

 

 

 

 

 

 

 

 

 不過看一下,在這個位置顯示的...咱修改下

 

 

 

 

 

 

 

 首先說一點

 

 發送數據都是給個數組

因此

 

 

 

 

 

 

 添加上格式

實際上咱獲取的文本框裏面的都是字符串

咱須要把字符串轉化爲    列如: "33"   ==>  0x33

 

/** 
     * 將已十六進制編碼後的字符串src,以每兩個字符分割轉換爲16進制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF, 
     * 0xD9} 
     * 
     * @param src 
     *            String 
     * @return byte[] 
     */ 
    public static byte[] HexString2Bytes(String str) { 
        StringBuilder sb = null;
        String src = null;
        if ((str.length()%2)!=0) {//數據不是偶數
            sb = new StringBuilder(str);//構造一個StringBuilder對象
            sb.insert(str.length()-1, "0");//在指定的位置1,插入指定的字符串
            src = sb.toString();
        }
        else {
            src = str;
        }
        Log.e("error", "str.length()"+str.length());
        byte[] ret = new byte[src.length() / 2]; 
        byte[] tmp = src.getBytes(); 
        for (int i = 0; i < tmp.length / 2; i++) 
        { 
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]); 
        } 
        return ret; 
    } 
    
    
    /** 
     * 將兩個ASCII字符合成一個字節; 如:"EF"--> 0xEF 
     * 
     * @param src0 
     *            byte 
     * @param src1 
     *            byte 
     * @return byte 
     */ 
    public static byte uniteBytes(byte src0, byte src1) { 
        try 
        {
            byte _b0 = Byte.decode("0x"+new String(new byte[] { src0 })) .byteValue(); 
            _b0 = (byte) (_b0 << 4); 
            byte _b1 = Byte.decode("0x"+new String(new byte[] { src1 })) .byteValue(); 
            byte ret = (byte) (_b0 ^ _b1); 
            return ret; 
        } catch (Exception e) {
            // TODO: handle exception
        }
        return 0;
    } 

 

 

 

 

 

 

 

 

public class MainActivity extends AppCompatActivity {

    EditText editTextActivityMain1,editTextActivityMain2,editTextActivityMain3;//IP,端口號,發送數據框
    Button buttonActivityMain1,buttonActivityMain2,buttonActivityMain3;//鏈接按鈕,發送,清除接收
    TextView textViewActivityMain4;//接收文本
    CheckBox checkBoxActivityMain1,checkBoxActivityMain2;//切換顯示,發送格式選擇

    Socket socket;//定義一個Socket
    MyHandler myHandler;
    private OutputStream outputStream;//TCP發送數據使用
    private InputStream inputStream;//TCP接收數據使用
    byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據
    byte[] TcpSendData = new byte[1024];//用來緩存發送的數據
    int TcpSendDataLen =0;//發送的數據個數
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler();
        //獲取控件
        editTextActivityMain1 = findViewById(R.id.editTextActivityMain1);//IP
        editTextActivityMain2 = findViewById(R.id.editTextActivityMain2);//端口號
        editTextActivityMain3 = findViewById(R.id.editTextActivityMain3);//發送數據框
        buttonActivityMain1 = findViewById(R.id.buttonActivityMain1);//鏈接按鈕
        buttonActivityMain2 = findViewById(R.id.buttonActivityMain2);//發送數據
        buttonActivityMain3 = findViewById(R.id.buttonActivityMain3);//清除接收
        textViewActivityMain4 = findViewById(R.id.textViewActivityMain4);//接收數據文本
        checkBoxActivityMain1 = findViewById(R.id.checkBoxActivityMain1);//切換顯示
        checkBoxActivityMain2 = findViewById(R.id.checkBoxActivityMain2);//發送格式選擇

        buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接"

        //鏈接按鈕點擊事件
        buttonActivityMain1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonActivityMain1.getText().toString() == "鏈接"){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //這裏面寫具體的程序
                            try {
                                socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器
                                if (socket.isConnected()){//若是鏈接上TCP服務器
                                    Log.e("MainActivity", "isConnected");
                                    Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                                    msg.what = 1;//設置消息變量的 what 變量值 爲1
                                    myHandler.sendMessage(msg);//插入消息隊列

                                    outputStream = socket.getOutputStream();//獲取輸出數據流
                                    inputStream = socket.getInputStream();//獲取輸入數據流
                                    TcpClientReceive();//加載接收函數
                                }
                            }
                            catch (Exception e){
                                Log.e("MainActivity", e.toString());
                            }
                        }
                    }).start();
                }
                else {
                    try{ socket.close(); }catch (Exception e){} //關閉鏈接
                    try{ inputStream.close(); }catch (Exception e){} //關閉數據流
                    buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
                }
            }
        });

        //發送按鈕
        buttonActivityMain2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                    //獲取發送數據框裏面的數據
                    if (checkBoxActivityMain2.isChecked()){//16進制發送
                        byte[] TcpSendData1 = HexString2Bytes(editTextActivityMain3.getText().toString().replace(" ", ""));
                        TcpSendDataLen = TcpSendData1.length;
                        TcpSendData = TcpSendData1;
                    }
                    else{
                        byte[] TcpSendData2 = editTextActivityMain3.getText().toString().replace(" ", "").getBytes("utf-8");//"gb2312","gbk","us-ascii"
                        TcpSendDataLen = TcpSendData2.length;
                        TcpSendData = TcpSendData2;
                    }
                    if (socket!=null && socket.isConnected()){//若是TCP是正常鏈接的
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try{
                                    outputStream.write(TcpSendData,0,TcpSendDataLen);//發送數據
                                }catch (Exception e){}
                            }
                        }).start();
                    }
                }catch (Exception  e){}
            }
        });
    }

    //TCP客戶端接收數據
    public void TcpClientReceive(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面
                    try{
                        int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1

                        if(TcpReceiveDataLen!=-1){
                            byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組
                            System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 2;//設置消息變量
                            msg.obj = Buffer;//obj 能夠接收任意類型的變量
                            myHandler.sendMessage(msg);//插入消息隊列
                        }
                        else{//斷開了鏈接
                            Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                            msg.what = 9;//設置消息變量
                            myHandler.sendMessage(msg);//插入消息隊列
                            break;
                        }
                    }catch (Exception e){//接收數據有錯誤
                        Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量
                        msg.what = 9;//設置消息變量
                        myHandler.sendMessage(msg);//插入消息隊列
                        break;
                    }
                }
            }
        }).start();
    }



    //Handler
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1){//接收到消息變量的 what 變量值 爲1
                buttonActivityMain1.setText("斷開");//按鈕顯示斷開
            }
            else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2
                try{
                    byte[] TcpReadData = (byte[])msg.obj;//接收消息
                    if (checkBoxActivityMain1.isChecked()){//選擇了顯示16進制
                        textViewActivityMain4.append(byteToHexStr(TcpReadData));
                    }
                    else {
                        textViewActivityMain4.append(new String(TcpReadData,"utf-8"));//追加顯示數據 "utf-8","gb2312","gbk","us-ascii"  參見:https://www.cnblogs.com/yangfengwu/p/10274289.html
                    }
                    //textViewActivityMain4.setText(new String(TcpReadData));//顯示一次數據從新刷新顯示
                    Log.e("MainActivity", new String(TcpReadData) );//打印消息
                }catch (Exception e){}

            }
            else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9
                try{ socket.close(); }catch (Exception e){} //關閉鏈接
                try{ inputStream.close(); }catch (Exception e){} //關閉鏈接
                buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接
                Log.e("MainActivity", "和服務器斷開鏈接!!!" );//打印消息
            }
        }
    }


    /**
     * 16進制byte轉16進制String--用空格隔開
     * @param bytes
     * @return
     */
    public static String byteToHexStr(byte[] bytes)
    {
        String str_msg = "";
        for (int i = 0; i < bytes.length; i++){
            str_msg = str_msg + String.format("%02X",bytes[i])+" ";
        }
        return str_msg;
    }


    /**
     * 將已十六進制編碼後的字符串src,以每兩個字符分割轉換爲16進制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,
     * 0xD9}
     *
     * @param src
     *            String
     * @return byte[]
     */
    public static byte[] HexString2Bytes(String str) {
        StringBuilder sb = null;
        String src = null;
        if ((str.length()%2)!=0) {//數據不是偶數
            sb = new StringBuilder(str);//構造一個StringBuilder對象
            sb.insert(str.length()-1, "0");//在指定的位置1,插入指定的字符串
            src = sb.toString();
        }
        else {
            src = str;
        }
        Log.e("error", "str.length()"+str.length());
        byte[] ret = new byte[src.length() / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < tmp.length / 2; i++)
        {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }


    /**
     * 將兩個ASCII字符合成一個字節; 如:"EF"--> 0xEF
     *
     * @param src0
     *            byte
     * @param src1
     *            byte
     * @return byte
     */
    public static byte uniteBytes(byte src0, byte src1) {
        try
        {
            byte _b0 = Byte.decode("0x"+new String(new byte[] { src0 })) .byteValue();
            _b0 = (byte) (_b0 << 4);
            byte _b1 = Byte.decode("0x"+new String(new byte[] { src1 })) .byteValue();
            byte ret = (byte) (_b0 ^ _b1);
            return ret;
        } catch (Exception e) {
            // TODO: handle exception
        }
        return 0;
    }
}

測試

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相關文章
相關標籤/搜索